diff --git a/.github/build.in.yml b/.github/build.in.yml index 7a5fc57e42d7b..3facc8b60a92b 100644 --- a/.github/build.in.yml +++ b/.github/build.in.yml @@ -133,8 +133,8 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init - lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + lake exe cache get #Mathlib.Init + #lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean id: mk_all @@ -278,7 +278,7 @@ jobs: # Output is posted to the zulip topic # https://leanprover.zulipchat.com/#narrow/stream/345428-mathlib-reviewers/topic/lean4checker - - name: Post comments for lean-pr-testing branch + - name: Post comments for lean-pr-testing-NNNN and batteries-pr-testing-NNNN branches if: always() env: TOKEN: ${{ secrets.LEAN_PR_TESTING }} @@ -291,7 +291,8 @@ jobs: LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} run: | - scripts/lean-pr-testing-comments.sh + scripts/lean-pr-testing-comments.sh lean + scripts/lean-pr-testing-comments.sh batteries final: name: Post-CI jobJOB_NAME diff --git a/.github/workflows/PR_summary.yml b/.github/workflows/PR_summary.yml index 25529d869f64b..bbde4ace8c7e5 100644 --- a/.github/workflows/PR_summary.yml +++ b/.github/workflows/PR_summary.yml @@ -55,12 +55,27 @@ jobs: PR="${{ github.event.pull_request.number }}" title="### PR summary" + graphAndHighPercentReports=$(python ./scripts/import-graph-report.py base.json head.json changed_files.txt) + ## Import count comment importCount=$( - python ./scripts/import-graph-report.py base.json head.json changed_files.txt + printf '%s\n' "${graphAndHighPercentReports}" | sed '/^Import changes exceeding/Q' ./scripts/import_trans_difference.sh ) + ## High percentage imports + high_percentages=$( + printf '%s\n' "${graphAndHighPercentReports}" | sed -n '/^Import changes exceeding/,$p' + ) + # if there are files with large increase in transitive imports, then we add the `large-import` label + if [ -n "${high_percentages}" ] + then + high_percentages=$'\n\n'"${high_percentages}" + gh pr edit "${PR}" --add-label large-import + else # otherwise, we remove the label + gh pr edit "${PR}" --remove-label large-import + fi + if [ "$(printf '%s' "${importCount}" | wc -l)" -gt 12 ] then importCount="$(printf '
\n\n%s\n\n\n\n%s\n\n
\n' "#### Import changes for modified files" "${importCount}")" @@ -80,6 +95,6 @@ jobs: currentHash="$(git rev-parse HEAD)" hashURL="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}/commits/${currentHash}" - message="$(printf '%s [%s](%s)\n\n%s\n\n---\n\n%s\n' "${title}" "$(git rev-parse --short HEAD)" "${hashURL}" "${importCount}" "${declDiff}")" + message="$(printf '%s [%s](%s)%s\n\n%s\n\n---\n\n%s\n' "${title}" "$(git rev-parse --short HEAD)" "${hashURL}" "${high_percentages}" "${importCount}" "${declDiff}")" ./scripts/update_PR_comment.sh "${message}" "${title}" "${PR}" diff --git a/.github/workflows/add_label_from_diff.yaml b/.github/workflows/add_label_from_diff.yaml new file mode 100644 index 0000000000000..271ac1b95ce59 --- /dev/null +++ b/.github/workflows/add_label_from_diff.yaml @@ -0,0 +1,42 @@ +name: Autolabel PRs + +on: + pull_request: + types: [opened] + push: + paths: + - scripts/autolabel.lean + - .github/workflows/add_label_from_diff.yaml + +jobs: + add_topic_label: + name: Add topic label + runs-on: ubuntu-latest + # Don't run on forks, where we wouldn't have permissions to add the label anyway. + if: github.repository == 'leanprover-community/mathlib4' + permissions: + issues: write + checks: write + pull-requests: write + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: install elan + run: | + set -o pipefail + curl -sSfL https://github.com/leanprover/elan/releases/download/v3.1.1/elan-x86_64-unknown-linux-gnu.tar.gz | tar xz + ./elan-init -y --default-toolchain none + echo "$HOME/.elan/bin" >> "${GITHUB_PATH}" + - name: lake exe autolabel + run: | + # the checkout dance, to avoid a detached head + git checkout master + git checkout - + lake exe autolabel "$NUMBER" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.number }} diff --git a/.github/workflows/bors.yml b/.github/workflows/bors.yml index 2d3b247327d23..207aee8482616 100644 --- a/.github/workflows/bors.yml +++ b/.github/workflows/bors.yml @@ -143,8 +143,8 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init - lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + lake exe cache get #Mathlib.Init + #lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean id: mk_all @@ -288,7 +288,7 @@ jobs: # Output is posted to the zulip topic # https://leanprover.zulipchat.com/#narrow/stream/345428-mathlib-reviewers/topic/lean4checker - - name: Post comments for lean-pr-testing branch + - name: Post comments for lean-pr-testing-NNNN and batteries-pr-testing-NNNN branches if: always() env: TOKEN: ${{ secrets.LEAN_PR_TESTING }} @@ -301,7 +301,8 @@ jobs: LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} run: | - scripts/lean-pr-testing-comments.sh + scripts/lean-pr-testing-comments.sh lean + scripts/lean-pr-testing-comments.sh batteries final: name: Post-CI job diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 245362dfe5d7c..c47cd306ed4da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -150,8 +150,8 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init - lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + lake exe cache get #Mathlib.Init + #lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean id: mk_all @@ -295,7 +295,7 @@ jobs: # Output is posted to the zulip topic # https://leanprover.zulipchat.com/#narrow/stream/345428-mathlib-reviewers/topic/lean4checker - - name: Post comments for lean-pr-testing branch + - name: Post comments for lean-pr-testing-NNNN and batteries-pr-testing-NNNN branches if: always() env: TOKEN: ${{ secrets.LEAN_PR_TESTING }} @@ -308,7 +308,8 @@ jobs: LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} run: | - scripts/lean-pr-testing-comments.sh + scripts/lean-pr-testing-comments.sh lean + scripts/lean-pr-testing-comments.sh batteries final: name: Post-CI job diff --git a/.github/workflows/build_fork.yml b/.github/workflows/build_fork.yml index 5c3fa8a2099b1..c431ad5e7d2f2 100644 --- a/.github/workflows/build_fork.yml +++ b/.github/workflows/build_fork.yml @@ -147,8 +147,8 @@ jobs: run: | rm -rf .lake/build/lib/Mathlib/ # Fail quickly if the cache is completely cold, by checking for Mathlib.Init - lake exe cache get Mathlib.Init - lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" + lake exe cache get #Mathlib.Init + #lake build --no-build Mathlib.Init && lake exe cache get || echo "No cache for 'Mathlib.Init' available" - name: update {Mathlib, Tactic, Counterexamples, Archive}.lean id: mk_all @@ -292,7 +292,7 @@ jobs: # Output is posted to the zulip topic # https://leanprover.zulipchat.com/#narrow/stream/345428-mathlib-reviewers/topic/lean4checker - - name: Post comments for lean-pr-testing branch + - name: Post comments for lean-pr-testing-NNNN and batteries-pr-testing-NNNN branches if: always() env: TOKEN: ${{ secrets.LEAN_PR_TESTING }} @@ -305,7 +305,8 @@ jobs: LINT_OUTCOME: ${{ steps.lint.outcome }} TEST_OUTCOME: ${{ steps.test.outcome }} run: | - scripts/lean-pr-testing-comments.sh + scripts/lean-pr-testing-comments.sh lean + scripts/lean-pr-testing-comments.sh batteries final: name: Post-CI job (fork) diff --git a/.github/workflows/lean4checker.yml b/.github/workflows/lean4checker.yml index 8405cde825320..8976cc19badb6 100644 --- a/.github/workflows/lean4checker.yml +++ b/.github/workflows/lean4checker.yml @@ -70,7 +70,7 @@ jobs: run: | git clone https://github.com/leanprover/lean4checker cd lean4checker - git checkout v4.12.0-rc1 + git checkout v4.13.0-rc3 # Now that the git hash is embedded in each olean, # we need to compile lean4checker on the same toolchain cp ../lean-toolchain . diff --git a/.github/workflows/nightly_detect_failure.yml b/.github/workflows/nightly_detect_failure.yml index e1cfd9147086b..25835698e99ab 100644 --- a/.github/workflows/nightly_detect_failure.yml +++ b/.github/workflows/nightly_detect_failure.yml @@ -23,6 +23,7 @@ jobs: topic: 'Mathlib status updates' content: | ❌ The latest CI for Mathlib's branch#nightly-testing has [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) ([${{ github.sha }}](https://github.com/${{ github.repository }}/commit/${{ github.sha }})). + You can `git fetch; git checkout nightly-testing` and push a fix. handle_success: if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'nightly-testing' }} @@ -210,26 +211,15 @@ jobs: bump_branch_suffix = bump_branch.replace('bump/', '') payload = f"🛠️: it looks like it's time to create a new bump/nightly-{current_version} branch from nightly-testing (specifically {sha}), and then PR that to {bump_branch}. " payload += "To do so semi-automatically, run the following script from mathlib root:\n\n" - payload += f"```bash\n./scripts/create-adaptation-pr.sh {bump_branch_suffix} {current_version}\n```\n" - # Only post if the message is different - # We compare the first 160 characters, since that includes the date and bump version - if not messages or messages[0]['content'][:160] != payload[:160]: - # Log messages, because the bot seems to repeat itself... - if messages: - print("###### Last message:") - print(messages[0]['content']) - print("###### Current message:") - print(payload) - else: - print('The strings match!') - # Post the reminder message - request = { - 'type': 'stream', - 'to': 'nightly-testing', - 'topic': 'Mathlib bump branch reminders', - 'content': payload - } - result = client.send_message(request) - print(result) + payload += f"```bash\n./scripts/create-adaptation-pr.sh --bumpversion={bump_branch_suffix} --nightlydate={current_version} --nightlysha={sha}\n```\n" + # Post the reminder message + request = { + 'type': 'stream', + 'to': 'nightly-testing', + 'topic': 'Mathlib bump branch reminders', + 'content': payload + } + result = client.send_message(request) + print(result) else: print('No action needed.') diff --git a/.github/workflows/update_dependencies_zulip.yml b/.github/workflows/update_dependencies_zulip.yml index 1f8a3b507374b..f4e72b01d7034 100644 --- a/.github/workflows/update_dependencies_zulip.yml +++ b/.github/workflows/update_dependencies_zulip.yml @@ -40,7 +40,7 @@ jobs: }); } } else { - output += "No PR found for this run!"; + output += "No PR found for this run! If you are feeling impatient and have write access, please go to the following page and click the "Run workflow" button!\nhttps://github.com/leanprover-community/mathlib4/actions/workflows/update_dependencies.yml"; } return output; diff --git a/.vscode/deprecated-alias.code-snippets b/.vscode/deprecated.code-snippets similarity index 53% rename from .vscode/deprecated-alias.code-snippets rename to .vscode/deprecated.code-snippets index c760b46045763..8be8e537cd5f0 100644 --- a/.vscode/deprecated-alias.code-snippets +++ b/.vscode/deprecated.code-snippets @@ -1,4 +1,11 @@ { + "Deprecation for mathlib": { + "scope": "lean4", + "prefix": "deprecated", + "body": [ + "@[deprecated $1 (since := \"${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}\")]" + ] + }, "Deprecated alias for mathlib": { "scope": "lean4", "prefix": "deprecated alias", diff --git a/Archive/Examples/IfNormalization/Result.lean b/Archive/Examples/IfNormalization/Result.lean index ef69269689c77..30ac2f21636cd 100644 --- a/Archive/Examples/IfNormalization/Result.lean +++ b/Archive/Examples/IfNormalization/Result.lean @@ -54,7 +54,7 @@ We don't want a `simp` lemma for `(ite i t e).eval` in general, only once we kno `e` to the literal booleans given by `l` -/ def normalize (l : AList (fun _ : ℕ => Bool)) : (e : IfExpr) → { e' : IfExpr // - (∀ f, e'.eval f = e.eval (fun w => (l.lookup w).elim (f w) (fun b => b))) + (∀ f, e'.eval f = e.eval (fun w => (l.lookup w).elim (f w) id)) ∧ e'.normalized ∧ ∀ (v : ℕ), v ∈ vars e' → l.lookup v = none } | lit b => ⟨lit b, ◾⟩ diff --git a/Archive/Examples/IfNormalization/WithoutAesop.lean b/Archive/Examples/IfNormalization/WithoutAesop.lean index 1ac14973a5106..0f376cdbd1590 100644 --- a/Archive/Examples/IfNormalization/WithoutAesop.lean +++ b/Archive/Examples/IfNormalization/WithoutAesop.lean @@ -36,7 +36,7 @@ theorem eval_ite_ite' {a b c d e : IfExpr} {f : ℕ → Bool} : `e` to the literal booleans given by `l` -/ def normalize' (l : AList (fun _ : ℕ => Bool)) : (e : IfExpr) → { e' : IfExpr // - (∀ f, e'.eval f = e.eval (fun w => (l.lookup w).elim (f w) (fun b => b))) + (∀ f, e'.eval f = e.eval (fun w => (l.lookup w).elim (f w) id)) ∧ e'.normalized ∧ ∀ (v : ℕ), v ∈ vars e' → l.lookup v = none } | lit b => ⟨lit b, by simp⟩ @@ -92,8 +92,8 @@ def normalize' (l : AList (fun _ : ℕ => Bool)) : · simp_all · have := ht₃ v have := he₃ v - simp_all? says simp_all only [normalized, Bool.and_eq_true, Bool.not_eq_true', - AList.lookup_insert_eq_none, ne_eq, AList.lookup_insert] + simp_all? says simp_all only [normalized, Bool.and_eq_true, Bool.not_eq_eq_eq_not, + Bool.not_true, AList.lookup_insert_eq_none, ne_eq, AList.lookup_insert] obtain ⟨⟨⟨tn, tc⟩, tr⟩, td⟩ := ht₂ split <;> rename_i h' · subst h' @@ -103,9 +103,9 @@ def normalize' (l : AList (fun _ : ℕ => Bool)) : have := he₃ w by_cases h : w = v · subst h; simp_all - · simp_all? says simp_all only [normalized, Bool.and_eq_true, Bool.not_eq_true', - AList.lookup_insert_eq_none, ne_eq, not_false_eq_true, AList.lookup_insert_ne, - implies_true] + · simp_all? says simp_all only [normalized, Bool.and_eq_true, Bool.not_eq_eq_eq_not, + Bool.not_true, AList.lookup_insert_eq_none, ne_eq, not_false_eq_true, + AList.lookup_insert_ne, implies_true] obtain ⟨⟨⟨en, ec⟩, er⟩, ed⟩ := he₂ split at b <;> rename_i h' · subst h'; simp_all diff --git a/Archive/Hairer.lean b/Archive/Hairer.lean index acd326c0b13bf..e9b91c32132a8 100644 --- a/Archive/Hairer.lean +++ b/Archive/Hairer.lean @@ -100,7 +100,7 @@ lemma inj_L : Injective (L ι) := fun g hg _h2g g_supp ↦ by simpa [mul_comm (g _), L] using congr($hp ⟨g, g_supp.trans ball_subset_closedBall, hg⟩) simp_rw [MvPolynomial.funext_iff, map_zero] - refine fun x ↦ AnalyticOn.eval_linearMap (EuclideanSpace.equiv ι ℝ).toLinearMap p + refine fun x ↦ AnalyticOnNhd.eval_linearMap (EuclideanSpace.equiv ι ℝ).toLinearMap p |>.eqOn_zero_of_preconnected_of_eventuallyEq_zero (preconnectedSpace_iff_univ.mp inferInstance) (z₀ := 0) trivial (Filter.mem_of_superset (Metric.ball_mem_nhds 0 zero_lt_one) ?_) trivial diff --git a/Archive/Imo/Imo1962Q1.lean b/Archive/Imo/Imo1962Q1.lean index dd0ef63d96b8b..d151c6df95fc3 100644 --- a/Archive/Imo/Imo1962Q1.lean +++ b/Archive/Imo/Imo1962Q1.lean @@ -107,7 +107,7 @@ lemma case_more_digits {c n : ℕ} (hc : (digits 10 c).length ≥ 6) (hpp : Prob calc n ≥ 10 * c := le.intro hpp.left.symm _ ≥ 10 ^ (digits 10 c).length := base_pow_length_digits_le 10 c (by decide) hnz - _ ≥ 10 ^ 6 := pow_le_pow_right (by decide) hc + _ ≥ 10 ^ 6 := pow_right_mono₀ (by decide) hc _ ≥ 153846 := by norm_num /-! diff --git a/Archive/Imo/Imo1972Q5.lean b/Archive/Imo/Imo1972Q5.lean index f96965f9d6a75..ba2e4d8c6a0a0 100644 --- a/Archive/Imo/Imo1972Q5.lean +++ b/Archive/Imo/Imo1972Q5.lean @@ -50,7 +50,7 @@ theorem imo1972_q5 (f g : ℝ → ℝ) (hf1 : ∀ x, ∀ y, f (x + y) + f (x - y calc 0 < ‖f x‖ := norm_pos_iff.mpr hx _ ≤ k := hk₁ x - rw [div_lt_iff] + rw [div_lt_iff₀] · apply lt_mul_of_one_lt_right h₁ hneg · exact zero_lt_one.trans hneg -- Demonstrate that `k ≤ k'` using `hk₂`. @@ -87,7 +87,7 @@ theorem imo1972_q5' (f g : ℝ → ℝ) (hf1 : ∀ x, ∀ y, f (x + y) + f (x - have h : ∀ x, ‖f x‖ ≤ k := le_ciSup hf2 have hgy : 0 < ‖g y‖ := by linarith have k_pos : 0 < k := lt_of_lt_of_le (norm_pos_iff.mpr hx) (h x) - have : k / ‖g y‖ < k := (div_lt_iff hgy).mpr (lt_mul_of_one_lt_right k_pos H) + have : k / ‖g y‖ < k := (div_lt_iff₀ hgy).mpr (lt_mul_of_one_lt_right k_pos H) have : k ≤ k / ‖g y‖ := by suffices ∀ x, ‖f x‖ ≤ k / ‖g y‖ from ciSup_le this intro x diff --git a/Archive/Imo/Imo1986Q5.lean b/Archive/Imo/Imo1986Q5.lean index 6789efcbb837d..82fe5961c1647 100644 --- a/Archive/Imo/Imo1986Q5.lean +++ b/Archive/Imo/Imo1986Q5.lean @@ -54,7 +54,7 @@ theorem map_of_lt_two (hx : x < 2) : f x = 2 / (2 - x) := by have hx' : 0 < 2 - x := tsub_pos_of_lt hx have hfx : f x ≠ 0 := hf.map_ne_zero_iff.2 hx apply le_antisymm - · rw [le_div_iff₀ hx', ← NNReal.le_div_iff' hfx, tsub_le_iff_right, ← hf.map_eq_zero, + · rw [le_div_iff₀ hx', ← le_div_iff₀' hfx.bot_lt, tsub_le_iff_right, ← hf.map_eq_zero, hf.map_add, div_mul_cancel₀ _ hfx, hf.map_two, zero_mul] · rw [div_le_iff₀' hx', ← hf.map_eq_zero] refine (mul_eq_zero.1 ?_).resolve_right hfx diff --git a/Archive/Imo/Imo2006Q5.lean b/Archive/Imo/Imo2006Q5.lean index 0e2398d7919ba..d317993a8c618 100644 --- a/Archive/Imo/Imo2006Q5.lean +++ b/Archive/Imo/Imo2006Q5.lean @@ -122,7 +122,7 @@ theorem Polynomial.iterate_comp_sub_X_ne {P : Polynomial ℤ} (hP : 1 < P.natDeg (hk : 0 < k) : P.comp^[k] X - X ≠ 0 := by rw [sub_ne_zero] apply_fun natDegree - simpa using (one_lt_pow hP hk.ne').ne' + simpa using (one_lt_pow₀ hP hk.ne').ne' /-- We solve the problem for the specific case k = 2 first. -/ theorem imo2006_q5' {P : Polynomial ℤ} (hP : 1 < P.natDegree) : diff --git a/Archive/Imo/Imo2013Q5.lean b/Archive/Imo/Imo2013Q5.lean index 48e7486e9c230..225e64ae35b02 100644 --- a/Archive/Imo/Imo2013Q5.lean +++ b/Archive/Imo/Imo2013Q5.lean @@ -38,9 +38,9 @@ theorem le_of_all_pow_lt_succ {x y : ℝ} (hx : 1 < x) (hy : 1 < y) have hterm : ∀ i : ℕ, i ∈ Finset.range n → 1 ≤ x ^ i * y ^ (n - 1 - i) := by intro i _ calc - 1 ≤ x ^ i := one_le_pow_of_one_le hx.le i + 1 ≤ x ^ i := one_le_pow₀ hx.le _ = x ^ i * 1 := by ring - _ ≤ x ^ i * y ^ (n - 1 - i) := by gcongr; apply one_le_pow_of_one_le hy.le + _ ≤ x ^ i * y ^ (n - 1 - i) := by gcongr; apply one_le_pow₀ hy.le calc (x - y) * (n : ℝ) = (n : ℝ) * (x - y) := by ring _ = (∑ _i ∈ Finset.range n, (1 : ℝ)) * (x - y) := by @@ -134,7 +134,7 @@ theorem fixed_point_of_pos_nat_pow {f : ℚ → ℝ} {n : ℕ} (hn : 0 < n) (H1 : ∀ x y, 0 < x → 0 < y → f (x * y) ≤ f x * f y) (H4 : ∀ n : ℕ, 0 < n → (n : ℝ) ≤ f n) (H5 : ∀ x : ℚ, 1 < x → (x : ℝ) ≤ f x) {a : ℚ} (ha1 : 1 < a) (hae : f a = a) : f (a ^ n) = a ^ n := by - have hh0 : (a : ℝ) ^ n ≤ f (a ^ n) := mod_cast H5 (a ^ n) (one_lt_pow ha1 hn.ne') + have hh0 : (a : ℝ) ^ n ≤ f (a ^ n) := mod_cast H5 (a ^ n) (one_lt_pow₀ ha1 hn.ne') have hh1 := calc f (a ^ n) ≤ f a ^ n := pow_f_le_f_pow hn ha1 H1 H4 @@ -206,7 +206,7 @@ theorem imo2013_q5 (f : ℚ → ℝ) (H1 : ∀ x y, 0 < x → 0 < y → f (x * y intro n hn calc (x : ℝ) ^ n - 1 < f (x ^ n) := - mod_cast fx_gt_xm1 (one_le_pow_of_one_le hx.le n) H1 H2 H4 + mod_cast fx_gt_xm1 (one_le_pow₀ hx.le) H1 H2 H4 _ ≤ f x ^ n := pow_f_le_f_pow hn hx H1 H4 have hx' : 1 < (x : ℝ) := mod_cast hx have hxp : 0 < x := by positivity diff --git a/Archive/Imo/Imo2019Q2.lean b/Archive/Imo/Imo2019Q2.lean index db1650a221391..86353bd5b6d91 100644 --- a/Archive/Imo/Imo2019Q2.lean +++ b/Archive/Imo/Imo2019Q2.lean @@ -57,7 +57,7 @@ rather than more literally with `affineSegment`. -/ -open Affine Affine.Simplex EuclideanGeometry FiniteDimensional +open Affine Affine.Simplex EuclideanGeometry Module open scoped Affine EuclideanGeometry Real diff --git a/Archive/Imo/Imo2021Q1.lean b/Archive/Imo/Imo2021Q1.lean index 8cb685761f6bb..051bea2e28ac9 100644 --- a/Archive/Imo/Imo2021Q1.lean +++ b/Archive/Imo/Imo2021Q1.lean @@ -10,7 +10,7 @@ import Mathlib.Tactic.Linarith /-! # IMO 2021 Q1 -Let `n≥100` be an integer. Ivan writes the numbers `n, n+1,..., 2n` each on different cards. +Let `n ≥ 100` be an integer. Ivan writes the numbers `n, n+1, ..., 2*n` each on different cards. He then shuffles these `n+1` cards, and divides them into two piles. Prove that at least one of the piles contains two cards such that the sum of their numbers is a perfect square. @@ -30,7 +30,7 @@ which can be solved to give b = 2 * l ^ 2 + 1 c = 2 * l ^ 2 + 4 * l -Therefore, it is enough to show that there exists a natural number l such that +Therefore, it is enough to show that there exists a natural number `l` such that `n ≤ 2 * l ^ 2 - 4 * l` and `2 * l ^ 2 + 4 * l ≤ 2 * n` for `n ≥ 100`. Then, by the Pigeonhole principle, at least two numbers in the triplet must lie in the same pile, @@ -41,13 +41,13 @@ open Finset namespace Imo2021Q1 --- We will later make use of the fact that there exists (l : ℕ) such that --- n ≤ 2 * l ^ 2 - 4 * l and 2 * l ^ 2 + 4 * l ≤ 2 * n for n ≥ 100. -theorem exists_numbers_in_interval (n : ℕ) (hn : 100 ≤ n) : +-- We will later make use of the fact that there exists `l : ℕ` such that +-- `n ≤ 2 * l ^ 2 - 4 * l` and `2 * l ^ 2 + 4 * l ≤ 2 * n` for `n ≥ 100`. +lemma exists_numbers_in_interval {n : ℕ} (hn : 100 ≤ n) : ∃ l : ℕ, n + 4 * l ≤ 2 * l ^ 2 ∧ 2 * l ^ 2 + 4 * l ≤ 2 * n := by have hn' : 1 ≤ Nat.sqrt (n + 1) := by rw [Nat.le_sqrt] - linarith + apply Nat.le_add_left have h₁ := Nat.sqrt_le' (n + 1) have h₂ := Nat.succ_le_succ_sqrt' (n + 1) have h₃ : 10 ≤ (n + 1).sqrt := by @@ -60,11 +60,11 @@ theorem exists_numbers_in_interval (n : ℕ) (hn : 100 ≤ n) : _ ≤ 2 * l ^ 2 := by nlinarith only [h₃] · linarith only [h₁] -theorem exists_triplet_summing_to_squares (n : ℕ) (hn : 100 ≤ n) : +lemma exists_triplet_summing_to_squares {n : ℕ} (hn : 100 ≤ n) : ∃ a b c : ℕ, n ≤ a ∧ a < b ∧ b < c ∧ c ≤ 2 * n ∧ - (∃ k : ℕ, a + b = k ^ 2) ∧ (∃ l : ℕ, c + a = l ^ 2) ∧ ∃ m : ℕ, b + c = m ^ 2 := by - obtain ⟨l, hl1, hl2⟩ := exists_numbers_in_interval n hn - have p : 1 < l := by contrapose! hl1; interval_cases l <;> linarith + IsSquare (a + b) ∧ IsSquare (c + a) ∧ IsSquare (b + c) := by + obtain ⟨l, hl1, hl2⟩ := exists_numbers_in_interval hn + have hl : 1 < l := by contrapose! hl1; interval_cases l <;> linarith have h₁ : 4 * l ≤ 2 * l ^ 2 := by linarith have h₂ : 1 ≤ 2 * l := by linarith refine ⟨2 * l ^ 2 - 4 * l, 2 * l ^ 2 + 1, 2 * l ^ 2 + 4 * l, ?_, ?_, ?_, @@ -74,15 +74,14 @@ theorem exists_triplet_summing_to_squares (n : ℕ) (hn : 100 ≤ n) : -- Since it will be more convenient to work with sets later on, we will translate the above claim -- to state that there always exists a set B ⊆ [n, 2n] of cardinality at least 3, such that each -- pair of pairwise unequal elements of B sums to a perfect square. -theorem exists_finset_3_le_card_with_pairs_summing_to_squares (n : ℕ) (hn : 100 ≤ n) : +lemma exists_finset_3_le_card_with_pairs_summing_to_squares {n : ℕ} (hn : 100 ≤ n) : ∃ B : Finset ℕ, 2 * 1 + 1 ≤ B.card ∧ - (∀ a ∈ B, ∀ b ∈ B, a ≠ b → ∃ k, a + b = k ^ 2) ∧ + (∀ a ∈ B, ∀ b ∈ B, a ≠ b → IsSquare (a + b)) ∧ ∀ c ∈ B, n ≤ c ∧ c ≤ 2 * n := by - obtain ⟨a, b, c, hna, hab, hbc, hcn, h₁, h₂, h₃⟩ := exists_triplet_summing_to_squares n hn + obtain ⟨a, b, c, hna, hab, hbc, hcn, h₁, h₂, h₃⟩ := exists_triplet_summing_to_squares hn refine ⟨{a, b, c}, ?_, ?_, ?_⟩ - · suffices ({a, b, c} : Finset ℕ).card = 3 by rw [this] - suffices a ∉ {b, c} ∧ b ∉ {c} by + · suffices a ∉ {b, c} ∧ b ∉ {c} by rw [Finset.card_insert_of_not_mem this.1, Finset.card_insert_of_not_mem this.2, Finset.card_singleton] rw [Finset.mem_insert, Finset.mem_singleton, Finset.mem_singleton] @@ -105,22 +104,20 @@ open Imo2021Q1 theorem imo2021_q1 : ∀ n : ℕ, 100 ≤ n → ∀ A ⊆ Finset.Icc n (2 * n), - (∃ a ∈ A, ∃ b ∈ A, a ≠ b ∧ ∃ k : ℕ, a + b = k ^ 2) ∨ - ∃ a ∈ Finset.Icc n (2 * n) \ A, ∃ b ∈ Finset.Icc n (2 * n) \ A, - a ≠ b ∧ ∃ k : ℕ, a + b = k ^ 2 := by + (∃ a ∈ A, ∃ b ∈ A, a ≠ b ∧ IsSquare (a + b)) ∨ + ∃ a ∈ Finset.Icc n (2 * n) \ A, ∃ b ∈ Finset.Icc n (2 * n) \ A, a ≠ b ∧ IsSquare (a + b) := by intro n hn A hA -- For each n ∈ ℕ such that 100 ≤ n, there exists a pairwise unequal triplet {a, b, c} ⊆ [n, 2n] -- such that all pairwise sums are perfect squares. In practice, it will be easier to use -- a finite set B ⊆ [n, 2n] such that all pairwise unequal pairs of B sum to a perfect square -- noting that B has cardinality greater or equal to 3, by the explicit construction of the -- triplet {a, b, c} before. - obtain ⟨B, hB, h₁, h₂⟩ := exists_finset_3_le_card_with_pairs_summing_to_squares n hn + obtain ⟨B, hB, h₁, h₂⟩ := exists_finset_3_le_card_with_pairs_summing_to_squares hn have hBsub : B ⊆ Finset.Icc n (2 * n) := by intro c hcB; simpa only [Finset.mem_Icc] using h₂ c hcB have hB' : 2 * 1 < (B ∩ (Finset.Icc n (2 * n) \ A) ∪ B ∩ A).card := by - rw [← inter_union_distrib_left, sdiff_union_self_eq_union, union_eq_left.2 hA, - inter_eq_left.2 hBsub] - exact Nat.succ_le_iff.mp hB + rwa [← inter_union_distrib_left, sdiff_union_self_eq_union, union_eq_left.2 hA, + inter_eq_left.2 hBsub, ← Nat.succ_le_iff] -- Since B has cardinality greater or equal to 3, there must exist a subset C ⊆ B such that -- for any A ⊆ [n, 2n], either C ⊆ A or C ⊆ [n, 2n] \ A and C has cardinality greater -- or equal to 2. diff --git a/Archive/Imo/Imo2024Q1.lean b/Archive/Imo/Imo2024Q1.lean index 0e94469d1e0d9..00575c6abc94a 100644 --- a/Archive/Imo/Imo2024Q1.lean +++ b/Archive/Imo/Imo2024Q1.lean @@ -71,7 +71,7 @@ lemma mem_Ico_one_of_mem_Ioo (h : α ∈ Set.Ioo 0 2) : α ∈ Set.Ico 1 2 := by by_contra! hn have hr : 1 < ⌈α⁻¹⌉₊ := by rw [Nat.lt_ceil] - exact_mod_cast one_lt_inv h0 hn + exact_mod_cast (one_lt_inv₀ h0).2 hn apply hr.ne' suffices ⌈α⁻¹⌉₊ = (1 : ℤ) from mod_cast this apply Int.eq_one_of_dvd_one (Int.zero_le_ofNat _) @@ -153,7 +153,7 @@ lemma not_condition_of_mem_Ioo {α : ℝ} (h : α ∈ Set.Ioo 0 2) : ¬Condition convert hna using 1 field_simp rw [sub_eq_add_neg, ← le_sub_iff_add_le', neg_le, neg_sub] at hna' - rw [le_inv (by linarith) (mod_cast hn), ← not_lt] at hna' + rw [le_inv_comm₀ (by linarith) (mod_cast hn), ← not_lt] at hna' apply hna' exact_mod_cast Nat.lt_floor_add_one (_ : ℝ) diff --git a/Archive/Sensitivity.lean b/Archive/Sensitivity.lean index 3ebec47f3b7d6..5cae8d062537c 100644 --- a/Archive/Sensitivity.lean +++ b/Archive/Sensitivity.lean @@ -41,7 +41,7 @@ noncomputable section local notation "√" => Real.sqrt -open Function Bool LinearMap Fintype FiniteDimensional Module.DualBases +open Function Bool LinearMap Fintype Module Module.DualBases /-! ### The hypercube @@ -374,7 +374,7 @@ theorem exists_eigenvalue (H : Set (Q m.succ)) (hH : Card H ≥ 2 ^ m + 1) : suffices 0 < dim (W ⊓ img) by exact mod_cast exists_mem_ne_zero_of_rank_pos this have dim_le : dim (W ⊔ img) ≤ 2 ^ (m + 1 : Cardinal) := by - convert ← rank_submodule_le (W ⊔ img) + convert ← Submodule.rank_le (W ⊔ img) rw [← Nat.cast_succ] apply dim_V have dim_add : dim (W ⊔ img) + dim (W ⊓ img) = dim W + 2 ^ m := by diff --git a/Archive/Wiedijk100Theorems/AbelRuffini.lean b/Archive/Wiedijk100Theorems/AbelRuffini.lean index df179eb859924..36026dc2ddd76 100644 --- a/Archive/Wiedijk100Theorems/AbelRuffini.lean +++ b/Archive/Wiedijk100Theorems/AbelRuffini.lean @@ -115,7 +115,7 @@ theorem real_roots_Phi_ge_aux (hab : b < a) : · have hf1 : f 1 < 0 := by simp [hf, hb] have hfa : 0 ≤ f a := by simp_rw [hf, ← sq] - refine add_nonneg (sub_nonneg.mpr (pow_le_pow_right ha ?_)) ?_ <;> norm_num + refine add_nonneg (sub_nonneg.mpr (pow_right_mono₀ ha ?_)) ?_ <;> norm_num obtain ⟨x, ⟨-, hx1⟩, hx2⟩ := intermediate_value_Ico' hle (hc _) (Set.mem_Ioc.mpr ⟨hf1, hf0⟩) obtain ⟨y, ⟨hy1, -⟩, hy2⟩ := intermediate_value_Ioc ha (hc _) (Set.mem_Ioc.mpr ⟨hf1, hfa⟩) exact ⟨x, y, (hx1.trans hy1).ne, hx2, hy2⟩ @@ -126,7 +126,7 @@ theorem real_roots_Phi_ge_aux (hab : b < a) : f (-a) = (a : ℝ) ^ 2 - (a : ℝ) ^ 5 + b := by norm_num [hf, ← sq, sub_eq_add_neg, add_comm, Odd.neg_pow (by decide : Odd 5)] _ ≤ (a : ℝ) ^ 2 - (a : ℝ) ^ 3 + (a - 1) := by - refine add_le_add (sub_le_sub_left (pow_le_pow_right ha ?_) _) ?_ <;> linarith + refine add_le_add (sub_le_sub_left (pow_right_mono₀ ha ?_) _) ?_ <;> linarith _ = -((a : ℝ) - 1) ^ 2 * (a + 1) := by ring _ ≤ 0 := by nlinarith have ha' := neg_nonpos.mpr (hle.trans ha) diff --git a/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean b/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean index f4dbb1df5644d..df05d9256c5a5 100644 --- a/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean +++ b/Archive/Wiedijk100Theorems/AscendingDescendingSequences.lean @@ -3,6 +3,7 @@ Copyright (c) 2020 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta -/ +import Mathlib.Data.Finset.Max import Mathlib.Data.Fintype.Powerset /-! diff --git a/Archive/Wiedijk100Theorems/BallotProblem.lean b/Archive/Wiedijk100Theorems/BallotProblem.lean index 5d22c4ad829b2..3fd05ee140379 100644 --- a/Archive/Wiedijk100Theorems/BallotProblem.lean +++ b/Archive/Wiedijk100Theorems/BallotProblem.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Bhavik Mehta, Kexing Ying. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta, Kexing Ying -/ -import Mathlib.Probability.CondCount +import Mathlib.Probability.UniformOn /-! # Ballot problem @@ -188,21 +188,21 @@ theorem count_countedSequence : ∀ p q : ℕ, count (countedSequence p q) = (p theorem first_vote_pos : ∀ p q, - 0 < p + q → condCount (countedSequence p q : Set (List ℤ)) {l | l.headI = 1} = p / (p + q) + 0 < p + q → uniformOn (countedSequence p q : Set (List ℤ)) {l | l.headI = 1} = p / (p + q) | p + 1, 0, _ => by - rw [counted_right_zero, condCount_singleton] + rw [counted_right_zero, uniformOn_singleton] simp [ENNReal.div_self _ _, List.replicate_succ] | 0, q + 1, _ => by - rw [counted_left_zero, condCount_singleton] + rw [counted_left_zero, uniformOn_singleton] simp only [List.replicate, Nat.add_eq, add_zero, mem_setOf_eq, List.headI_cons, Nat.cast_zero, ENNReal.zero_div, ite_eq_right_iff] decide | p + 1, q + 1, _ => by simp_rw [counted_succ_succ] - rw [← condCount_disjoint_union ((countedSequence_finite _ _).image _) + rw [← uniformOn_disjoint_union ((countedSequence_finite _ _).image _) ((countedSequence_finite _ _).image _) (disjoint_bits _ _), ← counted_succ_succ, - condCount_eq_one_of ((countedSequence_finite p (q + 1)).image _) + uniformOn_eq_one_of ((countedSequence_finite p (q + 1)).image _) ((countedSequence_nonempty _ _).image _)] · have : List.cons (-1) '' countedSequence (p + 1) q ∩ {l : List ℤ | l.headI = 1} = ∅ := by ext @@ -215,7 +215,7 @@ theorem first_vote_pos : List.cons 1 '' countedSequence p (q + 1) := by rw [inter_eq_right, counted_succ_succ] exact subset_union_left - rw [(condCount_eq_zero_iff <| (countedSequence_finite _ _).image _).2 this, condCount, + rw [(uniformOn_eq_zero_iff <| (countedSequence_finite _ _).image _).2 this, uniformOn, cond_apply _ list_int_measurableSet, hint, count_injective_image List.cons_injective, count_countedSequence, count_countedSequence, one_mul, zero_mul, add_zero, Nat.cast_add, Nat.cast_one, mul_comm, ← div_eq_mul_inv, ENNReal.div_eq_div_iff] @@ -230,17 +230,17 @@ theorem headI_mem_of_nonempty {α : Type*} [Inhabited α] : ∀ {l : List α} (_ | x::l, _ => List.mem_cons_self x l theorem first_vote_neg (p q : ℕ) (h : 0 < p + q) : - condCount (countedSequence p q) {l | l.headI = 1}ᶜ = q / (p + q) := by + uniformOn (countedSequence p q) {l | l.headI = 1}ᶜ = q / (p + q) := by have h' : (p + q : ℝ≥0∞) ≠ 0 := mod_cast h.ne' - have := condCount_compl + have := uniformOn_compl {l : List ℤ | l.headI = 1}ᶜ (countedSequence_finite p q) (countedSequence_nonempty p q) rw [compl_compl, first_vote_pos _ _ h] at this - rw [← ENNReal.sub_eq_of_add_eq _ this, ENNReal.eq_div_iff, ENNReal.mul_sub, mul_one, + rw [ENNReal.eq_sub_of_add_eq _ this, ENNReal.eq_div_iff, ENNReal.mul_sub, mul_one, ENNReal.mul_div_cancel', ENNReal.add_sub_cancel_left] all_goals simp_all [ENNReal.div_eq_top] -theorem ballot_same (p : ℕ) : condCount (countedSequence (p + 1) (p + 1)) staysPositive = 0 := by - rw [condCount_eq_zero_iff (countedSequence_finite _ _), eq_empty_iff_forall_not_mem] +theorem ballot_same (p : ℕ) : uniformOn (countedSequence (p + 1) (p + 1)) staysPositive = 0 := by + rw [uniformOn_eq_zero_iff (countedSequence_finite _ _), eq_empty_iff_forall_not_mem] rintro x ⟨hx, t⟩ apply ne_of_gt (t x _ x.suffix_refl) · simpa using sum_of_mem_countedSequence hx @@ -248,9 +248,9 @@ theorem ballot_same (p : ℕ) : condCount (countedSequence (p + 1) (p + 1)) stay rw [length_of_mem_countedSequence hx] exact Nat.add_pos_left (Nat.succ_pos _) _ -theorem ballot_edge (p : ℕ) : condCount (countedSequence (p + 1) 0) staysPositive = 1 := by +theorem ballot_edge (p : ℕ) : uniformOn (countedSequence (p + 1) 0) staysPositive = 1 := by rw [counted_right_zero] - refine condCount_eq_one_of (finite_singleton _) (singleton_nonempty _) ?_ + refine uniformOn_eq_one_of (finite_singleton _) (singleton_nonempty _) ?_ refine singleton_subset_iff.2 fun l hl₁ hl₂ => List.sum_pos _ (fun x hx => ?_) hl₁ rw [List.eq_of_mem_replicate (hl₂.mem hx)] norm_num @@ -267,9 +267,9 @@ theorem countedSequence_int_pos_counted_succ_succ (p q : ℕ) : norm_num theorem ballot_pos (p q : ℕ) : - condCount (countedSequence (p + 1) (q + 1) ∩ {l | l.headI = 1}) staysPositive = - condCount (countedSequence p (q + 1)) staysPositive := by - rw [countedSequence_int_pos_counted_succ_succ, condCount, condCount, + uniformOn (countedSequence (p + 1) (q + 1) ∩ {l | l.headI = 1}) staysPositive = + uniformOn (countedSequence p (q + 1)) staysPositive := by + rw [countedSequence_int_pos_counted_succ_succ, uniformOn, uniformOn, cond_apply _ list_int_measurableSet, cond_apply _ list_int_measurableSet, count_injective_image List.cons_injective] congr 1 @@ -294,9 +294,9 @@ theorem countedSequence_int_neg_counted_succ_succ (p q : ℕ) : norm_num theorem ballot_neg (p q : ℕ) (qp : q < p) : - condCount (countedSequence (p + 1) (q + 1) ∩ {l | l.headI = 1}ᶜ) staysPositive = - condCount (countedSequence (p + 1) q) staysPositive := by - rw [countedSequence_int_neg_counted_succ_succ, condCount, condCount, + uniformOn (countedSequence (p + 1) (q + 1) ∩ {l | l.headI = 1}ᶜ) staysPositive = + uniformOn (countedSequence (p + 1) q) staysPositive := by + rw [countedSequence_int_neg_counted_succ_succ, uniformOn, uniformOn, cond_apply _ list_int_measurableSet, cond_apply _ list_int_measurableSet, count_injective_image List.cons_injective] congr 1 @@ -310,7 +310,7 @@ theorem ballot_neg (p q : ℕ) (qp : q < p) : exact List.cons_injective theorem ballot_problem' : - ∀ q p, q < p → (condCount (countedSequence p q) staysPositive).toReal = (p - q) / (p + q) := by + ∀ q p, q < p → (uniformOn (countedSequence p q) staysPositive).toReal = (p - q) / (p + q) := by classical apply Nat.diag_induction · intro p @@ -322,12 +322,12 @@ theorem ballot_problem' : rw [div_self] exact Nat.cast_add_one_ne_zero p · intro q p qp h₁ h₂ - haveI := condCount_isProbabilityMeasure + haveI := uniformOn_isProbabilityMeasure (countedSequence_finite p (q + 1)) (countedSequence_nonempty _ _) - haveI := condCount_isProbabilityMeasure + haveI := uniformOn_isProbabilityMeasure (countedSequence_finite (p + 1) q) (countedSequence_nonempty _ _) have h₃ : p + 1 + (q + 1) > 0 := Nat.add_pos_left (Nat.succ_pos _) _ - rw [← condCount_add_compl_eq {l : List ℤ | l.headI = 1} _ (countedSequence_finite _ _), + rw [← uniformOn_add_compl_eq {l : List ℤ | l.headI = 1} _ (countedSequence_finite _ _), first_vote_pos _ _ h₃, first_vote_neg _ _ h₃, ballot_pos, ballot_neg _ _ qp] rw [ENNReal.toReal_add, ENNReal.toReal_mul, ENNReal.toReal_mul, ← Nat.cast_add, ENNReal.toReal_div, ENNReal.toReal_div, ENNReal.toReal_nat, ENNReal.toReal_nat, @@ -349,12 +349,12 @@ theorem ballot_problem' : /-- The ballot problem. -/ theorem ballot_problem : - ∀ q p, q < p → condCount (countedSequence p q) staysPositive = (p - q) / (p + q) := by + ∀ q p, q < p → uniformOn (countedSequence p q) staysPositive = (p - q) / (p + q) := by intro q p qp haveI := - condCount_isProbabilityMeasure (countedSequence_finite p q) (countedSequence_nonempty _ _) + uniformOn_isProbabilityMeasure (countedSequence_finite p q) (countedSequence_nonempty _ _) have : - (condCount (countedSequence p q) staysPositive).toReal = + (uniformOn (countedSequence p q) staysPositive).toReal = ((p - q) / (p + q) : ℝ≥0∞).toReal := by rw [ballot_problem' q p qp] rw [ENNReal.toReal_div, ← Nat.cast_add, ← Nat.cast_add, ENNReal.toReal_nat, diff --git a/Archive/Wiedijk100Theorems/BirthdayProblem.lean b/Archive/Wiedijk100Theorems/BirthdayProblem.lean index 67d6fec9989c3..02a04dd66801e 100644 --- a/Archive/Wiedijk100Theorems/BirthdayProblem.lean +++ b/Archive/Wiedijk100Theorems/BirthdayProblem.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Rodriguez -/ import Mathlib.Data.Fintype.CardEmbedding -import Mathlib.Probability.CondCount +import Mathlib.Probability.UniformOn import Mathlib.Probability.Notation /-! @@ -52,15 +52,15 @@ instance : MeasurableSingletonClass (Fin m) := /- We then endow the space with a canonical measure, which is called ℙ. We define this to be the conditional counting measure. -/ noncomputable instance : MeasureSpace (Fin n → Fin m) := - ⟨condCount Set.univ⟩ + ⟨uniformOn Set.univ⟩ -- The canonical measure on `Fin n → Fin m` is a probability measure (except on an empty space). instance : IsProbabilityMeasure (ℙ : Measure (Fin n → Fin (m + 1))) := - condCount_isProbabilityMeasure Set.finite_univ Set.univ_nonempty + uniformOn_isProbabilityMeasure Set.finite_univ Set.univ_nonempty theorem FinFin.measure_apply {s : Set <| Fin n → Fin m} : ℙ s = |s.toFinite.toFinset| / ‖Fin n → Fin m‖ := by - erw [condCount_univ, Measure.count_apply_finite] + erw [uniformOn_univ, Measure.count_apply_finite] /-- **Birthday Problem**: first probabilistic interpretation. -/ theorem birthday_measure : diff --git a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean index 74017293ce14b..e30881c10059f 100644 --- a/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean +++ b/Archive/Wiedijk100Theorems/SumOfPrimeReciprocalsDiverges.lean @@ -154,7 +154,7 @@ theorem card_le_two_pow {x k : ℕ} : card M₁ ≤ card (image f K) := card_le_card h _ ≤ card K := card_image_le _ ≤ 2 ^ card (image Nat.succ (range k)) := by simp only [K, card_powerset]; rfl - _ ≤ 2 ^ card (range k) := pow_le_pow_right one_le_two card_image_le + _ ≤ 2 ^ card (range k) := pow_right_mono₀ one_le_two card_image_le _ = 2 ^ k := by rw [card_range k] /-- diff --git a/Cache/Hashing.lean b/Cache/Hashing.lean index f50466b1c1980..5ebc53b76db24 100644 --- a/Cache/Hashing.lean +++ b/Cache/Hashing.lean @@ -73,9 +73,9 @@ def getRootHash : CacheM UInt64 := do pure id else pure ((← mathlibDepPath) / ·) - let hashs ← rootFiles.mapM fun path => + let hashes ← rootFiles.mapM fun path => hashFileContents <$> IO.FS.readFile (qualifyPath path) - return hash (hash Lean.githash :: hashs) + return hash (hash Lean.githash :: hashes) /-- Computes the hash of a file, which mixes: diff --git a/Cache/IO.lean b/Cache/IO.lean index 6cbd295c31031..43e3f70652623 100644 --- a/Cache/IO.lean +++ b/Cache/IO.lean @@ -338,7 +338,7 @@ def packCache (hashMap : HashMap) (overwrite verbose unpackedOnly : Bool) /-- Gets the set of all cached files -/ def getLocalCacheSet : IO <| Lean.RBTree String compare := do let paths ← getFilesWithExtension CACHEDIR "ltar" - return .fromList (paths.data.map (·.withoutParent CACHEDIR |>.toString)) _ + return .fromList (paths.toList.map (·.withoutParent CACHEDIR |>.toString)) _ def isPathFromMathlib (path : FilePath) : Bool := match path.components with diff --git a/Cache/Requests.lean b/Cache/Requests.lean index 5c4c6038aecaa..71b74cb4b051d 100644 --- a/Cache/Requests.lean +++ b/Cache/Requests.lean @@ -184,7 +184,7 @@ def UPLOAD_URL : String := /-- Formats the config file for `curl`, containing the list of files to be uploaded -/ def mkPutConfigContent (fileNames : Array String) (token : String) : IO String := do let token := if useFROCache then "" else s!"?{token}" -- the FRO cache doesn't pass the token here - let l ← fileNames.data.mapM fun fileName : String => do + let l ← fileNames.toList.mapM fun fileName : String => do pure s!"-T {(IO.CACHEDIR / fileName).toString}\nurl = {mkFileURL UPLOAD_URL fileName}{token}" return "\n".intercalate l diff --git a/Counterexamples/CliffordAlgebraNotInjective.lean b/Counterexamples/CliffordAlgebraNotInjective.lean index c924cfe15c215..8670d40f77954 100644 --- a/Counterexamples/CliffordAlgebraNotInjective.lean +++ b/Counterexamples/CliffordAlgebraNotInjective.lean @@ -208,7 +208,7 @@ def Q : QuadraticForm K L := QuadraticMap.ofPolar (fun x => Quotient.liftOn' x Q' fun a b h => by - rw [Submodule.quotientRel_r_def] at h + rw [Submodule.quotientRel_def] at h suffices Q' (a - b) = 0 by rwa [Q'_sub, sub_eq_zero] at this apply Q'_zero_under_ideal (a - b) h) (fun a x => by diff --git a/Counterexamples/Phillips.lean b/Counterexamples/Phillips.lean index 86aeacfb5f059..cf03d0dc7c250 100644 --- a/Counterexamples/Phillips.lean +++ b/Counterexamples/Phillips.lean @@ -6,7 +6,7 @@ Authors: Sébastien Gouëzel import Mathlib.Analysis.NormedSpace.HahnBanach.Extension import Mathlib.MeasureTheory.Integral.SetIntegral import Mathlib.MeasureTheory.Measure.Lebesgue.Basic -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded /-! # A counterexample on Pettis integrability diff --git a/Counterexamples/SeminormLatticeNotDistrib.lean b/Counterexamples/SeminormLatticeNotDistrib.lean index 770184c227ba7..e547175d5a7d5 100644 --- a/Counterexamples/SeminormLatticeNotDistrib.lean +++ b/Counterexamples/SeminormLatticeNotDistrib.lean @@ -57,14 +57,14 @@ theorem not_distrib : ¬(p ⊔ q1) ⊓ (p ⊔ q2) ≤ p ⊔ q1 ⊓ q2 := by 4 / 3 = 4 * (1 - 2 / 3) := by norm_num _ ≤ 4 * (1 - x.snd) := by gcongr _ ≤ 4 * |1 - x.snd| := by gcongr; apply le_abs_self - _ = q2 ((1, 1) - x) := by simp; rfl + _ = q2 ((1, 1) - x) := rfl _ ≤ (p ⊔ q2) ((1, 1) - x) := le_sup_right _ ≤ (p ⊔ q1) x + (p ⊔ q2) ((1, 1) - x) := le_add_of_nonneg_left (apply_nonneg _ _) · calc 4 / 3 = 2 / 3 + (1 - 1 / 3) := by norm_num _ ≤ 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 x + p ((1, 1) - x) := 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 diff --git a/Counterexamples/SorgenfreyLine.lean b/Counterexamples/SorgenfreyLine.lean index 746700b0769de..bdebf6085e105 100644 --- a/Counterexamples/SorgenfreyLine.lean +++ b/Counterexamples/SorgenfreyLine.lean @@ -110,7 +110,7 @@ theorem nhds_countable_basis_Ico_inv_pnat (a : ℝₗ) : 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) + (fun k _l hkl => inv_anti₀ (Nat.cast_pos.2 k.2) (Nat.mono_cast <| Subtype.coe_le_coe.2 hkl)) _⟩ theorem isOpen_iff {s : Set ℝₗ} : IsOpen s ↔ ∀ x ∈ s, ∃ y > x, Ico x y ⊆ s := @@ -141,7 +141,7 @@ theorem continuous_toReal : Continuous toReal := exact inf_le_left instance : OrderClosedTopology ℝₗ := - ⟨isClosed_le_prod.preimage (continuous_toReal.prod_map continuous_toReal)⟩ + ⟨isClosed_le_prod.preimage (continuous_toReal.prodMap continuous_toReal)⟩ instance : ContinuousAdd ℝₗ := by refine ⟨continuous_iff_continuousAt.2 ?_⟩ diff --git a/Mathlib.lean b/Mathlib.lean index cc970198038fa..9c48ed611ec6c 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -32,10 +32,12 @@ import Mathlib.Algebra.Algebra.Subalgebra.Tower import Mathlib.Algebra.Algebra.Subalgebra.Unitization import Mathlib.Algebra.Algebra.Tower import Mathlib.Algebra.Algebra.Unitization +import Mathlib.Algebra.Algebra.ZMod import Mathlib.Algebra.AlgebraicCard import Mathlib.Algebra.Associated.Basic import Mathlib.Algebra.Associated.OrderedCommMonoid import Mathlib.Algebra.BigOperators.Associated +import Mathlib.Algebra.BigOperators.Balance import Mathlib.Algebra.BigOperators.Expect import Mathlib.Algebra.BigOperators.Fin import Mathlib.Algebra.BigOperators.Finprod @@ -56,7 +58,6 @@ import Mathlib.Algebra.BigOperators.Ring.Multiset import Mathlib.Algebra.BigOperators.Ring.Nat import Mathlib.Algebra.BigOperators.RingEquiv import Mathlib.Algebra.BigOperators.WithTop -import Mathlib.Algebra.Bounds import Mathlib.Algebra.Category.AlgebraCat.Basic import Mathlib.Algebra.Category.AlgebraCat.Limits import Mathlib.Algebra.Category.AlgebraCat.Monoidal @@ -268,8 +269,8 @@ import Mathlib.Algebra.Group.Pi.Basic import Mathlib.Algebra.Group.Pi.Lemmas import Mathlib.Algebra.Group.Pointwise.Finset.Basic import Mathlib.Algebra.Group.Pointwise.Finset.Interval -import Mathlib.Algebra.Group.Pointwise.Finset.NatCard -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Group.Pointwise.Set.Card import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Semiconj.Basic import Mathlib.Algebra.Group.Semiconj.Defs @@ -323,7 +324,7 @@ import Mathlib.Algebra.GroupWithZero.NeZero import Mathlib.Algebra.GroupWithZero.NonZeroDivisors import Mathlib.Algebra.GroupWithZero.Opposite import Mathlib.Algebra.GroupWithZero.Pi -import Mathlib.Algebra.GroupWithZero.Pointwise.Set +import Mathlib.Algebra.GroupWithZero.Pointwise.Set.Basic import Mathlib.Algebra.GroupWithZero.Prod import Mathlib.Algebra.GroupWithZero.Semiconj import Mathlib.Algebra.GroupWithZero.ULift @@ -346,6 +347,7 @@ import Mathlib.Algebra.Homology.ConcreteCategory import Mathlib.Algebra.Homology.DerivedCategory.Basic import Mathlib.Algebra.Homology.DerivedCategory.ExactFunctor import Mathlib.Algebra.Homology.DerivedCategory.Ext.Basic +import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExactSequences import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExtClass import Mathlib.Algebra.Homology.DerivedCategory.HomologySequence import Mathlib.Algebra.Homology.DerivedCategory.ShortExact @@ -507,6 +509,7 @@ import Mathlib.Algebra.Module.Torsion import Mathlib.Algebra.Module.ULift import Mathlib.Algebra.Module.ZLattice.Basic import Mathlib.Algebra.Module.ZLattice.Covolume +import Mathlib.Algebra.Module.ZMod import Mathlib.Algebra.MonoidAlgebra.Basic import Mathlib.Algebra.MonoidAlgebra.Defs import Mathlib.Algebra.MonoidAlgebra.Degree @@ -546,8 +549,10 @@ import Mathlib.Algebra.Order.Antidiag.Prod import Mathlib.Algebra.Order.Archimedean.Basic import Mathlib.Algebra.Order.Archimedean.Hom import Mathlib.Algebra.Order.Archimedean.Submonoid +import Mathlib.Algebra.Order.BigOperators.Expect import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Algebra.Order.BigOperators.Group.List +import Mathlib.Algebra.Order.BigOperators.Group.LocallyFinite import Mathlib.Algebra.Order.BigOperators.Group.Multiset import Mathlib.Algebra.Order.BigOperators.GroupWithZero.List import Mathlib.Algebra.Order.BigOperators.GroupWithZero.Multiset @@ -566,6 +571,7 @@ import Mathlib.Algebra.Order.Field.Canonical.Defs import Mathlib.Algebra.Order.Field.Defs import Mathlib.Algebra.Order.Field.InjSurj import Mathlib.Algebra.Order.Field.Pi +import Mathlib.Algebra.Order.Field.Pointwise import Mathlib.Algebra.Order.Field.Power import Mathlib.Algebra.Order.Field.Rat import Mathlib.Algebra.Order.Field.Subfield @@ -577,6 +583,7 @@ import Mathlib.Algebra.Order.Group.Action import Mathlib.Algebra.Order.Group.Action.Synonym import Mathlib.Algebra.Order.Group.Basic import Mathlib.Algebra.Order.Group.Bounds +import Mathlib.Algebra.Order.Group.CompleteLattice import Mathlib.Algebra.Order.Group.Cone import Mathlib.Algebra.Order.Group.Defs import Mathlib.Algebra.Order.Group.DenselyOrdered @@ -587,8 +594,11 @@ import Mathlib.Algebra.Order.Group.Int import Mathlib.Algebra.Order.Group.Lattice import Mathlib.Algebra.Order.Group.MinMax import Mathlib.Algebra.Order.Group.Nat +import Mathlib.Algebra.Order.Group.Opposite import Mathlib.Algebra.Order.Group.OrderIso import Mathlib.Algebra.Order.Group.PiLex +import Mathlib.Algebra.Order.Group.Pointwise.Bounds +import Mathlib.Algebra.Order.Group.Pointwise.CompleteLattice import Mathlib.Algebra.Order.Group.PosPart import Mathlib.Algebra.Order.Group.Prod import Mathlib.Algebra.Order.Group.Synonym @@ -602,6 +612,7 @@ import Mathlib.Algebra.Order.GroupWithZero.Canonical import Mathlib.Algebra.Order.GroupWithZero.Submonoid import Mathlib.Algebra.Order.GroupWithZero.Synonym import Mathlib.Algebra.Order.GroupWithZero.Unbundled +import Mathlib.Algebra.Order.GroupWithZero.Unbundled.Lemmas import Mathlib.Algebra.Order.GroupWithZero.WithZero import Mathlib.Algebra.Order.Hom.Basic import Mathlib.Algebra.Order.Hom.Monoid @@ -621,6 +632,7 @@ import Mathlib.Algebra.Order.Module.Pointwise import Mathlib.Algebra.Order.Module.Rat import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Algebra.Order.Monoid.Basic +import Mathlib.Algebra.Order.Monoid.Canonical.Basic import Mathlib.Algebra.Order.Monoid.Canonical.Defs import Mathlib.Algebra.Order.Monoid.Defs import Mathlib.Algebra.Order.Monoid.NatCast @@ -644,7 +656,6 @@ import Mathlib.Algebra.Order.Nonneg.Floor import Mathlib.Algebra.Order.Nonneg.Module import Mathlib.Algebra.Order.Nonneg.Ring import Mathlib.Algebra.Order.Pi -import Mathlib.Algebra.Order.Pointwise import Mathlib.Algebra.Order.Positive.Field import Mathlib.Algebra.Order.Positive.Ring import Mathlib.Algebra.Order.Rearrangement @@ -658,6 +669,7 @@ import Mathlib.Algebra.Order.Ring.Finset import Mathlib.Algebra.Order.Ring.InjSurj import Mathlib.Algebra.Order.Ring.Int import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Order.Ring.Opposite import Mathlib.Algebra.Order.Ring.Pow import Mathlib.Algebra.Order.Ring.Prod import Mathlib.Algebra.Order.Ring.Rat @@ -826,7 +838,9 @@ import Mathlib.AlgebraicGeometry.EllipticCurve.DivisionPolynomial.Basic import Mathlib.AlgebraicGeometry.EllipticCurve.DivisionPolynomial.Degree import Mathlib.AlgebraicGeometry.EllipticCurve.Group import Mathlib.AlgebraicGeometry.EllipticCurve.Jacobian +import Mathlib.AlgebraicGeometry.EllipticCurve.NormalForms import Mathlib.AlgebraicGeometry.EllipticCurve.Projective +import Mathlib.AlgebraicGeometry.EllipticCurve.VariableChange import Mathlib.AlgebraicGeometry.EllipticCurve.Weierstrass import Mathlib.AlgebraicGeometry.FunctionField import Mathlib.AlgebraicGeometry.GammaSpecAdjunction @@ -864,6 +878,7 @@ import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf import Mathlib.AlgebraicGeometry.ProjectiveSpectrum.Topology import Mathlib.AlgebraicGeometry.Properties import Mathlib.AlgebraicGeometry.Pullbacks +import Mathlib.AlgebraicGeometry.ResidueField import Mathlib.AlgebraicGeometry.Restrict import Mathlib.AlgebraicGeometry.Scheme import Mathlib.AlgebraicGeometry.Sites.BigZariski @@ -898,16 +913,16 @@ import Mathlib.AlgebraicTopology.FundamentalGroupoid.InducedMaps import Mathlib.AlgebraicTopology.FundamentalGroupoid.PUnit import Mathlib.AlgebraicTopology.FundamentalGroupoid.Product import Mathlib.AlgebraicTopology.FundamentalGroupoid.SimplyConnected -import Mathlib.AlgebraicTopology.KanComplex import Mathlib.AlgebraicTopology.MooreComplex -import Mathlib.AlgebraicTopology.Nerve -import Mathlib.AlgebraicTopology.Quasicategory import Mathlib.AlgebraicTopology.SimplexCategory import Mathlib.AlgebraicTopology.SimplicialCategory.Basic import Mathlib.AlgebraicTopology.SimplicialCategory.SimplicialObject import Mathlib.AlgebraicTopology.SimplicialObject -import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic +import Mathlib.AlgebraicTopology.SimplicialSet.KanComplex import Mathlib.AlgebraicTopology.SimplicialSet.Monoidal +import Mathlib.AlgebraicTopology.SimplicialSet.Nerve +import Mathlib.AlgebraicTopology.SimplicialSet.Quasicategory import Mathlib.AlgebraicTopology.SingularSet import Mathlib.AlgebraicTopology.SplitSimplicialObject import Mathlib.AlgebraicTopology.TopologicalSimplex @@ -978,6 +993,7 @@ import Mathlib.Analysis.Calculus.ContDiff.FTaylorSeries import Mathlib.Analysis.Calculus.ContDiff.FiniteDimension import Mathlib.Analysis.Calculus.ContDiff.RCLike import Mathlib.Analysis.Calculus.Darboux +import Mathlib.Analysis.Calculus.Deriv.Abs import Mathlib.Analysis.Calculus.Deriv.Add import Mathlib.Analysis.Calculus.Deriv.AffineMap import Mathlib.Analysis.Calculus.Deriv.Basic @@ -1007,6 +1023,7 @@ import Mathlib.Analysis.Calculus.FDeriv.Extend import Mathlib.Analysis.Calculus.FDeriv.Linear import Mathlib.Analysis.Calculus.FDeriv.Measurable import Mathlib.Analysis.Calculus.FDeriv.Mul +import Mathlib.Analysis.Calculus.FDeriv.Norm import Mathlib.Analysis.Calculus.FDeriv.Pi import Mathlib.Analysis.Calculus.FDeriv.Prod import Mathlib.Analysis.Calculus.FDeriv.RestrictScalars @@ -1080,6 +1097,7 @@ import Mathlib.Analysis.ConstantSpeed import Mathlib.Analysis.Convex.AmpleSet import Mathlib.Analysis.Convex.Basic import Mathlib.Analysis.Convex.Between +import Mathlib.Analysis.Convex.Birkhoff import Mathlib.Analysis.Convex.Body import Mathlib.Analysis.Convex.Caratheodory import Mathlib.Analysis.Convex.Combination @@ -1090,6 +1108,7 @@ 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.Continuous import Mathlib.Analysis.Convex.Contractible import Mathlib.Analysis.Convex.Deriv import Mathlib.Analysis.Convex.EGauge @@ -1190,6 +1209,7 @@ import Mathlib.Analysis.Normed.Affine.MazurUlam import Mathlib.Analysis.Normed.Algebra.Basic import Mathlib.Analysis.Normed.Algebra.Exponential import Mathlib.Analysis.Normed.Algebra.MatrixExponential +import Mathlib.Analysis.Normed.Algebra.Norm import Mathlib.Analysis.Normed.Algebra.QuaternionExponential import Mathlib.Analysis.Normed.Algebra.Spectrum import Mathlib.Analysis.Normed.Algebra.TrivSqZeroExt @@ -1224,6 +1244,7 @@ import Mathlib.Analysis.Normed.Group.SemiNormedGrp.Kernels import Mathlib.Analysis.Normed.Group.Seminorm import Mathlib.Analysis.Normed.Group.Submodule import Mathlib.Analysis.Normed.Group.Tannery +import Mathlib.Analysis.Normed.Group.Ultra import Mathlib.Analysis.Normed.Group.Uniform import Mathlib.Analysis.Normed.Group.ZeroAtInfty import Mathlib.Analysis.Normed.Lp.LpEquiv @@ -1250,9 +1271,11 @@ import Mathlib.Analysis.Normed.Operator.WeakOperatorTopology import Mathlib.Analysis.Normed.Order.Basic import Mathlib.Analysis.Normed.Order.Lattice import Mathlib.Analysis.Normed.Order.UpperLower +import Mathlib.Analysis.Normed.Ring.IsPowMulFaithful import Mathlib.Analysis.Normed.Ring.Seminorm import Mathlib.Analysis.Normed.Ring.SeminormFromBounded import Mathlib.Analysis.Normed.Ring.SeminormFromConst +import Mathlib.Analysis.Normed.Ring.Ultra import Mathlib.Analysis.Normed.Ring.Units import Mathlib.Analysis.NormedSpace.BallAction import Mathlib.Analysis.NormedSpace.ConformalLinearMap @@ -1293,6 +1316,7 @@ import Mathlib.Analysis.PSeries import Mathlib.Analysis.PSeriesComplex import Mathlib.Analysis.Quaternion import Mathlib.Analysis.RCLike.Basic +import Mathlib.Analysis.RCLike.Inner import Mathlib.Analysis.RCLike.Lemmas import Mathlib.Analysis.Seminorm import Mathlib.Analysis.SpecialFunctions.Arsinh @@ -1441,6 +1465,7 @@ import Mathlib.CategoryTheory.Category.PartialFun import Mathlib.CategoryTheory.Category.Pointed import Mathlib.CategoryTheory.Category.Preorder import Mathlib.CategoryTheory.Category.Quiv +import Mathlib.CategoryTheory.Category.ReflQuiv import Mathlib.CategoryTheory.Category.RelCat import Mathlib.CategoryTheory.Category.TwoP import Mathlib.CategoryTheory.Category.ULift @@ -1530,6 +1555,7 @@ import Mathlib.CategoryTheory.Functor.Trifunctor import Mathlib.CategoryTheory.Galois.Action import Mathlib.CategoryTheory.Galois.Basic import Mathlib.CategoryTheory.Galois.Decomposition +import Mathlib.CategoryTheory.Galois.EssSurj import Mathlib.CategoryTheory.Galois.Examples import Mathlib.CategoryTheory.Galois.Full import Mathlib.CategoryTheory.Galois.GaloisObjects @@ -1956,6 +1982,7 @@ import Mathlib.Combinatorics.Quiver.ConnectedComponent import Mathlib.Combinatorics.Quiver.Covering import Mathlib.Combinatorics.Quiver.Path import Mathlib.Combinatorics.Quiver.Push +import Mathlib.Combinatorics.Quiver.ReflQuiver import Mathlib.Combinatorics.Quiver.SingleObj import Mathlib.Combinatorics.Quiver.Subquiver import Mathlib.Combinatorics.Quiver.Symmetric @@ -2043,6 +2070,7 @@ import Mathlib.Condensed.Basic import Mathlib.Condensed.CartesianClosed import Mathlib.Condensed.Discrete.Basic import Mathlib.Condensed.Discrete.LocallyConstant +import Mathlib.Condensed.Discrete.Module import Mathlib.Condensed.Epi import Mathlib.Condensed.Equivalence import Mathlib.Condensed.Explicit @@ -2164,6 +2192,7 @@ import Mathlib.Data.Finset.Grade import Mathlib.Data.Finset.Image import Mathlib.Data.Finset.Interval import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Finset.Max import Mathlib.Data.Finset.MulAntidiagonal import Mathlib.Data.Finset.NAry import Mathlib.Data.Finset.NatAntidiagonal @@ -2247,6 +2276,7 @@ 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.DivMod import Mathlib.Data.Int.GCD import Mathlib.Data.Int.Interval import Mathlib.Data.Int.LeastGreatest @@ -2262,6 +2292,7 @@ import Mathlib.Data.Int.Range import Mathlib.Data.Int.Sqrt import Mathlib.Data.Int.Star import Mathlib.Data.Int.SuccPred +import Mathlib.Data.Int.WithZero import Mathlib.Data.LazyList.Basic import Mathlib.Data.List.AList import Mathlib.Data.List.Basic @@ -2326,6 +2357,7 @@ import Mathlib.Data.Matrix.CharP import Mathlib.Data.Matrix.ColumnRowPartitioned import Mathlib.Data.Matrix.Composition import Mathlib.Data.Matrix.DMatrix +import Mathlib.Data.Matrix.DoublyStochastic import Mathlib.Data.Matrix.DualNumber import Mathlib.Data.Matrix.Hadamard import Mathlib.Data.Matrix.Invertible @@ -2508,6 +2540,7 @@ import Mathlib.Data.Real.GoldenRatio import Mathlib.Data.Real.Hyperreal import Mathlib.Data.Real.Irrational import Mathlib.Data.Real.Pi.Bounds +import Mathlib.Data.Real.Pi.Irrational import Mathlib.Data.Real.Pi.Leibniz import Mathlib.Data.Real.Pi.Wallis import Mathlib.Data.Real.Pointwise @@ -2538,6 +2571,7 @@ import Mathlib.Data.Set.Image import Mathlib.Data.Set.Lattice import Mathlib.Data.Set.List import Mathlib.Data.Set.MemPartition +import Mathlib.Data.Set.Monotone import Mathlib.Data.Set.MulAntidiagonal import Mathlib.Data.Set.NAry import Mathlib.Data.Set.Notation @@ -2602,14 +2636,11 @@ import Mathlib.Data.Vector3 import Mathlib.Data.W.Basic import Mathlib.Data.W.Cardinal import Mathlib.Data.W.Constructions -import Mathlib.Data.ZMod.Algebra import Mathlib.Data.ZMod.Basic import Mathlib.Data.ZMod.Coprime import Mathlib.Data.ZMod.Defs import Mathlib.Data.ZMod.Factorial import Mathlib.Data.ZMod.IntUnitsPower -import Mathlib.Data.ZMod.Module -import Mathlib.Data.ZMod.Parity import Mathlib.Data.ZMod.Quotient import Mathlib.Data.ZMod.Units import Mathlib.Deprecated.Aliases @@ -2642,6 +2673,8 @@ import Mathlib.Dynamics.OmegaLimit import Mathlib.Dynamics.PeriodicPts import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy import Mathlib.Dynamics.TopologicalEntropy.DynamicalEntourage +import Mathlib.Dynamics.TopologicalEntropy.NetEntropy +import Mathlib.Dynamics.TopologicalEntropy.Semiconj import Mathlib.FieldTheory.AbelRuffini import Mathlib.FieldTheory.AbsoluteGaloisGroup import Mathlib.FieldTheory.Adjoin @@ -2656,7 +2689,7 @@ import Mathlib.FieldTheory.Finite.Polynomial import Mathlib.FieldTheory.Finite.Trace import Mathlib.FieldTheory.Finiteness import Mathlib.FieldTheory.Fixed -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic import Mathlib.FieldTheory.IntermediateField.Algebraic import Mathlib.FieldTheory.IntermediateField.Basic import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure @@ -2742,6 +2775,7 @@ 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.Tangent import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential import Mathlib.Geometry.Manifold.Metrizable import Mathlib.Geometry.Manifold.PartitionOfUnity @@ -3081,6 +3115,7 @@ import Mathlib.LinearAlgebra.Ray import Mathlib.LinearAlgebra.Reflection import Mathlib.LinearAlgebra.RootSystem.Basic import Mathlib.LinearAlgebra.RootSystem.Defs +import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear import Mathlib.LinearAlgebra.RootSystem.Hom import Mathlib.LinearAlgebra.RootSystem.OfBilinear import Mathlib.LinearAlgebra.RootSystem.RootPairingCat @@ -3417,6 +3452,8 @@ import Mathlib.NumberTheory.EulerProduct.DirichletLSeries import Mathlib.NumberTheory.FLT.Basic import Mathlib.NumberTheory.FLT.Four import Mathlib.NumberTheory.FLT.Three +import Mathlib.NumberTheory.FactorisationProperties +import Mathlib.NumberTheory.Fermat import Mathlib.NumberTheory.FermatPsp import Mathlib.NumberTheory.FrobeniusNumber import Mathlib.NumberTheory.FunctionField @@ -3534,6 +3571,7 @@ import Mathlib.Order.Booleanisation import Mathlib.Order.Bounded import Mathlib.Order.BoundedOrder import Mathlib.Order.Bounds.Basic +import Mathlib.Order.Bounds.Defs import Mathlib.Order.Bounds.OrderIso import Mathlib.Order.Category.BddDistLat import Mathlib.Order.Category.BddLat @@ -3561,6 +3599,7 @@ import Mathlib.Order.CompactlyGenerated.Intervals import Mathlib.Order.Compare import Mathlib.Order.CompleteBooleanAlgebra import Mathlib.Order.CompleteLattice +import Mathlib.Order.CompleteLattice.Finset import Mathlib.Order.CompleteLatticeIntervals import Mathlib.Order.CompletePartialOrder import Mathlib.Order.CompleteSublattice @@ -3582,6 +3621,7 @@ import Mathlib.Order.Filter.AtTopBot import Mathlib.Order.Filter.AtTopBot.Archimedean import Mathlib.Order.Filter.AtTopBot.BigOperators import Mathlib.Order.Filter.AtTopBot.Field +import Mathlib.Order.Filter.AtTopBot.Floor import Mathlib.Order.Filter.AtTopBot.Group import Mathlib.Order.Filter.AtTopBot.ModEq import Mathlib.Order.Filter.AtTopBot.Monoid @@ -3594,6 +3634,7 @@ import Mathlib.Order.Filter.Cofinite import Mathlib.Order.Filter.CountableInter import Mathlib.Order.Filter.CountableSeparatingOn import Mathlib.Order.Filter.Curry +import Mathlib.Order.Filter.Defs import Mathlib.Order.Filter.ENNReal import Mathlib.Order.Filter.EventuallyConst import Mathlib.Order.Filter.Extr @@ -3723,7 +3764,6 @@ import Mathlib.Order.Zorn import Mathlib.Order.ZornAtoms import Mathlib.Probability.BorelCantelli import Mathlib.Probability.CDF -import Mathlib.Probability.CondCount import Mathlib.Probability.ConditionalExpectation import Mathlib.Probability.ConditionalProbability import Mathlib.Probability.Density @@ -3731,6 +3771,7 @@ import Mathlib.Probability.Distributions.Exponential import Mathlib.Probability.Distributions.Gamma import Mathlib.Probability.Distributions.Gaussian import Mathlib.Probability.Distributions.Geometric +import Mathlib.Probability.Distributions.Pareto import Mathlib.Probability.Distributions.Poisson import Mathlib.Probability.Distributions.Uniform import Mathlib.Probability.IdentDistrib @@ -3780,6 +3821,7 @@ import Mathlib.Probability.Process.HittingTime import Mathlib.Probability.Process.PartitionFiltration import Mathlib.Probability.Process.Stopping import Mathlib.Probability.StrongLaw +import Mathlib.Probability.UniformOn import Mathlib.Probability.Variance import Mathlib.RepresentationTheory.Action.Basic import Mathlib.RepresentationTheory.Action.Concrete @@ -3848,11 +3890,13 @@ import Mathlib.RingTheory.Derivation.ToSquareZero import Mathlib.RingTheory.DiscreteValuationRing.Basic import Mathlib.RingTheory.DiscreteValuationRing.TFAE import Mathlib.RingTheory.Discriminant +import Mathlib.RingTheory.DualNumber import Mathlib.RingTheory.EisensteinCriterion import Mathlib.RingTheory.EssentialFiniteness import Mathlib.RingTheory.Etale.Basic import Mathlib.RingTheory.EuclideanDomain import Mathlib.RingTheory.Filtration +import Mathlib.RingTheory.FiniteLength import Mathlib.RingTheory.FinitePresentation import Mathlib.RingTheory.FiniteStability import Mathlib.RingTheory.FiniteType @@ -3918,6 +3962,8 @@ import Mathlib.RingTheory.JacobsonIdeal import Mathlib.RingTheory.Kaehler.Basic import Mathlib.RingTheory.Kaehler.CotangentComplex import Mathlib.RingTheory.Kaehler.Polynomial +import Mathlib.RingTheory.KrullDimension.Basic +import Mathlib.RingTheory.KrullDimension.Field import Mathlib.RingTheory.LaurentSeries import Mathlib.RingTheory.LittleWedderburn import Mathlib.RingTheory.LocalProperties.Basic @@ -3931,12 +3977,12 @@ import Mathlib.RingTheory.LocalRing.Module import Mathlib.RingTheory.LocalRing.ResidueField.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs import Mathlib.RingTheory.LocalRing.RingHom.Basic -import Mathlib.RingTheory.LocalRing.RingHom.Defs import Mathlib.RingTheory.Localization.Algebra 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.Away.Lemmas import Mathlib.RingTheory.Localization.BaseChange import Mathlib.RingTheory.Localization.Basic import Mathlib.RingTheory.Localization.Cardinality @@ -4035,6 +4081,7 @@ import Mathlib.RingTheory.RingHom.Finite import Mathlib.RingTheory.RingHom.FinitePresentation import Mathlib.RingTheory.RingHom.FiniteType import Mathlib.RingTheory.RingHom.Integral +import Mathlib.RingTheory.RingHom.Locally import Mathlib.RingTheory.RingHom.Surjective import Mathlib.RingTheory.RingHomProperties import Mathlib.RingTheory.RingInvo @@ -4055,12 +4102,16 @@ import Mathlib.RingTheory.TensorProduct.MvPolynomial import Mathlib.RingTheory.Trace.Basic import Mathlib.RingTheory.Trace.Defs import Mathlib.RingTheory.TwoSidedIdeal.Basic +import Mathlib.RingTheory.TwoSidedIdeal.BigOperators import Mathlib.RingTheory.TwoSidedIdeal.Instances import Mathlib.RingTheory.TwoSidedIdeal.Lattice +import Mathlib.RingTheory.TwoSidedIdeal.Operations import Mathlib.RingTheory.UniqueFactorizationDomain import Mathlib.RingTheory.Unramified.Basic import Mathlib.RingTheory.Unramified.Derivations +import Mathlib.RingTheory.Unramified.Field import Mathlib.RingTheory.Unramified.Finite +import Mathlib.RingTheory.Unramified.Pi import Mathlib.RingTheory.Valuation.AlgebraInstances import Mathlib.RingTheory.Valuation.Basic import Mathlib.RingTheory.Valuation.ExtendToLocalization @@ -4093,6 +4144,8 @@ import Mathlib.RingTheory.WittVector.Truncated import Mathlib.RingTheory.WittVector.Verschiebung import Mathlib.RingTheory.WittVector.WittPolynomial import Mathlib.RingTheory.ZMod +import Mathlib.SetTheory.Cardinal.Aleph +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Basic import Mathlib.SetTheory.Cardinal.Cofinality import Mathlib.SetTheory.Cardinal.Continuum @@ -4101,7 +4154,6 @@ import Mathlib.SetTheory.Cardinal.Divisibility import Mathlib.SetTheory.Cardinal.ENat import Mathlib.SetTheory.Cardinal.Finite import Mathlib.SetTheory.Cardinal.Finsupp -import Mathlib.SetTheory.Cardinal.Ordinal import Mathlib.SetTheory.Cardinal.PartENat import Mathlib.SetTheory.Cardinal.SchroederBernstein import Mathlib.SetTheory.Cardinal.Subfield @@ -4120,6 +4172,7 @@ import Mathlib.SetTheory.Lists import Mathlib.SetTheory.Ordinal.Arithmetic import Mathlib.SetTheory.Ordinal.Basic import Mathlib.SetTheory.Ordinal.CantorNormalForm +import Mathlib.SetTheory.Ordinal.Enum import Mathlib.SetTheory.Ordinal.Exponential import Mathlib.SetTheory.Ordinal.FixedPoint import Mathlib.SetTheory.Ordinal.FixedPointApproximants @@ -4138,6 +4191,7 @@ import Mathlib.Std.Data.HashMap import Mathlib.Tactic import Mathlib.Tactic.Abel import Mathlib.Tactic.AdaptationNote +import Mathlib.Tactic.Algebraize import Mathlib.Tactic.ApplyAt import Mathlib.Tactic.ApplyCongr import Mathlib.Tactic.ApplyFun @@ -4272,6 +4326,7 @@ import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.LinearCombination.Lemmas import Mathlib.Tactic.Linter import Mathlib.Tactic.Linter.AdmitLinter +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.FlexibleLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter @@ -4279,6 +4334,7 @@ import Mathlib.Tactic.Linter.HaveLetLinter import Mathlib.Tactic.Linter.Lint import Mathlib.Tactic.Linter.MinImports import Mathlib.Tactic.Linter.OldObtain +import Mathlib.Tactic.Linter.PPRoundtrip import Mathlib.Tactic.Linter.RefineLinter import Mathlib.Tactic.Linter.Style import Mathlib.Tactic.Linter.TextBased @@ -4288,6 +4344,7 @@ import Mathlib.Tactic.Measurability.Init import Mathlib.Tactic.MinImports import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.ModCases +import Mathlib.Tactic.Module import Mathlib.Tactic.Monotonicity import Mathlib.Tactic.Monotonicity.Attr import Mathlib.Tactic.Monotonicity.Basic @@ -4343,6 +4400,7 @@ import Mathlib.Tactic.RewriteSearch import Mathlib.Tactic.Rify import Mathlib.Tactic.Ring import Mathlib.Tactic.Ring.Basic +import Mathlib.Tactic.Ring.Compare import Mathlib.Tactic.Ring.PNat import Mathlib.Tactic.Ring.RingNF import Mathlib.Tactic.Sat.FromLRAT @@ -4397,7 +4455,8 @@ import Mathlib.Topology.AlexandrovDiscrete import Mathlib.Topology.Algebra.Affine import Mathlib.Topology.Algebra.Algebra import Mathlib.Topology.Algebra.Algebra.Rat -import Mathlib.Topology.Algebra.Category.ProfiniteGrp +import Mathlib.Topology.Algebra.Category.ProfiniteGrp.Basic +import Mathlib.Topology.Algebra.ClosedSubgroup import Mathlib.Topology.Algebra.ConstMulAction import Mathlib.Topology.Algebra.Constructions import Mathlib.Topology.Algebra.Constructions.DomMulAct @@ -4491,6 +4550,7 @@ import Mathlib.Topology.Bornology.Basic import Mathlib.Topology.Bornology.BoundedOperation import Mathlib.Topology.Bornology.Constructions import Mathlib.Topology.Bornology.Hom +import Mathlib.Topology.CWComplex import Mathlib.Topology.Category.Born import Mathlib.Topology.Category.CompHaus.Basic import Mathlib.Topology.Category.CompHaus.EffectiveEpi @@ -4535,6 +4595,7 @@ import Mathlib.Topology.Category.TopCat.Limits.Products import Mathlib.Topology.Category.TopCat.Limits.Pullbacks import Mathlib.Topology.Category.TopCat.OpenNhds import Mathlib.Topology.Category.TopCat.Opens +import Mathlib.Topology.Category.TopCat.Sphere import Mathlib.Topology.Category.TopCat.Yoneda import Mathlib.Topology.Category.TopCommRingCat import Mathlib.Topology.Category.UniformSpace @@ -4558,25 +4619,26 @@ import Mathlib.Topology.Connected.PathConnected import Mathlib.Topology.Connected.Separation import Mathlib.Topology.Connected.TotallyDisconnected import Mathlib.Topology.Constructions -import Mathlib.Topology.ContinuousFunction.Algebra -import Mathlib.Topology.ContinuousFunction.Basic -import Mathlib.Topology.ContinuousFunction.Bounded -import Mathlib.Topology.ContinuousFunction.BoundedCompactlySupported -import Mathlib.Topology.ContinuousFunction.CocompactMap -import Mathlib.Topology.ContinuousFunction.Compact -import Mathlib.Topology.ContinuousFunction.CompactlySupported -import Mathlib.Topology.ContinuousFunction.ContinuousMapZero -import Mathlib.Topology.ContinuousFunction.Ideals -import Mathlib.Topology.ContinuousFunction.LocallyConstant -import Mathlib.Topology.ContinuousFunction.Ordered -import Mathlib.Topology.ContinuousFunction.Polynomial -import Mathlib.Topology.ContinuousFunction.Sigma -import Mathlib.Topology.ContinuousFunction.StarOrdered -import Mathlib.Topology.ContinuousFunction.StoneWeierstrass -import Mathlib.Topology.ContinuousFunction.T0Sierpinski -import Mathlib.Topology.ContinuousFunction.Units -import Mathlib.Topology.ContinuousFunction.Weierstrass -import Mathlib.Topology.ContinuousFunction.ZeroAtInfty +import Mathlib.Topology.ContinuousMap.Algebra +import Mathlib.Topology.ContinuousMap.Basic +import Mathlib.Topology.ContinuousMap.Bounded +import Mathlib.Topology.ContinuousMap.BoundedCompactlySupported +import Mathlib.Topology.ContinuousMap.CocompactMap +import Mathlib.Topology.ContinuousMap.Compact +import Mathlib.Topology.ContinuousMap.CompactlySupported +import Mathlib.Topology.ContinuousMap.ContinuousMapZero +import Mathlib.Topology.ContinuousMap.Defs +import Mathlib.Topology.ContinuousMap.Ideals +import Mathlib.Topology.ContinuousMap.LocallyConstant +import Mathlib.Topology.ContinuousMap.Ordered +import Mathlib.Topology.ContinuousMap.Polynomial +import Mathlib.Topology.ContinuousMap.Sigma +import Mathlib.Topology.ContinuousMap.StarOrdered +import Mathlib.Topology.ContinuousMap.StoneWeierstrass +import Mathlib.Topology.ContinuousMap.T0Sierpinski +import Mathlib.Topology.ContinuousMap.Units +import Mathlib.Topology.ContinuousMap.Weierstrass +import Mathlib.Topology.ContinuousMap.ZeroAtInfty import Mathlib.Topology.ContinuousOn import Mathlib.Topology.CountableSeparatingOn import Mathlib.Topology.Covering @@ -4647,6 +4709,7 @@ import Mathlib.Topology.LocallyConstant.Algebra import Mathlib.Topology.LocallyConstant.Basic import Mathlib.Topology.LocallyFinite import Mathlib.Topology.Maps.Basic +import Mathlib.Topology.Maps.OpenQuotient import Mathlib.Topology.Maps.Proper.Basic import Mathlib.Topology.Maps.Proper.UniversallyClosed import Mathlib.Topology.MetricSpace.Algebra @@ -4670,6 +4733,7 @@ import Mathlib.Topology.MetricSpace.GromovHausdorffRealized import Mathlib.Topology.MetricSpace.HausdorffDimension import Mathlib.Topology.MetricSpace.HausdorffDistance import Mathlib.Topology.MetricSpace.Holder +import Mathlib.Topology.MetricSpace.HolderNorm import Mathlib.Topology.MetricSpace.Infsep import Mathlib.Topology.MetricSpace.IsometricSMul import Mathlib.Topology.MetricSpace.Isometry @@ -4693,6 +4757,8 @@ import Mathlib.Topology.MetricSpace.ShrinkingLemma import Mathlib.Topology.MetricSpace.ThickenedIndicator import Mathlib.Topology.MetricSpace.Thickening import Mathlib.Topology.MetricSpace.Ultra.Basic +import Mathlib.Topology.MetricSpace.Ultra.ContinuousMaps +import Mathlib.Topology.MetricSpace.Ultra.TotallySeparated import Mathlib.Topology.Metrizable.Basic import Mathlib.Topology.Metrizable.ContinuousMap import Mathlib.Topology.Metrizable.Uniformity @@ -4789,6 +4855,7 @@ import Mathlib.Topology.UniformSpace.Completion import Mathlib.Topology.UniformSpace.Equicontinuity import Mathlib.Topology.UniformSpace.Equiv import Mathlib.Topology.UniformSpace.Matrix +import Mathlib.Topology.UniformSpace.OfFun import Mathlib.Topology.UniformSpace.Pi import Mathlib.Topology.UniformSpace.Separation import Mathlib.Topology.UniformSpace.UniformConvergence diff --git a/Mathlib/Algebra/AddTorsor.lean b/Mathlib/Algebra/AddTorsor.lean index f9baa6191726f..ed65a54d0f15f 100644 --- a/Mathlib/Algebra/AddTorsor.lean +++ b/Mathlib/Algebra/AddTorsor.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joseph Myers, Yury Kudryashov -/ import Mathlib.Algebra.Group.Action.Basic -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic /-! # Torsors of additive group actions @@ -248,7 +248,6 @@ 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.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 29d91b4ab7439..f4a24f5977006 100644 --- a/Mathlib/Algebra/Algebra/Basic.lean +++ b/Mathlib/Algebra/Algebra/Basic.lean @@ -23,12 +23,12 @@ universe u v w u₁ v₁ namespace Algebra -variable {R : Type u} {S : Type v} {A : Type w} {B : Type*} +variable {R : Type u} {A : Type w} section Semiring -variable [CommSemiring R] [CommSemiring S] -variable [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] +variable [CommSemiring R] +variable [Semiring A] [Algebra R A] section PUnit @@ -185,8 +185,7 @@ theorem End_algebraMap_isUnit_inv_apply_eq_iff {x : R} mpr := fun H => H.symm ▸ by apply_fun ⇑h.unit.val using ((Module.End_isUnit_iff _).mp h).injective - erw [End_isUnit_apply_inv_apply_of_isUnit] - rfl } + simpa using End_isUnit_apply_inv_apply_of_isUnit h (x • m') } theorem End_algebraMap_isUnit_inv_apply_eq_iff' {x : R} (h : IsUnit (algebraMap R (Module.End S M) x)) (m m' : M) : @@ -195,8 +194,7 @@ theorem End_algebraMap_isUnit_inv_apply_eq_iff' {x : R} mpr := fun H => H.symm ▸ by apply_fun (↑h.unit : M → M) using ((Module.End_isUnit_iff _).mp h).injective - erw [End_isUnit_apply_inv_apply_of_isUnit] - rfl } + simpa using End_isUnit_apply_inv_apply_of_isUnit h (x • m') |>.symm } end @@ -321,7 +319,6 @@ section IsScalarTower variable {R : Type*} [CommSemiring R] variable (A : Type*) [Semiring A] [Algebra R A] variable {M : Type*} [AddCommMonoid M] [Module A M] [Module R M] [IsScalarTower R A M] -variable {N : Type*} [AddCommMonoid N] [Module A N] [Module R N] [IsScalarTower R A N] theorem algebra_compatible_smul (r : R) (m : M) : r • m = (algebraMap R A) r • m := by rw [← one_smul A m, ← smul_assoc, Algebra.smul_def, mul_one, one_smul] diff --git a/Mathlib/Algebra/Algebra/Defs.lean b/Mathlib/Algebra/Algebra/Defs.lean index 0393439d7bb1f..9683ddd51e176 100644 --- a/Mathlib/Algebra/Algebra/Defs.lean +++ b/Mathlib/Algebra/Algebra/Defs.lean @@ -237,7 +237,8 @@ theorem algebra_ext {R : Type*} [CommSemiring R] {A : Type*} [Semiring A] (P Q : congr -- see Note [lower instance priority] -instance (priority := 200) toModule : Module R A where +instance (priority := 200) toModule {R A} {_ : CommSemiring R} {_ : Semiring A} [Algebra R A] : + Module R A where one_smul _ := by simp [smul_def'] mul_smul := by simp [smul_def', mul_assoc] smul_add := by simp [smul_def', mul_add] diff --git a/Mathlib/Algebra/Algebra/Spectrum.lean b/Mathlib/Algebra/Algebra/Spectrum.lean index 2b7e28f8e2c29..65c69f706fb00 100644 --- a/Mathlib/Algebra/Algebra/Spectrum.lean +++ b/Mathlib/Algebra/Algebra/Spectrum.lean @@ -400,7 +400,7 @@ end CommSemiring section CommRing -variable {F R A B : Type*} [CommRing R] [Ring A] [Algebra R A] [Ring B] [Algebra R B] +variable {F R A : Type*} [CommRing R] [Ring A] [Algebra R A] variable [FunLike F A R] [AlgHomClass F R A R] local notation "σ" => spectrum R diff --git a/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean b/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean index 468781008d3b8..2c9016caf3b6c 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/IsSimpleOrder.lean @@ -12,7 +12,7 @@ If `A` is a domain, and a finite-dimensional algebra over a field `F`, with prim then there are no non-trivial `F`-subalgebras. -/ -open FiniteDimensional Submodule +open Module Submodule 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) := diff --git a/Mathlib/Algebra/Algebra/Subalgebra/Rank.lean b/Mathlib/Algebra/Algebra/Subalgebra/Rank.lean index 1dac252bbf591..e4b3c91e4d894 100644 --- a/Mathlib/Algebra/Algebra/Subalgebra/Rank.lean +++ b/Mathlib/Algebra/Algebra/Subalgebra/Rank.lean @@ -18,7 +18,7 @@ satisfies strong rank condition, we put them into a separate file. -/ -open FiniteDimensional +open Module namespace Subalgebra diff --git a/Mathlib/Data/ZMod/Algebra.lean b/Mathlib/Algebra/Algebra/ZMod.lean similarity index 100% rename from Mathlib/Data/ZMod/Algebra.lean rename to Mathlib/Algebra/Algebra/ZMod.lean index 2f5737b396fd4..a04244c46ce31 100644 --- a/Mathlib/Data/ZMod/Algebra.lean +++ b/Mathlib/Algebra/Algebra/ZMod.lean @@ -3,8 +3,8 @@ Copyright (c) 2021 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Data.ZMod.Basic import Mathlib.Algebra.Algebra.Defs +import Mathlib.Data.ZMod.Basic /-! # The `ZMod n`-algebra structure on rings whose characteristic divides `n` diff --git a/Mathlib/Algebra/Associated/Basic.lean b/Mathlib/Algebra/Associated/Basic.lean index 7eaa44c44512d..47308730de6b6 100644 --- a/Mathlib/Algebra/Associated/Basic.lean +++ b/Mathlib/Algebra/Associated/Basic.lean @@ -31,20 +31,20 @@ and prove basic properties of this quotient. assert_not_exists OrderedCommMonoid assert_not_exists Multiset -variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} +variable {M N : Type*} section Prime -variable [CommMonoidWithZero α] +variable [CommMonoidWithZero M] /-- An element `p` of a commutative monoid with zero (e.g., a ring) is called *prime*, if it's not zero, not a unit, and `p ∣ a * b → p ∣ a ∨ p ∣ b` for all `a`, `b`. -/ -def Prime (p : α) : Prop := +def Prime (p : M) : Prop := p ≠ 0 ∧ ¬IsUnit p ∧ ∀ a b, p ∣ a * b → p ∣ a ∨ p ∣ b namespace Prime -variable {p : α} (hp : Prime p) +variable {p : M} (hp : Prime p) include hp theorem ne_zero : p ≠ 0 := @@ -58,19 +58,19 @@ theorem not_dvd_one : ¬p ∣ 1 := theorem ne_one : p ≠ 1 := fun h => hp.2.1 (h.symm ▸ isUnit_one) -theorem dvd_or_dvd {a b : α} (h : p ∣ a * b) : p ∣ a ∨ p ∣ b := +theorem dvd_or_dvd {a b : M} (h : p ∣ a * b) : p ∣ a ∨ p ∣ b := hp.2.2 a b h -theorem dvd_mul {a b : α} : p ∣ a * b ↔ p ∣ a ∨ p ∣ b := +theorem dvd_mul {a b : M} : p ∣ a * b ↔ p ∣ a ∨ p ∣ b := ⟨hp.dvd_or_dvd, (Or.elim · (dvd_mul_of_dvd_left · _) (dvd_mul_of_dvd_right · _))⟩ theorem isPrimal : IsPrimal p := fun _a _b dvd ↦ (hp.dvd_or_dvd dvd).elim (fun h ↦ ⟨p, 1, h, one_dvd _, (mul_one p).symm⟩) fun h ↦ ⟨1, p, one_dvd _, h, (one_mul p).symm⟩ -theorem not_dvd_mul {a b : α} (ha : ¬ p ∣ a) (hb : ¬ p ∣ b) : ¬ p ∣ a * b := +theorem not_dvd_mul {a b : M} (ha : ¬ p ∣ a) (hb : ¬ p ∣ b) : ¬ p ∣ a * b := hp.dvd_mul.not.mpr <| not_or.mpr ⟨ha, hb⟩ -theorem dvd_of_dvd_pow {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by +theorem dvd_of_dvd_pow {a : M} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by induction n with | zero => rw [pow_zero] at h @@ -83,24 +83,24 @@ theorem dvd_of_dvd_pow {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by · assumption · exact ih dvd_pow -theorem dvd_pow_iff_dvd {a : α} {n : ℕ} (hn : n ≠ 0) : p ∣ a ^ n ↔ p ∣ a := +theorem dvd_pow_iff_dvd {a : M} {n : ℕ} (hn : n ≠ 0) : p ∣ a ^ n ↔ p ∣ a := ⟨hp.dvd_of_dvd_pow, (dvd_pow · hn)⟩ end Prime @[simp] -theorem not_prime_zero : ¬Prime (0 : α) := fun h => h.ne_zero rfl +theorem not_prime_zero : ¬Prime (0 : M) := fun h => h.ne_zero rfl @[simp] -theorem not_prime_one : ¬Prime (1 : α) := fun h => h.not_unit isUnit_one +theorem not_prime_one : ¬Prime (1 : M) := fun h => h.not_unit isUnit_one section Map -variable [CommMonoidWithZero β] {F : Type*} {G : Type*} [FunLike F α β] -variable [MonoidWithZeroHomClass F α β] [FunLike G β α] [MulHomClass G β α] -variable (f : F) (g : G) {p : α} +variable [CommMonoidWithZero N] {F : Type*} {G : Type*} [FunLike F M N] +variable [MonoidWithZeroHomClass F M N] [FunLike G N M] [MulHomClass G N M] +variable (f : F) (g : G) {p : M} -theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p := +theorem comap_prime (hinv : ∀ a, g (f a : N) = a) (hp : Prime (f p)) : Prime p := ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by refine (hp.2.2 (f a) (f b) <| by @@ -110,7 +110,7 @@ theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime · intro h convert ← map_dvd g h <;> apply hinv⟩ -theorem MulEquiv.prime_iff (e : α ≃* β) : Prime p ↔ Prime (e p) := +theorem MulEquiv.prime_iff (e : M ≃* N) : Prime p ↔ Prime (e p) := ⟨fun h => (comap_prime e.symm e fun a => by simp) <| (e.symm_apply_apply p).substr h, comap_prime e e.symm fun a => by simp⟩ @@ -118,15 +118,15 @@ end Map end Prime -theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p) - {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by +theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero M] {p : M} (hp : Prime p) + {a b : M} : a ∣ p * b → p ∣ a ∨ a ∣ b := by rintro ⟨c, hc⟩ rcases hp.2.2 a c (hc ▸ dvd_mul_right _ _) with (h | ⟨x, rfl⟩) · exact Or.inl h · rw [mul_left_comm, mul_right_inj' hp.ne_zero] at hc exact Or.inr (hc.symm ▸ dvd_mul_right _ _) -theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p) +theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero M] {p a b : M} (hp : Prime p) (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by induction n with | zero => @@ -138,12 +138,12 @@ theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} apply mul_dvd_mul_left _ ((hp.dvd_or_dvd _).resolve_left h) rwa [← mul_dvd_mul_iff_left (pow_ne_zero n hp.ne_zero), ← pow_succ, mul_left_comm] -theorem Prime.pow_dvd_of_dvd_mul_right [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p) +theorem Prime.pow_dvd_of_dvd_mul_right [CancelCommMonoidWithZero M] {p a b : M} (hp : Prime p) (n : ℕ) (h : ¬p ∣ b) (h' : p ^ n ∣ a * b) : p ^ n ∣ a := by rw [mul_comm] at h' exact hp.pow_dvd_of_dvd_mul_left n h h' -theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α} +theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero M] {p a b : M} {n : ℕ} (hp : Prime p) (hpow : p ^ n.succ ∣ a ^ n.succ * b ^ n) (hb : ¬p ^ 2 ∣ b) : p ∣ a := by -- Suppose `p ∣ b`, write `b = p * x` and `hy : a ^ n.succ * b ^ n = p ^ n.succ * y`. rcases hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H | hbdiv @@ -161,7 +161,7 @@ theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWith rw [pow_two, ← mul_assoc] exact dvd_mul_right _ _ -theorem prime_pow_succ_dvd_mul {α : Type*} [CancelCommMonoidWithZero α] {p x y : α} (h : Prime p) +theorem prime_pow_succ_dvd_mul {M : Type*} [CancelCommMonoidWithZero M] {p x y : M} (h : Prime p) {i : ℕ} (hxy : p ^ (i + 1) ∣ x * y) : p ^ (i + 1) ∣ x ∨ p ∣ y := by rw [or_iff_not_imp_right] intro hy @@ -178,7 +178,7 @@ theorem prime_pow_succ_dvd_mul {α : Type*} [CancelCommMonoidWithZero α] {p x y We explicitly avoid stating that `p` is non-zero, this would require a semiring. Assuming only a monoid allows us to reuse irreducible for associated elements. -/ -structure Irreducible [Monoid α] (p : α) : Prop where +structure Irreducible [Monoid M] (p : M) : Prop where /-- `p` is not a unit -/ not_unit : ¬IsUnit p /-- if `p` factors then one factor is a unit -/ @@ -186,38 +186,38 @@ structure Irreducible [Monoid α] (p : α) : Prop where namespace Irreducible -theorem not_dvd_one [CommMonoid α] {p : α} (hp : Irreducible p) : ¬p ∣ 1 := +theorem not_dvd_one [CommMonoid M] {p : M} (hp : Irreducible p) : ¬p ∣ 1 := mt (isUnit_of_dvd_one ·) hp.not_unit -theorem isUnit_or_isUnit [Monoid α] {p : α} (hp : Irreducible p) {a b : α} (h : p = a * b) : +theorem isUnit_or_isUnit [Monoid M] {p : M} (hp : Irreducible p) {a b : M} (h : p = a * b) : IsUnit a ∨ IsUnit b := hp.isUnit_or_isUnit' a b h end Irreducible -theorem irreducible_iff [Monoid α] {p : α} : +theorem irreducible_iff [Monoid M] {p : M} : Irreducible p ↔ ¬IsUnit p ∧ ∀ a b, p = a * b → IsUnit a ∨ IsUnit b := ⟨fun h => ⟨h.1, h.2⟩, fun h => ⟨h.1, h.2⟩⟩ @[simp] -theorem not_irreducible_one [Monoid α] : ¬Irreducible (1 : α) := by simp [irreducible_iff] +theorem not_irreducible_one [Monoid M] : ¬Irreducible (1 : M) := by simp [irreducible_iff] -theorem Irreducible.ne_one [Monoid α] : ∀ {p : α}, Irreducible p → p ≠ 1 +theorem Irreducible.ne_one [Monoid M] : ∀ {p : M}, Irreducible p → p ≠ 1 | _, hp, rfl => not_irreducible_one hp @[simp] -theorem not_irreducible_zero [MonoidWithZero α] : ¬Irreducible (0 : α) +theorem not_irreducible_zero [MonoidWithZero M] : ¬Irreducible (0 : M) | ⟨hn0, h⟩ => - have : IsUnit (0 : α) ∨ IsUnit (0 : α) := h 0 0 (mul_zero 0).symm + have : IsUnit (0 : M) ∨ IsUnit (0 : M) := h 0 0 (mul_zero 0).symm this.elim hn0 hn0 -theorem Irreducible.ne_zero [MonoidWithZero α] : ∀ {p : α}, Irreducible p → p ≠ 0 +theorem Irreducible.ne_zero [MonoidWithZero M] : ∀ {p : M}, Irreducible p → p ≠ 0 | _, hp, rfl => not_irreducible_zero hp -theorem of_irreducible_mul {α} [Monoid α] {x y : α} : Irreducible (x * y) → IsUnit x ∨ IsUnit y +theorem of_irreducible_mul {M} [Monoid M] {x y : M} : Irreducible (x * y) → IsUnit x ∨ IsUnit y | ⟨_, h⟩ => h _ _ rfl -theorem not_irreducible_pow {α} [Monoid α] {x : α} {n : ℕ} (hn : n ≠ 1) : +theorem not_irreducible_pow {M} [Monoid M] {x : M} {n : ℕ} (hn : n ≠ 1) : ¬ Irreducible (x ^ n) := by cases n with | zero => simp @@ -227,7 +227,7 @@ theorem not_irreducible_pow {α} [Monoid α] {x : α} {n : ℕ} (hn : n ≠ 1) : rw [isUnit_pow_iff (Nat.succ_ne_succ.mp hn), or_self] at this exact h₁ (this.pow _) -theorem irreducible_or_factor {α} [Monoid α] (x : α) (h : ¬IsUnit x) : +theorem irreducible_or_factor {M} [Monoid M] (x : M) (h : ¬IsUnit x) : Irreducible x ∨ ∃ a b, ¬IsUnit a ∧ ¬IsUnit b ∧ a * b = x := by haveI := Classical.dec refine or_iff_not_imp_right.2 fun H => ?_ @@ -239,20 +239,26 @@ theorem irreducible_or_factor {α} [Monoid α] (x : α) (h : ¬IsUnit x) : exact H _ o.1 _ o.2 h.symm /-- If `p` and `q` are irreducible, then `p ∣ q` implies `q ∣ p`. -/ -theorem Irreducible.dvd_symm [Monoid α] {p q : α} (hp : Irreducible p) (hq : Irreducible q) : +theorem Irreducible.dvd_symm [Monoid M] {p q : M} (hp : Irreducible p) (hq : Irreducible q) : p ∣ q → q ∣ p := by rintro ⟨q', rfl⟩ rw [IsUnit.mul_right_dvd (Or.resolve_left (of_irreducible_mul hq) hp.not_unit)] -theorem Irreducible.dvd_comm [Monoid α] {p q : α} (hp : Irreducible p) (hq : Irreducible q) : +theorem Irreducible.dvd_comm [Monoid M] {p q : M} (hp : Irreducible p) (hq : Irreducible q) : p ∣ q ↔ q ∣ p := ⟨hp.dvd_symm hq, hq.dvd_symm hp⟩ +theorem Irreducible.of_map {F : Type*} [Monoid M] [Monoid N] [FunLike F M N] [MonoidHomClass F M N] + {f : F} [IsLocalRingHom f] {x} (hfx : Irreducible (f x)) : Irreducible x := + ⟨fun hu ↦ hfx.not_unit <| hu.map f, + by rintro p q rfl + exact (hfx.isUnit_or_isUnit <| map_mul f p q).imp (.of_map f _) (.of_map f _)⟩ + section -variable [Monoid α] +variable [Monoid M] -theorem irreducible_units_mul (a : αˣ) (b : α) : Irreducible (↑a * b) ↔ Irreducible b := by +theorem irreducible_units_mul (a : Mˣ) (b : M) : Irreducible (↑a * b) ↔ Irreducible b := by simp only [irreducible_iff, Units.isUnit_units_mul, and_congr_right_iff] refine fun _ => ⟨fun h A B HAB => ?_, fun h A B HAB => ?_⟩ · rw [← a.isUnit_units_mul] @@ -262,11 +268,11 @@ theorem irreducible_units_mul (a : αˣ) (b : α) : Irreducible (↑a * b) ↔ I apply h rw [mul_assoc, ← HAB, Units.inv_mul_cancel_left] -theorem irreducible_isUnit_mul {a b : α} (h : IsUnit a) : Irreducible (a * b) ↔ Irreducible b := +theorem irreducible_isUnit_mul {a b : M} (h : IsUnit a) : Irreducible (a * b) ↔ Irreducible b := let ⟨a, ha⟩ := h ha ▸ irreducible_units_mul a b -theorem irreducible_mul_units (a : αˣ) (b : α) : Irreducible (b * ↑a) ↔ Irreducible b := by +theorem irreducible_mul_units (a : Mˣ) (b : M) : Irreducible (b * ↑a) ↔ Irreducible b := by simp only [irreducible_iff, Units.isUnit_mul_units, and_congr_right_iff] refine fun _ => ⟨fun h A B HAB => ?_, fun h A B HAB => ?_⟩ · rw [← Units.isUnit_mul_units B a] @@ -276,11 +282,11 @@ theorem irreducible_mul_units (a : αˣ) (b : α) : Irreducible (b * ↑a) ↔ I apply h rw [← mul_assoc, ← HAB, Units.mul_inv_cancel_right] -theorem irreducible_mul_isUnit {a b : α} (h : IsUnit a) : Irreducible (b * a) ↔ Irreducible b := +theorem irreducible_mul_isUnit {a b : M} (h : IsUnit a) : Irreducible (b * a) ↔ Irreducible b := let ⟨a, ha⟩ := h ha ▸ irreducible_mul_units a b -theorem irreducible_mul_iff {a b : α} : +theorem irreducible_mul_iff {a b : M} : Irreducible (a * b) ↔ Irreducible a ∧ IsUnit b ∨ Irreducible b ∧ IsUnit a := by constructor · refine fun h => Or.imp (fun h' => ⟨?_, h'⟩) (fun h' => ⟨?_, h'⟩) (h.isUnit_or_isUnit rfl).symm @@ -294,7 +300,7 @@ end section CommMonoid -variable [CommMonoid α] {a : α} +variable [CommMonoid M] {a : M} theorem Irreducible.not_square (ha : Irreducible a) : ¬IsSquare a := by rw [isSquare_iff_exists_sq] @@ -307,22 +313,22 @@ end CommMonoid section CommMonoidWithZero -variable [CommMonoidWithZero α] +variable [CommMonoidWithZero M] -theorem Irreducible.prime_of_isPrimal {a : α} +theorem Irreducible.prime_of_isPrimal {a : M} (irr : Irreducible a) (primal : IsPrimal a) : Prime a := ⟨irr.ne_zero, irr.not_unit, fun a b dvd ↦ by obtain ⟨d₁, d₂, h₁, h₂, rfl⟩ := primal dvd exact (of_irreducible_mul irr).symm.imp (·.mul_right_dvd.mpr h₁) (·.mul_left_dvd.mpr h₂)⟩ -theorem Irreducible.prime [DecompositionMonoid α] {a : α} (irr : Irreducible a) : Prime a := +theorem Irreducible.prime [DecompositionMonoid M] {a : M} (irr : Irreducible a) : Prime a := irr.prime_of_isPrimal (DecompositionMonoid.primal a) end CommMonoidWithZero section CancelCommMonoidWithZero -variable [CancelCommMonoidWithZero α] {a p : α} +variable [CancelCommMonoidWithZero M] {a p : M} protected theorem Prime.irreducible (hp : Prime p) : Irreducible p := ⟨hp.not_unit, fun a b ↦ by @@ -333,10 +339,10 @@ protected theorem Prime.irreducible (hp : Prime p) : Irreducible p := (isUnit_of_dvd_one <| (mul_dvd_mul_iff_left <| left_ne_zero_of_mul hp.ne_zero).mp <| dvd_mul_of_dvd_left · _)⟩ -theorem irreducible_iff_prime [DecompositionMonoid α] {a : α} : Irreducible a ↔ Prime a := +theorem irreducible_iff_prime [DecompositionMonoid M] {a : M} : Irreducible a ↔ Prime a := ⟨Irreducible.prime, Prime.irreducible⟩ -theorem succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul (hp : Prime p) {a b : α} {k l : ℕ} : +theorem succ_dvd_or_succ_dvd_of_succ_sum_dvd_mul (hp : Prime p) {a b : M} {k l : ℕ} : p ^ k ∣ a → p ^ l ∣ b → p ^ (k + l + 1) ∣ a * b → p ^ (k + 1) ∣ a ∨ p ^ (l + 1) ∣ b := fun ⟨x, hx⟩ ⟨y, hy⟩ ⟨z, hz⟩ => have h : p ^ (k + l) * (x * y) = p ^ (k + l) * (p * z) := by @@ -359,8 +365,8 @@ end CancelCommMonoidWithZero /-- Two elements of a `Monoid` are `Associated` if one of them is another one multiplied by a unit on the right. -/ -def Associated [Monoid α] (x y : α) : Prop := - ∃ u : αˣ, x * u = y +def Associated [Monoid M] (x y : M) : Prop := + ∃ u : Mˣ, x * u = y /-- Notation for two elements of a monoid are associated, i.e. if one of them is another one multiplied by a unit on the right. -/ @@ -369,35 +375,35 @@ local infixl:50 " ~ᵤ " => Associated namespace Associated @[refl] -protected theorem refl [Monoid α] (x : α) : x ~ᵤ x := +protected theorem refl [Monoid M] (x : M) : x ~ᵤ x := ⟨1, by simp⟩ -protected theorem rfl [Monoid α] {x : α} : x ~ᵤ x := +protected theorem rfl [Monoid M] {x : M} : x ~ᵤ x := .refl x -instance [Monoid α] : IsRefl α Associated := +instance [Monoid M] : IsRefl M Associated := ⟨Associated.refl⟩ @[symm] -protected theorem symm [Monoid α] : ∀ {x y : α}, x ~ᵤ y → y ~ᵤ x +protected theorem symm [Monoid M] : ∀ {x y : M}, x ~ᵤ y → y ~ᵤ x | x, _, ⟨u, rfl⟩ => ⟨u⁻¹, by rw [mul_assoc, Units.mul_inv, mul_one]⟩ -instance [Monoid α] : IsSymm α Associated := +instance [Monoid M] : IsSymm M Associated := ⟨fun _ _ => Associated.symm⟩ -protected theorem comm [Monoid α] {x y : α} : x ~ᵤ y ↔ y ~ᵤ x := +protected theorem comm [Monoid M] {x y : M} : x ~ᵤ y ↔ y ~ᵤ x := ⟨Associated.symm, Associated.symm⟩ @[trans] -protected theorem trans [Monoid α] : ∀ {x y z : α}, x ~ᵤ y → y ~ᵤ z → x ~ᵤ z +protected theorem trans [Monoid M] : ∀ {x y z : M}, x ~ᵤ y → y ~ᵤ z → x ~ᵤ z | x, _, _, ⟨u, rfl⟩, ⟨v, rfl⟩ => ⟨u * v, by rw [Units.val_mul, mul_assoc]⟩ -instance [Monoid α] : IsTrans α Associated := +instance [Monoid M] : IsTrans M Associated := ⟨fun _ _ _ => Associated.trans⟩ /-- The setoid of the relation `x ~ᵤ y` iff there is a unit `u` such that `x * u = y` -/ -protected def setoid (α : Type*) [Monoid α] : - Setoid α where +protected def setoid (M : Type*) [Monoid M] : + Setoid M where r := Associated iseqv := ⟨Associated.refl, Associated.symm, Associated.trans⟩ @@ -410,11 +416,11 @@ end Associated attribute [local instance] Associated.setoid -theorem unit_associated_one [Monoid α] {u : αˣ} : (u : α) ~ᵤ 1 := +theorem unit_associated_one [Monoid M] {u : Mˣ} : (u : M) ~ᵤ 1 := ⟨u⁻¹, Units.mul_inv u⟩ @[simp] -theorem associated_one_iff_isUnit [Monoid α] {a : α} : (a : α) ~ᵤ 1 ↔ IsUnit a := +theorem associated_one_iff_isUnit [Monoid M] {a : M} : (a : M) ~ᵤ 1 ↔ IsUnit a := Iff.intro (fun h => let ⟨c, h⟩ := h.symm @@ -422,98 +428,98 @@ theorem associated_one_iff_isUnit [Monoid α] {a : α} : (a : α) ~ᵤ 1 ↔ IsU fun ⟨c, h⟩ => Associated.symm ⟨c, by simp [h]⟩ @[simp] -theorem associated_zero_iff_eq_zero [MonoidWithZero α] (a : α) : a ~ᵤ 0 ↔ a = 0 := +theorem associated_zero_iff_eq_zero [MonoidWithZero M] (a : M) : a ~ᵤ 0 ↔ a = 0 := Iff.intro (fun h => by let ⟨u, h⟩ := h.symm simpa using h.symm) fun h => h ▸ Associated.refl a -theorem associated_one_of_mul_eq_one [CommMonoid α] {a : α} (b : α) (hab : a * b = 1) : a ~ᵤ 1 := - show (Units.mkOfMulEqOne a b hab : α) ~ᵤ 1 from unit_associated_one +theorem associated_one_of_mul_eq_one [CommMonoid M] {a : M} (b : M) (hab : a * b = 1) : a ~ᵤ 1 := + show (Units.mkOfMulEqOne a b hab : M) ~ᵤ 1 from unit_associated_one -theorem associated_one_of_associated_mul_one [CommMonoid α] {a b : α} : a * b ~ᵤ 1 → a ~ᵤ 1 +theorem associated_one_of_associated_mul_one [CommMonoid M] {a b : M} : a * b ~ᵤ 1 → a ~ᵤ 1 | ⟨u, h⟩ => associated_one_of_mul_eq_one (b * u) <| by simpa [mul_assoc] using h -theorem associated_mul_unit_left {β : Type*} [Monoid β] (a u : β) (hu : IsUnit u) : +theorem associated_mul_unit_left {N : Type*} [Monoid N] (a u : N) (hu : IsUnit u) : Associated (a * u) a := let ⟨u', hu⟩ := hu ⟨u'⁻¹, hu ▸ Units.mul_inv_cancel_right _ _⟩ -theorem associated_unit_mul_left {β : Type*} [CommMonoid β] (a u : β) (hu : IsUnit u) : +theorem associated_unit_mul_left {N : Type*} [CommMonoid N] (a u : N) (hu : IsUnit u) : Associated (u * a) a := by rw [mul_comm] exact associated_mul_unit_left _ _ hu -theorem associated_mul_unit_right {β : Type*} [Monoid β] (a u : β) (hu : IsUnit u) : +theorem associated_mul_unit_right {N : Type*} [Monoid N] (a u : N) (hu : IsUnit u) : Associated a (a * u) := (associated_mul_unit_left a u hu).symm -theorem associated_unit_mul_right {β : Type*} [CommMonoid β] (a u : β) (hu : IsUnit u) : +theorem associated_unit_mul_right {N : Type*} [CommMonoid N] (a u : N) (hu : IsUnit u) : Associated a (u * a) := (associated_unit_mul_left a u hu).symm -theorem associated_mul_isUnit_left_iff {β : Type*} [Monoid β] {a u b : β} (hu : IsUnit u) : +theorem associated_mul_isUnit_left_iff {N : Type*} [Monoid N] {a u b : N} (hu : IsUnit u) : Associated (a * u) b ↔ Associated a b := ⟨(associated_mul_unit_right _ _ hu).trans, (associated_mul_unit_left _ _ hu).trans⟩ -theorem associated_isUnit_mul_left_iff {β : Type*} [CommMonoid β] {u a b : β} (hu : IsUnit u) : +theorem associated_isUnit_mul_left_iff {N : Type*} [CommMonoid N] {u a b : N} (hu : IsUnit u) : Associated (u * a) b ↔ Associated a b := by rw [mul_comm] exact associated_mul_isUnit_left_iff hu -theorem associated_mul_isUnit_right_iff {β : Type*} [Monoid β] {a b u : β} (hu : IsUnit u) : +theorem associated_mul_isUnit_right_iff {N : Type*} [Monoid N] {a b u : N} (hu : IsUnit u) : Associated a (b * u) ↔ Associated a b := Associated.comm.trans <| (associated_mul_isUnit_left_iff hu).trans Associated.comm -theorem associated_isUnit_mul_right_iff {β : Type*} [CommMonoid β] {a u b : β} (hu : IsUnit u) : +theorem associated_isUnit_mul_right_iff {N : Type*} [CommMonoid N] {a u b : N} (hu : IsUnit u) : Associated a (u * b) ↔ Associated a b := Associated.comm.trans <| (associated_isUnit_mul_left_iff hu).trans Associated.comm @[simp] -theorem associated_mul_unit_left_iff {β : Type*} [Monoid β] {a b : β} {u : Units β} : +theorem associated_mul_unit_left_iff {N : Type*} [Monoid N] {a b : N} {u : Units N} : Associated (a * u) b ↔ Associated a b := associated_mul_isUnit_left_iff u.isUnit @[simp] -theorem associated_unit_mul_left_iff {β : Type*} [CommMonoid β] {a b : β} {u : Units β} : +theorem associated_unit_mul_left_iff {N : Type*} [CommMonoid N] {a b : N} {u : Units N} : Associated (↑u * a) b ↔ Associated a b := associated_isUnit_mul_left_iff u.isUnit @[simp] -theorem associated_mul_unit_right_iff {β : Type*} [Monoid β] {a b : β} {u : Units β} : +theorem associated_mul_unit_right_iff {N : Type*} [Monoid N] {a b : N} {u : Units N} : Associated a (b * u) ↔ Associated a b := associated_mul_isUnit_right_iff u.isUnit @[simp] -theorem associated_unit_mul_right_iff {β : Type*} [CommMonoid β] {a b : β} {u : Units β} : +theorem associated_unit_mul_right_iff {N : Type*} [CommMonoid N] {a b : N} {u : Units N} : Associated a (↑u * b) ↔ Associated a b := associated_isUnit_mul_right_iff u.isUnit -theorem Associated.mul_left [Monoid α] (a : α) {b c : α} (h : b ~ᵤ c) : a * b ~ᵤ a * c := by +theorem Associated.mul_left [Monoid M] (a : M) {b c : M} (h : b ~ᵤ c) : a * b ~ᵤ a * c := by obtain ⟨d, rfl⟩ := h; exact ⟨d, mul_assoc _ _ _⟩ -theorem Associated.mul_right [CommMonoid α] {a b : α} (h : a ~ᵤ b) (c : α) : a * c ~ᵤ b * c := by +theorem Associated.mul_right [CommMonoid M] {a b : M} (h : a ~ᵤ b) (c : M) : a * c ~ᵤ b * c := by obtain ⟨d, rfl⟩ := h; exact ⟨d, mul_right_comm _ _ _⟩ -theorem Associated.mul_mul [CommMonoid α] {a₁ a₂ b₁ b₂ : α} +theorem Associated.mul_mul [CommMonoid M] {a₁ a₂ b₁ b₂ : M} (h₁ : a₁ ~ᵤ b₁) (h₂ : a₂ ~ᵤ b₂) : a₁ * a₂ ~ᵤ b₁ * b₂ := (h₁.mul_right _).trans (h₂.mul_left _) -theorem Associated.pow_pow [CommMonoid α] {a b : α} {n : ℕ} (h : a ~ᵤ b) : a ^ n ~ᵤ b ^ n := by +theorem Associated.pow_pow [CommMonoid M] {a b : M} {n : ℕ} (h : a ~ᵤ b) : a ^ n ~ᵤ b ^ n := by induction n with | zero => simp [Associated.refl] | succ n ih => convert h.mul_mul ih <;> rw [pow_succ'] -protected theorem Associated.dvd [Monoid α] {a b : α} : a ~ᵤ b → a ∣ b := fun ⟨u, hu⟩ => +protected theorem Associated.dvd [Monoid M] {a b : M} : a ~ᵤ b → a ∣ b := fun ⟨u, hu⟩ => ⟨u, hu.symm⟩ -protected theorem Associated.dvd' [Monoid α] {a b : α} (h : a ~ᵤ b) : b ∣ a := +protected theorem Associated.dvd' [Monoid M] {a b : M} (h : a ~ᵤ b) : b ∣ a := h.symm.dvd -protected theorem Associated.dvd_dvd [Monoid α] {a b : α} (h : a ~ᵤ b) : a ∣ b ∧ b ∣ a := +protected theorem Associated.dvd_dvd [Monoid M] {a b : M} (h : a ~ᵤ b) : a ∣ b ∧ b ∣ a := ⟨h.dvd, h.symm.dvd⟩ -theorem associated_of_dvd_dvd [CancelMonoidWithZero α] {a b : α} (hab : a ∣ b) (hba : b ∣ a) : +theorem associated_of_dvd_dvd [CancelMonoidWithZero M] {a b : M} (hab : a ∣ b) (hba : b ∣ a) : a ~ᵤ b := by rcases hab with ⟨c, rfl⟩ rcases hba with ⟨d, a_eq⟩ @@ -529,40 +535,40 @@ theorem associated_of_dvd_dvd [CancelMonoidWithZero α] {a b : α} (hab : a ∣ have hdc : d * c = 1 := mul_left_cancel₀ hac0 this exact ⟨⟨c, d, hcd, hdc⟩, rfl⟩ -theorem dvd_dvd_iff_associated [CancelMonoidWithZero α] {a b : α} : a ∣ b ∧ b ∣ a ↔ a ~ᵤ b := +theorem dvd_dvd_iff_associated [CancelMonoidWithZero M] {a b : M} : a ∣ b ∧ b ∣ a ↔ a ~ᵤ b := ⟨fun ⟨h1, h2⟩ => associated_of_dvd_dvd h1 h2, Associated.dvd_dvd⟩ -instance [CancelMonoidWithZero α] [DecidableRel ((· ∣ ·) : α → α → Prop)] : - DecidableRel ((· ~ᵤ ·) : α → α → Prop) := fun _ _ => decidable_of_iff _ dvd_dvd_iff_associated +instance [CancelMonoidWithZero M] [DecidableRel ((· ∣ ·) : M → M → Prop)] : + DecidableRel ((· ~ᵤ ·) : M → M → Prop) := fun _ _ => decidable_of_iff _ dvd_dvd_iff_associated -theorem Associated.dvd_iff_dvd_left [Monoid α] {a b c : α} (h : a ~ᵤ b) : a ∣ c ↔ b ∣ c := +theorem Associated.dvd_iff_dvd_left [Monoid M] {a b c : M} (h : a ~ᵤ b) : a ∣ c ↔ b ∣ c := let ⟨_, hu⟩ := h hu ▸ Units.mul_right_dvd.symm -theorem Associated.dvd_iff_dvd_right [Monoid α] {a b c : α} (h : b ~ᵤ c) : a ∣ b ↔ a ∣ c := +theorem Associated.dvd_iff_dvd_right [Monoid M] {a b c : M} (h : b ~ᵤ c) : a ∣ b ↔ a ∣ c := let ⟨_, hu⟩ := h hu ▸ Units.dvd_mul_right.symm -theorem Associated.eq_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a = 0 ↔ b = 0 := by +theorem Associated.eq_zero_iff [MonoidWithZero M] {a b : M} (h : a ~ᵤ b) : a = 0 ↔ b = 0 := by obtain ⟨u, rfl⟩ := h rw [← Units.eq_mul_inv_iff_mul_eq, zero_mul] -theorem Associated.ne_zero_iff [MonoidWithZero α] {a b : α} (h : a ~ᵤ b) : a ≠ 0 ↔ b ≠ 0 := +theorem Associated.ne_zero_iff [MonoidWithZero M] {a b : M} (h : a ~ᵤ b) : a ≠ 0 ↔ b ≠ 0 := not_congr h.eq_zero_iff -theorem Associated.neg_left [Monoid α] [HasDistribNeg α] {a b : α} (h : Associated a b) : +theorem Associated.neg_left [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : Associated (-a) b := let ⟨u, hu⟩ := h; ⟨-u, by simp [hu]⟩ -theorem Associated.neg_right [Monoid α] [HasDistribNeg α] {a b : α} (h : Associated a b) : +theorem Associated.neg_right [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : Associated a (-b) := h.symm.neg_left.symm -theorem Associated.neg_neg [Monoid α] [HasDistribNeg α] {a b : α} (h : Associated a b) : +theorem Associated.neg_neg [Monoid M] [HasDistribNeg M] {a b : M} (h : Associated a b) : Associated (-a) (-b) := h.neg_left.neg_right -protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) (hp : Prime p) : +protected theorem Associated.prime [CommMonoidWithZero M] {p q : M} (h : p ~ᵤ q) (hp : Prime p) : Prime q := ⟨h.ne_zero_iff.1 hp.ne_zero, let ⟨u, hu⟩ := h @@ -572,7 +578,7 @@ protected theorem Associated.prime [CommMonoidWithZero α] {p q : α} (h : p ~ intro a b exact hp.dvd_or_dvd⟩⟩ -theorem prime_mul_iff [CancelCommMonoidWithZero α] {x y : α} : +theorem prime_mul_iff [CancelCommMonoidWithZero M] {x y : M} : Prime (x * y) ↔ (Prime x ∧ IsUnit y) ∨ (IsUnit x ∧ Prime y) := by refine ⟨fun h ↦ ?_, ?_⟩ · rcases of_irreducible_mul h.irreducible with hx | hy @@ -583,7 +589,7 @@ theorem prime_mul_iff [CancelCommMonoidWithZero α] {x y : α} : · exact (associated_unit_mul_right y x hx).prime hy @[simp] -lemma prime_pow_iff [CancelCommMonoidWithZero α] {p : α} {n : ℕ} : +lemma prime_pow_iff [CancelCommMonoidWithZero M] {p : M} {n : ℕ} : Prime (p ^ n) ↔ Prime p ∧ n = 1 := by refine ⟨fun hp ↦ ?_, fun ⟨hp, hn⟩ ↦ by simpa [hn]⟩ suffices n = 1 by aesop @@ -598,7 +604,7 @@ lemma prime_pow_iff [CancelCommMonoidWithZero α] {p : α} {n : ℕ} : · exfalso exact hpn.not_unit (hp.pow n) -theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) : +theorem Irreducible.dvd_iff [Monoid M] {x y : M} (hx : Irreducible x) : y ∣ x ↔ IsUnit y ∨ Associated x y := by constructor · rintro ⟨z, hz⟩ @@ -610,67 +616,67 @@ theorem Irreducible.dvd_iff [Monoid α] {x y : α} (hx : Irreducible x) : · exact hy.dvd · exact h.symm.dvd -theorem Irreducible.associated_of_dvd [Monoid α] {p q : α} (p_irr : Irreducible p) +theorem Irreducible.associated_of_dvd [Monoid M] {p q : M} (p_irr : Irreducible p) (q_irr : Irreducible q) (dvd : p ∣ q) : Associated p q := ((q_irr.dvd_iff.mp dvd).resolve_left p_irr.not_unit).symm -theorem Irreducible.dvd_irreducible_iff_associated [Monoid α] {p q : α} +theorem Irreducible.dvd_irreducible_iff_associated [Monoid M] {p q : M} (pp : Irreducible p) (qp : Irreducible q) : p ∣ q ↔ Associated p q := ⟨Irreducible.associated_of_dvd pp qp, Associated.dvd⟩ -theorem Prime.associated_of_dvd [CancelCommMonoidWithZero α] {p q : α} (p_prime : Prime p) +theorem Prime.associated_of_dvd [CancelCommMonoidWithZero M] {p q : M} (p_prime : Prime p) (q_prime : Prime q) (dvd : p ∣ q) : Associated p q := p_prime.irreducible.associated_of_dvd q_prime.irreducible dvd -theorem Prime.dvd_prime_iff_associated [CancelCommMonoidWithZero α] {p q : α} (pp : Prime p) +theorem Prime.dvd_prime_iff_associated [CancelCommMonoidWithZero M] {p q : M} (pp : Prime p) (qp : Prime q) : p ∣ q ↔ Associated p q := pp.irreducible.dvd_irreducible_iff_associated qp.irreducible -theorem Associated.prime_iff [CommMonoidWithZero α] {p q : α} (h : p ~ᵤ q) : Prime p ↔ Prime q := +theorem Associated.prime_iff [CommMonoidWithZero M] {p q : M} (h : p ~ᵤ q) : Prime p ↔ Prime q := ⟨h.prime, h.symm.prime⟩ -protected theorem Associated.isUnit [Monoid α] {a b : α} (h : a ~ᵤ b) : IsUnit a → IsUnit b := +protected theorem Associated.isUnit [Monoid M] {a b : M} (h : a ~ᵤ b) : IsUnit a → IsUnit b := let ⟨u, hu⟩ := h fun ⟨v, hv⟩ => ⟨v * u, by simp [hv, hu.symm]⟩ -theorem Associated.isUnit_iff [Monoid α] {a b : α} (h : a ~ᵤ b) : IsUnit a ↔ IsUnit b := +theorem Associated.isUnit_iff [Monoid M] {a b : M} (h : a ~ᵤ b) : IsUnit a ↔ IsUnit b := ⟨h.isUnit, h.symm.isUnit⟩ -theorem Irreducible.isUnit_iff_not_associated_of_dvd [Monoid α] - {x y : α} (hx : Irreducible x) (hy : y ∣ x) : IsUnit y ↔ ¬ Associated x y := +theorem Irreducible.isUnit_iff_not_associated_of_dvd [Monoid M] + {x y : M} (hx : Irreducible x) (hy : y ∣ x) : IsUnit y ↔ ¬ Associated x y := ⟨fun hy hxy => hx.1 (hxy.symm.isUnit hy), (hx.dvd_iff.mp hy).resolve_right⟩ -protected theorem Associated.irreducible [Monoid α] {p q : α} (h : p ~ᵤ q) (hp : Irreducible p) : +protected theorem Associated.irreducible [Monoid M] {p q : M} (h : p ~ᵤ q) (hp : Irreducible p) : Irreducible q := ⟨mt h.symm.isUnit hp.1, let ⟨u, hu⟩ := h fun a b hab => - have hpab : p = a * (b * (u⁻¹ : αˣ)) := + have hpab : p = a * (b * (u⁻¹ : Mˣ)) := calc - p = p * u * (u⁻¹ : αˣ) := by simp + p = p * u * (u⁻¹ : Mˣ) := by simp _ = _ := by rw [hu]; simp [hab, mul_assoc] (hp.isUnit_or_isUnit hpab).elim Or.inl fun ⟨v, hv⟩ => Or.inr ⟨v * u, by simp [hv]⟩⟩ -protected theorem Associated.irreducible_iff [Monoid α] {p q : α} (h : p ~ᵤ q) : +protected theorem Associated.irreducible_iff [Monoid M] {p q : M} (h : p ~ᵤ q) : Irreducible p ↔ Irreducible q := ⟨h.irreducible, h.symm.irreducible⟩ -theorem Associated.of_mul_left [CancelCommMonoidWithZero α] {a b c d : α} (h : a * b ~ᵤ c * d) +theorem Associated.of_mul_left [CancelCommMonoidWithZero M] {a b c d : M} (h : a * b ~ᵤ c * d) (h₁ : a ~ᵤ c) (ha : a ≠ 0) : b ~ᵤ d := let ⟨u, hu⟩ := h let ⟨v, hv⟩ := Associated.symm h₁ - ⟨u * (v : αˣ), + ⟨u * (v : Mˣ), mul_left_cancel₀ ha (by - rw [← hv, mul_assoc c (v : α) d, mul_left_comm c, ← hu] + rw [← hv, mul_assoc c (v : M) d, mul_left_comm c, ← hu] simp [hv.symm, mul_assoc, mul_comm, mul_left_comm])⟩ -theorem Associated.of_mul_right [CancelCommMonoidWithZero α] {a b c d : α} : +theorem Associated.of_mul_right [CancelCommMonoidWithZero M] {a b c d : M} : a * b ~ᵤ c * d → b ~ᵤ d → b ≠ 0 → a ~ᵤ c := by rw [mul_comm a, mul_comm c]; exact Associated.of_mul_left -theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ} +theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero M] {p₁ p₂ : M} {k₁ k₂ : ℕ} (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := by have : p₁ ∣ p₂ ^ k₂ := by rw [← h.dvd_iff_dvd_right] @@ -678,37 +684,37 @@ theorem Associated.of_pow_associated_of_prime [CancelCommMonoidWithZero α] {p rw [← hp₁.dvd_prime_iff_associated hp₂] exact hp₁.dvd_of_dvd_pow this -theorem Associated.of_pow_associated_of_prime' [CancelCommMonoidWithZero α] {p₁ p₂ : α} {k₁ k₂ : ℕ} +theorem Associated.of_pow_associated_of_prime' [CancelCommMonoidWithZero M] {p₁ p₂ : M} {k₁ k₂ : ℕ} (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₂ : 0 < k₂) (h : p₁ ^ k₁ ~ᵤ p₂ ^ k₂) : p₁ ~ᵤ p₂ := (h.symm.of_pow_associated_of_prime hp₂ hp₁ hk₂).symm /-- See also `Irreducible.coprime_iff_not_dvd`. -/ -lemma Irreducible.isRelPrime_iff_not_dvd [Monoid α] {p n : α} (hp : Irreducible p) : +lemma Irreducible.isRelPrime_iff_not_dvd [Monoid M] {p n : M} (hp : Irreducible p) : IsRelPrime p n ↔ ¬ p ∣ n := by refine ⟨fun h contra ↦ hp.not_unit (h dvd_rfl contra), fun hpn d hdp hdn ↦ ?_⟩ contrapose! hpn suffices Associated p d from this.dvd.trans hdn exact (hp.dvd_iff.mp hdp).resolve_left hpn -lemma Irreducible.dvd_or_isRelPrime [Monoid α] {p n : α} (hp : Irreducible p) : +lemma Irreducible.dvd_or_isRelPrime [Monoid M] {p n : M} (hp : Irreducible p) : p ∣ n ∨ IsRelPrime p n := Classical.or_iff_not_imp_left.mpr hp.isRelPrime_iff_not_dvd.2 section UniqueUnits -variable [Monoid α] [Unique αˣ] +variable [Monoid M] [Subsingleton Mˣ] -theorem associated_iff_eq {x y : α} : x ~ᵤ y ↔ x = y := by +theorem associated_iff_eq {x y : M} : x ~ᵤ y ↔ x = y := by constructor · rintro ⟨c, rfl⟩ rw [units_eq_one c, Units.val_one, mul_one] · rintro rfl rfl -theorem associated_eq_eq : (Associated : α → α → Prop) = Eq := by +theorem associated_eq_eq : (Associated : M → M → Prop) = Eq := by ext rw [associated_iff_eq] -theorem prime_dvd_prime_iff_eq {M : Type*} [CancelCommMonoidWithZero M] [Unique Mˣ] {p q : M} +theorem prime_dvd_prime_iff_eq {M : Type*} [CancelCommMonoidWithZero M] [Subsingleton Mˣ] {p q : M} (pp : Prime p) (qp : Prime q) : p ∣ q ↔ p = q := by rw [pp.dvd_prime_iff_associated qp, ← associated_eq_eq] @@ -716,7 +722,7 @@ end UniqueUnits section UniqueUnits₀ -variable {R : Type*} [CancelCommMonoidWithZero R] [Unique Rˣ] {p₁ p₂ : R} {k₁ k₂ : ℕ} +variable {R : Type*} [CancelCommMonoidWithZero R] [Subsingleton Rˣ] {p₁ p₂ : R} {k₁ k₂ : ℕ} theorem eq_of_prime_pow_eq (hp₁ : Prime p₁) (hp₂ : Prime p₂) (hk₁ : 0 < k₁) (h : p₁ ^ k₁ = p₂ ^ k₂) : p₁ = p₂ := by @@ -732,86 +738,86 @@ end UniqueUnits₀ /-- The quotient of a monoid by the `Associated` relation. Two elements `x` and `y` are associated iff there is a unit `u` such that `x * u = y`. There is a natural - monoid structure on `Associates α`. -/ -abbrev Associates (α : Type*) [Monoid α] : Type _ := - Quotient (Associated.setoid α) + monoid structure on `Associates M`. -/ +abbrev Associates (M : Type*) [Monoid M] : Type _ := + Quotient (Associated.setoid M) namespace Associates open Associated -/-- The canonical quotient map from a monoid `α` into the `Associates` of `α` -/ -protected abbrev mk {α : Type*} [Monoid α] (a : α) : Associates α := +/-- The canonical quotient map from a monoid `M` into the `Associates` of `M` -/ +protected abbrev mk {M : Type*} [Monoid M] (a : M) : Associates M := ⟦a⟧ -instance [Monoid α] : Inhabited (Associates α) := +instance [Monoid M] : Inhabited (Associates M) := ⟨⟦1⟧⟩ -theorem mk_eq_mk_iff_associated [Monoid α] {a b : α} : Associates.mk a = Associates.mk b ↔ a ~ᵤ b := +theorem mk_eq_mk_iff_associated [Monoid M] {a b : M} : Associates.mk a = Associates.mk b ↔ a ~ᵤ b := Iff.intro Quotient.exact Quot.sound -theorem quotient_mk_eq_mk [Monoid α] (a : α) : ⟦a⟧ = Associates.mk a := +theorem quotient_mk_eq_mk [Monoid M] (a : M) : ⟦a⟧ = Associates.mk a := rfl -theorem quot_mk_eq_mk [Monoid α] (a : α) : Quot.mk Setoid.r a = Associates.mk a := +theorem quot_mk_eq_mk [Monoid M] (a : M) : Quot.mk Setoid.r a = Associates.mk a := rfl @[simp] -theorem quot_out [Monoid α] (a : Associates α) : Associates.mk (Quot.out a) = a := by +theorem quot_out [Monoid M] (a : Associates M) : Associates.mk (Quot.out a) = a := by rw [← quot_mk_eq_mk, Quot.out_eq] -theorem mk_quot_out [Monoid α] (a : α) : Quot.out (Associates.mk a) ~ᵤ a := by +theorem mk_quot_out [Monoid M] (a : M) : Quot.out (Associates.mk a) ~ᵤ a := by rw [← Associates.mk_eq_mk_iff_associated, Associates.quot_out] -theorem forall_associated [Monoid α] {p : Associates α → Prop} : +theorem forall_associated [Monoid M] {p : Associates M → Prop} : (∀ a, p a) ↔ ∀ a, p (Associates.mk a) := Iff.intro (fun h _ => h _) fun h a => Quotient.inductionOn a h -theorem mk_surjective [Monoid α] : Function.Surjective (@Associates.mk α _) := +theorem mk_surjective [Monoid M] : Function.Surjective (@Associates.mk M _) := forall_associated.2 fun a => ⟨a, rfl⟩ -instance [Monoid α] : One (Associates α) := +instance [Monoid M] : One (Associates M) := ⟨⟦1⟧⟩ @[simp] -theorem mk_one [Monoid α] : Associates.mk (1 : α) = 1 := +theorem mk_one [Monoid M] : Associates.mk (1 : M) = 1 := rfl -theorem one_eq_mk_one [Monoid α] : (1 : Associates α) = Associates.mk 1 := +theorem one_eq_mk_one [Monoid M] : (1 : Associates M) = Associates.mk 1 := rfl @[simp] -theorem mk_eq_one [Monoid α] {a : α} : Associates.mk a = 1 ↔ IsUnit a := by +theorem mk_eq_one [Monoid M] {a : M} : Associates.mk a = 1 ↔ IsUnit a := by rw [← mk_one, mk_eq_mk_iff_associated, associated_one_iff_isUnit] -instance [Monoid α] : Bot (Associates α) := +instance [Monoid M] : Bot (Associates M) := ⟨1⟩ -theorem bot_eq_one [Monoid α] : (⊥ : Associates α) = 1 := +theorem bot_eq_one [Monoid M] : (⊥ : Associates M) = 1 := rfl -theorem exists_rep [Monoid α] (a : Associates α) : ∃ a0 : α, Associates.mk a0 = a := +theorem exists_rep [Monoid M] (a : Associates M) : ∃ a0 : M, Associates.mk a0 = a := Quot.exists_rep a -instance [Monoid α] [Subsingleton α] : - Unique (Associates α) where +instance [Monoid M] [Subsingleton M] : + Unique (Associates M) where default := 1 uniq := forall_associated.2 fun _ ↦ mk_eq_one.2 <| isUnit_of_subsingleton _ -theorem mk_injective [Monoid α] [Unique (Units α)] : Function.Injective (@Associates.mk α _) := +theorem mk_injective [Monoid M] [Subsingleton Mˣ] : Function.Injective (@Associates.mk M _) := fun _ _ h => associated_iff_eq.mp (Associates.mk_eq_mk_iff_associated.mp h) section CommMonoid -variable [CommMonoid α] +variable [CommMonoid M] -instance instMul : Mul (Associates α) := +instance instMul : Mul (Associates M) := ⟨Quotient.map₂ (· * ·) fun _ _ h₁ _ _ h₂ ↦ h₁.mul_mul h₂⟩ -theorem mk_mul_mk {x y : α} : Associates.mk x * Associates.mk y = Associates.mk (x * y) := +theorem mk_mul_mk {x y : M} : Associates.mk x * Associates.mk y = Associates.mk (x * y) := rfl -instance instCommMonoid : CommMonoid (Associates α) where +instance instCommMonoid : CommMonoid (Associates M) where one := 1 mul := (· * ·) mul_one a' := Quotient.inductionOn a' fun a => show ⟦a * 1⟧ = ⟦a⟧ by simp @@ -822,32 +828,32 @@ instance instCommMonoid : CommMonoid (Associates α) where mul_comm a' b' := Quotient.inductionOn₂ a' b' fun a b => show ⟦a * b⟧ = ⟦b * a⟧ by rw [mul_comm] -instance instPreorder : Preorder (Associates α) where +instance instPreorder : Preorder (Associates M) where le := Dvd.dvd le_refl := dvd_refl le_trans a b c := dvd_trans /-- `Associates.mk` as a `MonoidHom`. -/ -protected def mkMonoidHom : α →* Associates α where +protected def mkMonoidHom : M →* Associates M where toFun := Associates.mk map_one' := mk_one map_mul' _ _ := mk_mul_mk @[simp] -theorem mkMonoidHom_apply (a : α) : Associates.mkMonoidHom a = Associates.mk a := +theorem mkMonoidHom_apply (a : M) : Associates.mkMonoidHom a = Associates.mk a := rfl -theorem associated_map_mk {f : Associates α →* α} (hinv : Function.RightInverse f Associates.mk) - (a : α) : a ~ᵤ f (Associates.mk a) := +theorem associated_map_mk {f : Associates M →* M} (hinv : Function.RightInverse f Associates.mk) + (a : M) : a ~ᵤ f (Associates.mk a) := Associates.mk_eq_mk_iff_associated.1 (hinv (Associates.mk a)).symm -theorem mk_pow (a : α) (n : ℕ) : Associates.mk (a ^ n) = Associates.mk a ^ n := by +theorem mk_pow (a : M) (n : ℕ) : Associates.mk (a ^ n) = Associates.mk a ^ n := by induction n <;> simp [*, pow_succ, Associates.mk_mul_mk.symm] -theorem dvd_eq_le : ((· ∣ ·) : Associates α → Associates α → Prop) = (· ≤ ·) := +theorem dvd_eq_le : ((· ∣ ·) : Associates M → Associates M → Prop) = (· ≤ ·) := rfl -instance uniqueUnits : Unique (Associates α)ˣ where +instance uniqueUnits : Unique (Associates M)ˣ where uniq := by rintro ⟨a, b, hab, hba⟩ revert hab hba @@ -858,16 +864,16 @@ instance uniqueUnits : Unique (Associates α)ˣ where @[deprecated (since := "2024-07-22")] protected alias units_eq_one := Subsingleton.elim @[simp] -theorem coe_unit_eq_one (u : (Associates α)ˣ) : (u : Associates α) = 1 := by +theorem coe_unit_eq_one (u : (Associates M)ˣ) : (u : Associates M) = 1 := by simp [eq_iff_true_of_subsingleton] -theorem isUnit_iff_eq_one (a : Associates α) : IsUnit a ↔ a = 1 := +theorem isUnit_iff_eq_one (a : Associates M) : IsUnit a ↔ a = 1 := Iff.intro (fun ⟨_, h⟩ => h ▸ coe_unit_eq_one _) fun h => h.symm ▸ isUnit_one -theorem isUnit_iff_eq_bot {a : Associates α} : IsUnit a ↔ a = ⊥ := by +theorem isUnit_iff_eq_bot {a : Associates M} : IsUnit a ↔ a = ⊥ := by rw [Associates.isUnit_iff_eq_one, bot_eq_one] -theorem isUnit_mk {a : α} : IsUnit (Associates.mk a) ↔ IsUnit a := +theorem isUnit_mk {a : M} : IsUnit (Associates.mk a) ↔ IsUnit a := calc IsUnit (Associates.mk a) ↔ a ~ᵤ 1 := by rw [isUnit_iff_eq_one, one_eq_mk_one, mk_eq_mk_iff_associated] @@ -875,27 +881,27 @@ theorem isUnit_mk {a : α} : IsUnit (Associates.mk a) ↔ IsUnit a := section Order -theorem mul_mono {a b c d : Associates α} (h₁ : a ≤ b) (h₂ : c ≤ d) : a * c ≤ b * d := +theorem mul_mono {a b c d : Associates M} (h₁ : a ≤ b) (h₂ : c ≤ d) : a * c ≤ b * d := let ⟨x, hx⟩ := h₁ let ⟨y, hy⟩ := h₂ ⟨x * y, by simp [hx, hy, mul_comm, mul_assoc, mul_left_comm]⟩ -theorem one_le {a : Associates α} : 1 ≤ a := +theorem one_le {a : Associates M} : 1 ≤ a := Dvd.intro _ (one_mul a) -theorem le_mul_right {a b : Associates α} : a ≤ a * b := +theorem le_mul_right {a b : Associates M} : a ≤ a * b := ⟨b, rfl⟩ -theorem le_mul_left {a b : Associates α} : a ≤ b * a := by rw [mul_comm]; exact le_mul_right +theorem le_mul_left {a b : Associates M} : a ≤ b * a := by rw [mul_comm]; exact le_mul_right -instance instOrderBot : OrderBot (Associates α) where +instance instOrderBot : OrderBot (Associates M) where bot := 1 bot_le _ := one_le end Order @[simp] -theorem mk_dvd_mk {a b : α} : Associates.mk a ∣ Associates.mk b ↔ a ∣ b := by +theorem mk_dvd_mk {a b : M} : Associates.mk a ∣ Associates.mk b ↔ a ∣ b := by simp only [dvd_def, mk_surjective.exists, mk_mul_mk, mk_eq_mk_iff_associated, Associated.comm (x := b)] constructor @@ -904,18 +910,18 @@ theorem mk_dvd_mk {a b : α} : Associates.mk a ∣ Associates.mk b ↔ a ∣ b : · rintro ⟨c, rfl⟩ use c -theorem dvd_of_mk_le_mk {a b : α} : Associates.mk a ≤ Associates.mk b → a ∣ b := +theorem dvd_of_mk_le_mk {a b : M} : Associates.mk a ≤ Associates.mk b → a ∣ b := mk_dvd_mk.mp -theorem mk_le_mk_of_dvd {a b : α} : a ∣ b → Associates.mk a ≤ Associates.mk b := +theorem mk_le_mk_of_dvd {a b : M} : a ∣ b → Associates.mk a ≤ Associates.mk b := mk_dvd_mk.mpr -theorem mk_le_mk_iff_dvd {a b : α} : Associates.mk a ≤ Associates.mk b ↔ a ∣ b := mk_dvd_mk +theorem mk_le_mk_iff_dvd {a b : M} : Associates.mk a ≤ Associates.mk b ↔ a ∣ b := mk_dvd_mk @[deprecated (since := "2024-03-16")] alias mk_le_mk_iff_dvd_iff := mk_le_mk_iff_dvd @[simp] -theorem isPrimal_mk {a : α} : IsPrimal (Associates.mk a) ↔ IsPrimal a := by +theorem isPrimal_mk {a : M} : IsPrimal (Associates.mk a) ↔ IsPrimal a := by simp_rw [IsPrimal, forall_associated, mk_surjective.exists, mk_mul_mk, mk_dvd_mk] constructor <;> intro h b c dvd <;> obtain ⟨a₁, a₂, h₁, h₂, eq⟩ := @h b c dvd · obtain ⟨u, rfl⟩ := mk_eq_mk_iff_associated.mp eq.symm @@ -925,80 +931,80 @@ theorem isPrimal_mk {a : α} : IsPrimal (Associates.mk a) ↔ IsPrimal a := by @[deprecated (since := "2024-03-16")] alias isPrimal_iff := isPrimal_mk @[simp] -theorem decompositionMonoid_iff : DecompositionMonoid (Associates α) ↔ DecompositionMonoid α := by +theorem decompositionMonoid_iff : DecompositionMonoid (Associates M) ↔ DecompositionMonoid M := by simp_rw [_root_.decompositionMonoid_iff, forall_associated, isPrimal_mk] -instance instDecompositionMonoid [DecompositionMonoid α] : DecompositionMonoid (Associates α) := +instance instDecompositionMonoid [DecompositionMonoid M] : DecompositionMonoid (Associates M) := decompositionMonoid_iff.mpr ‹_› @[simp] -theorem mk_isRelPrime_iff {a b : α} : +theorem mk_isRelPrime_iff {a b : M} : IsRelPrime (Associates.mk a) (Associates.mk b) ↔ IsRelPrime a b := by simp_rw [IsRelPrime, forall_associated, mk_dvd_mk, isUnit_mk] end CommMonoid -instance [Zero α] [Monoid α] : Zero (Associates α) := +instance [Zero M] [Monoid M] : Zero (Associates M) := ⟨⟦0⟧⟩ -instance [Zero α] [Monoid α] : Top (Associates α) := +instance [Zero M] [Monoid M] : Top (Associates M) := ⟨0⟩ -@[simp] theorem mk_zero [Zero α] [Monoid α] : Associates.mk (0 : α) = 0 := rfl +@[simp] theorem mk_zero [Zero M] [Monoid M] : Associates.mk (0 : M) = 0 := rfl section MonoidWithZero -variable [MonoidWithZero α] +variable [MonoidWithZero M] @[simp] -theorem mk_eq_zero {a : α} : Associates.mk a = 0 ↔ a = 0 := +theorem mk_eq_zero {a : M} : Associates.mk a = 0 ↔ a = 0 := ⟨fun h => (associated_zero_iff_eq_zero a).1 <| Quotient.exact h, fun h => h.symm ▸ rfl⟩ @[simp] -theorem quot_out_zero : Quot.out (0 : Associates α) = 0 := by rw [← mk_eq_zero, quot_out] +theorem quot_out_zero : Quot.out (0 : Associates M) = 0 := by rw [← mk_eq_zero, quot_out] -theorem mk_ne_zero {a : α} : Associates.mk a ≠ 0 ↔ a ≠ 0 := +theorem mk_ne_zero {a : M} : Associates.mk a ≠ 0 ↔ a ≠ 0 := not_congr mk_eq_zero -instance [Nontrivial α] : Nontrivial (Associates α) := +instance [Nontrivial M] : Nontrivial (Associates M) := ⟨⟨1, 0, mk_ne_zero.2 one_ne_zero⟩⟩ -theorem exists_non_zero_rep {a : Associates α} : a ≠ 0 → ∃ a0 : α, a0 ≠ 0 ∧ Associates.mk a0 = a := +theorem exists_non_zero_rep {a : Associates M} : a ≠ 0 → ∃ a0 : M, a0 ≠ 0 ∧ Associates.mk a0 = a := Quotient.inductionOn a fun b nz => ⟨b, mt (congr_arg Quotient.mk'') nz, rfl⟩ end MonoidWithZero section CommMonoidWithZero -variable [CommMonoidWithZero α] +variable [CommMonoidWithZero M] -instance instCommMonoidWithZero : CommMonoidWithZero (Associates α) where +instance instCommMonoidWithZero : CommMonoidWithZero (Associates M) where zero_mul := forall_associated.2 fun a ↦ by rw [← mk_zero, mk_mul_mk, zero_mul] mul_zero := forall_associated.2 fun a ↦ by rw [← mk_zero, mk_mul_mk, mul_zero] -instance instOrderTop : OrderTop (Associates α) where +instance instOrderTop : OrderTop (Associates M) where top := 0 le_top := dvd_zero -@[simp] protected theorem le_zero (a : Associates α) : a ≤ 0 := le_top +@[simp] protected theorem le_zero (a : Associates M) : a ≤ 0 := le_top -instance instBoundedOrder : BoundedOrder (Associates α) where +instance instBoundedOrder : BoundedOrder (Associates M) where -instance [DecidableRel ((· ∣ ·) : α → α → Prop)] : - DecidableRel ((· ∣ ·) : Associates α → Associates α → Prop) := fun a b => +instance [DecidableRel ((· ∣ ·) : M → M → Prop)] : + DecidableRel ((· ∣ ·) : Associates M → Associates M → Prop) := fun a b => Quotient.recOnSubsingleton₂ a b fun _ _ => decidable_of_iff' _ mk_dvd_mk -theorem Prime.le_or_le {p : Associates α} (hp : Prime p) {a b : Associates α} (h : p ≤ a * b) : +theorem Prime.le_or_le {p : Associates M} (hp : Prime p) {a b : Associates M} (h : p ≤ a * b) : p ≤ a ∨ p ≤ b := hp.2.2 a b h @[simp] -theorem prime_mk {p : α} : Prime (Associates.mk p) ↔ Prime p := by +theorem prime_mk {p : M} : Prime (Associates.mk p) ↔ Prime p := by rw [Prime, _root_.Prime, forall_associated] simp only [forall_associated, mk_ne_zero, isUnit_mk, mk_mul_mk, mk_dvd_mk] @[simp] -theorem irreducible_mk {a : α} : Irreducible (Associates.mk a) ↔ Irreducible a := by +theorem irreducible_mk {a : M} : Irreducible (Associates.mk a) ↔ Irreducible a := by simp only [irreducible_iff, isUnit_mk, forall_associated, isUnit_mk, mk_mul_mk, mk_eq_mk_iff_associated, Associated.comm (x := a)] apply Iff.rfl.and @@ -1009,7 +1015,7 @@ theorem irreducible_mk {a : α} : Irreducible (Associates.mk a) ↔ Irreducible simpa using h x (y * u) (mul_assoc _ _ _) @[simp] -theorem mk_dvdNotUnit_mk_iff {a b : α} : +theorem mk_dvdNotUnit_mk_iff {a b : M} : DvdNotUnit (Associates.mk a) (Associates.mk b) ↔ DvdNotUnit a b := by simp only [DvdNotUnit, mk_ne_zero, mk_surjective.exists, isUnit_mk, mk_mul_mk, mk_eq_mk_iff_associated, Associated.comm (x := b)] @@ -1021,7 +1027,7 @@ theorem mk_dvdNotUnit_mk_iff {a b : α} : · rintro ⟨x, ⟨hx, rfl⟩⟩ use x -theorem dvdNotUnit_of_lt {a b : Associates α} (hlt : a < b) : DvdNotUnit a b := by +theorem dvdNotUnit_of_lt {a b : Associates M} (hlt : a < b) : DvdNotUnit a b := by constructor · rintro rfl apply not_lt_of_le _ hlt @@ -1033,46 +1039,46 @@ theorem dvdNotUnit_of_lt {a b : Associates α} (hlt : a < b) : DvdNotUnit a b := simp theorem irreducible_iff_prime_iff : - (∀ a : α, Irreducible a ↔ Prime a) ↔ ∀ a : Associates α, Irreducible a ↔ Prime a := by + (∀ a : M, Irreducible a ↔ Prime a) ↔ ∀ a : Associates M, Irreducible a ↔ Prime a := by simp_rw [forall_associated, irreducible_mk, prime_mk] end CommMonoidWithZero section CancelCommMonoidWithZero -variable [CancelCommMonoidWithZero α] +variable [CancelCommMonoidWithZero M] -instance instPartialOrder : PartialOrder (Associates α) where +instance instPartialOrder : PartialOrder (Associates M) where le_antisymm := mk_surjective.forall₂.2 fun _a _b hab hba => mk_eq_mk_iff_associated.2 <| associated_of_dvd_dvd (dvd_of_mk_le_mk hab) (dvd_of_mk_le_mk hba) -instance instCancelCommMonoidWithZero : CancelCommMonoidWithZero (Associates α) := - { (by infer_instance : CommMonoidWithZero (Associates α)) with +instance instCancelCommMonoidWithZero : CancelCommMonoidWithZero (Associates M) := + { (by infer_instance : CommMonoidWithZero (Associates M)) with mul_left_cancel_of_ne_zero := by rintro ⟨a⟩ ⟨b⟩ ⟨c⟩ ha h rcases Quotient.exact' h with ⟨u, hu⟩ have hu : a * (b * ↑u) = a * c := by rwa [← mul_assoc] exact Quotient.sound' ⟨u, mul_left_cancel₀ (mk_ne_zero.1 ha) hu⟩ } -theorem _root_.associates_irreducible_iff_prime [DecompositionMonoid α] {p : Associates α} : +theorem _root_.associates_irreducible_iff_prime [DecompositionMonoid M] {p : Associates M} : Irreducible p ↔ Prime p := irreducible_iff_prime -instance : NoZeroDivisors (Associates α) := by infer_instance +instance : NoZeroDivisors (Associates M) := by infer_instance -theorem le_of_mul_le_mul_left (a b c : Associates α) (ha : a ≠ 0) : a * b ≤ a * c → b ≤ c +theorem le_of_mul_le_mul_left (a b c : Associates M) (ha : a ≠ 0) : a * b ≤ a * c → b ≤ c | ⟨d, hd⟩ => ⟨d, mul_left_cancel₀ ha <| by rwa [← mul_assoc]⟩ -theorem one_or_eq_of_le_of_prime {p m : Associates α} (hp : Prime p) (hle : m ≤ p) : +theorem one_or_eq_of_le_of_prime {p m : Associates M} (hp : Prime p) (hle : m ≤ p) : m = 1 ∨ m = p := by rcases mk_surjective p with ⟨p, rfl⟩ rcases mk_surjective m with ⟨m, rfl⟩ simpa [mk_eq_mk_iff_associated, Associated.comm, -Quotient.eq] using (prime_mk.1 hp).irreducible.dvd_iff.mp (mk_le_mk_iff_dvd.1 hle) -theorem dvdNotUnit_iff_lt {a b : Associates α} : DvdNotUnit a b ↔ a < b := +theorem dvdNotUnit_iff_lt {a b : Associates M} : DvdNotUnit a b ↔ a < b := dvd_and_not_dvd_iff.symm -theorem le_one_iff {p : Associates α} : p ≤ 1 ↔ p = 1 := by rw [← Associates.bot_eq_one, le_bot_iff] +theorem le_one_iff {p : Associates M} : p ≤ 1 ↔ p = 1 := by rw [← Associates.bot_eq_one, le_bot_iff] end CancelCommMonoidWithZero @@ -1080,20 +1086,20 @@ end Associates section CommMonoidWithZero -theorem DvdNotUnit.isUnit_of_irreducible_right [CommMonoidWithZero α] {p q : α} +theorem DvdNotUnit.isUnit_of_irreducible_right [CommMonoidWithZero M] {p q : M} (h : DvdNotUnit p q) (hq : Irreducible q) : IsUnit p := by obtain ⟨_, x, hx, hx'⟩ := h exact Or.resolve_right ((irreducible_iff.1 hq).right p x hx') hx -theorem not_irreducible_of_not_unit_dvdNotUnit [CommMonoidWithZero α] {p q : α} (hp : ¬IsUnit p) +theorem not_irreducible_of_not_unit_dvdNotUnit [CommMonoidWithZero M] {p q : M} (hp : ¬IsUnit p) (h : DvdNotUnit p q) : ¬Irreducible q := mt h.isUnit_of_irreducible_right hp -theorem DvdNotUnit.not_unit [CommMonoidWithZero α] {p q : α} (hp : DvdNotUnit p q) : ¬IsUnit q := by +theorem DvdNotUnit.not_unit [CommMonoidWithZero M] {p q : M} (hp : DvdNotUnit p q) : ¬IsUnit q := by obtain ⟨-, x, hx, rfl⟩ := hp exact fun hc => hx (isUnit_iff_dvd_one.mpr (dvd_of_mul_left_dvd (isUnit_iff_dvd_one.mp hc))) -theorem dvdNotUnit_of_dvdNotUnit_associated [CommMonoidWithZero α] [Nontrivial α] {p q r : α} +theorem dvdNotUnit_of_dvdNotUnit_associated [CommMonoidWithZero M] [Nontrivial M] {p q r : M} (h : DvdNotUnit p q) (h' : Associated q r) : DvdNotUnit p r := by obtain ⟨u, rfl⟩ := Associated.symm h' obtain ⟨hp, x, hx⟩ := h @@ -1104,27 +1110,27 @@ end CommMonoidWithZero section CancelCommMonoidWithZero -theorem isUnit_of_associated_mul [CancelCommMonoidWithZero α] {p b : α} (h : Associated (p * b) p) +theorem isUnit_of_associated_mul [CancelCommMonoidWithZero M] {p b : M} (h : Associated (p * b) p) (hp : p ≠ 0) : IsUnit b := by obtain ⟨a, ha⟩ := h refine isUnit_of_mul_eq_one b a ((mul_right_inj' hp).mp ?_) rwa [← mul_assoc, mul_one] -theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : +theorem DvdNotUnit.not_associated [CancelCommMonoidWithZero M] {p q : M} (h : DvdNotUnit p q) : ¬Associated p q := by rintro ⟨a, rfl⟩ obtain ⟨hp, x, hx, hx'⟩ := h rcases (mul_right_inj' hp).mp hx' with rfl exact hx a.isUnit -theorem DvdNotUnit.ne [CancelCommMonoidWithZero α] {p q : α} (h : DvdNotUnit p q) : p ≠ q := by +theorem DvdNotUnit.ne [CancelCommMonoidWithZero M] {p q : M} (h : DvdNotUnit p q) : p ≠ q := by by_contra hcontra obtain ⟨hp, x, hx', hx''⟩ := h conv_lhs at hx'' => rw [← hcontra, ← mul_one p] rw [(mul_left_cancel₀ hp hx'').symm] at hx' exact hx' isUnit_one -theorem pow_injective_of_not_isUnit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q) +theorem pow_injective_of_not_isUnit [CancelCommMonoidWithZero M] {q : M} (hq : ¬IsUnit q) (hq' : q ≠ 0) : Function.Injective fun n : ℕ => q ^ n := by refine injective_of_lt_imp_ne fun n m h => DvdNotUnit.ne ⟨pow_ne_zero n hq', q ^ (m - n), ?_, ?_⟩ · exact not_isUnit_of_not_isUnit_dvd hq (dvd_pow (dvd_refl _) (Nat.sub_pos_of_lt h).ne') @@ -1133,11 +1139,11 @@ theorem pow_injective_of_not_isUnit [CancelCommMonoidWithZero α] {q : α} (hq : @[deprecated (since := "2024-09-22")] alias pow_injective_of_not_unit := pow_injective_of_not_isUnit -theorem pow_inj_of_not_isUnit [CancelCommMonoidWithZero α] {q : α} (hq : ¬IsUnit q) +theorem pow_inj_of_not_isUnit [CancelCommMonoidWithZero M] {q : M} (hq : ¬IsUnit q) (hq' : q ≠ 0) {m n : ℕ} : q ^ m = q ^ n ↔ m = n := (pow_injective_of_not_isUnit hq hq').eq_iff -theorem dvd_prime_pow [CancelCommMonoidWithZero α] {p q : α} (hp : Prime p) (n : ℕ) : +theorem dvd_prime_pow [CancelCommMonoidWithZero M] {p q : M} (hp : Prime p) (n : ℕ) : q ∣ p ^ n ↔ ∃ i ≤ n, Associated q (p ^ i) := by induction n generalizing q with | zero => diff --git a/Mathlib/Algebra/BigOperators/Associated.lean b/Mathlib/Algebra/BigOperators/Associated.lean index ffad576334789..ebe6b44cb5983 100644 --- a/Mathlib/Algebra/BigOperators/Associated.lean +++ b/Mathlib/Algebra/BigOperators/Associated.lean @@ -94,14 +94,14 @@ theorem divisor_closure_eq_closure [CancelCommMonoidWithZero α] obtain ⟨ha₁ | ha₂, hs⟩ := hm · rcases ha₁.exists_right_inv with ⟨k, hk⟩ refine hind x (y*k) ?_ hs ?_ - simp only [← mul_assoc, ← hprod, ← Multiset.prod_cons, mul_comm] - refine multiset_prod_mem _ _ (Multiset.forall_mem_cons.2 ⟨subset_closure (Set.mem_def.2 ?_), - Multiset.forall_mem_cons.2 ⟨subset_closure (Set.mem_def.2 ?_), (fun t ht => - subset_closure (hs t ht))⟩⟩) - · left; exact isUnit_of_mul_eq_one_right _ _ hk - · left; exact ha₁ - rw [← mul_one s.prod, ← hk, ← mul_assoc, ← mul_assoc, mul_eq_mul_right_iff, mul_comm] - left; exact hprod + · simp only [← mul_assoc, ← hprod, ← Multiset.prod_cons, mul_comm] + refine multiset_prod_mem _ _ (Multiset.forall_mem_cons.2 ⟨subset_closure (Set.mem_def.2 ?_), + Multiset.forall_mem_cons.2 ⟨subset_closure (Set.mem_def.2 ?_), (fun t ht => + subset_closure (hs t ht))⟩⟩) + · left; exact isUnit_of_mul_eq_one_right _ _ hk + · left; exact ha₁ + · rw [← mul_one s.prod, ← hk, ← mul_assoc, ← mul_assoc, mul_eq_mul_right_iff, mul_comm] + left; exact hprod · rcases ha₂.dvd_mul.1 (Dvd.intro _ hprod) with ⟨c, hc⟩ | ⟨c, hc⟩ · rw [hc]; rw [hc, mul_assoc] at hprod refine Submonoid.mul_mem _ (subset_closure (Set.mem_def.2 ?_)) @@ -135,7 +135,7 @@ theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α] Multiset.countP_pos] at this exact this ⟨b, b_in_s, assoc.symm⟩ -theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α) +theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Subsingleton αˣ] {s : Finset α} (n : α) (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p ∈ s, p) ∣ n := by classical exact diff --git a/Mathlib/Algebra/BigOperators/Balance.lean b/Mathlib/Algebra/BigOperators/Balance.lean new file mode 100644 index 0000000000000..1b2b2ca767a64 --- /dev/null +++ b/Mathlib/Algebra/BigOperators/Balance.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2023 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.Expect + +/-! +# Balancing a function + +This file defines the balancing of a function `f`, defined as `f` minus its average. + +This is the unique function `g` such that `f a - f b = g a - g b` for all `a` and `b`, and +`∑ a, g a = 0`. This is particularly useful in Fourier analysis as `f` and `g` then have the same +Fourier transform, except in the `0`-th frequency where the Fourier transform of `g` vanishes. +-/ + +open Finset Function +open scoped BigOperators + +variable {ι H F G : Type*} + +namespace Fintype + +section AddCommGroup +variable [Fintype ι] [AddCommGroup G] [Module ℚ≥0 G] [AddCommGroup H] [Module ℚ≥0 H] + +/-- The balancing of a function, namely the function minus its average. -/ +def balance (f : ι → G) : ι → G := f - Function.const _ (𝔼 y, f y) + +lemma balance_apply (f : ι → G) (x : ι) : balance f x = f x - 𝔼 y, f y := rfl + +@[simp] lemma balance_zero : balance (0 : ι → G) = 0 := by simp [balance] + +@[simp] lemma balance_add (f g : ι → G) : balance (f + g) = balance f + balance g := by + simp only [balance, expect_add_distrib, ← const_add, add_sub_add_comm, Pi.add_apply] + +@[simp] lemma balance_sub (f g : ι → G) : balance (f - g) = balance f - balance g := by + simp only [balance, expect_sub_distrib, const_sub, sub_sub_sub_comm, Pi.sub_apply] + +@[simp] lemma balance_neg (f : ι → G) : balance (-f) = -balance f := by + simp only [balance, expect_neg_distrib, const_neg, neg_sub', Pi.neg_apply] + +@[simp] lemma sum_balance (f : ι → G) : ∑ x, balance f x = 0 := by + cases isEmpty_or_nonempty ι <;> simp [balance_apply] + +@[simp] lemma expect_balance (f : ι → G) : 𝔼 x, balance f x = 0 := by simp [expect] + +@[simp] lemma balance_idem (f : ι → G) : balance (balance f) = balance f := by + cases isEmpty_or_nonempty ι <;> ext x <;> simp [balance, expect_sub_distrib, univ_nonempty] + +@[simp] lemma map_balance [FunLike F G H] [LinearMapClass F ℚ≥0 G H] (g : F) (f : ι → G) (a : ι) : + g (balance f a) = balance (g ∘ f) a := by simp [balance, map_expect] + +end AddCommGroup +end Fintype diff --git a/Mathlib/Algebra/BigOperators/Expect.lean b/Mathlib/Algebra/BigOperators/Expect.lean index ed859ddca94e4..cf6a0e4d72664 100644 --- a/Mathlib/Algebra/BigOperators/Expect.lean +++ b/Mathlib/Algebra/BigOperators/Expect.lean @@ -5,8 +5,11 @@ Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Algebra.Algebra.Rat import Mathlib.Algebra.BigOperators.GroupWithZero.Action +import Mathlib.Algebra.BigOperators.Pi import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.Group.Pointwise.Finset.Basic +import Mathlib.Algebra.Module.Pi +import Mathlib.Data.Finset.Density import Mathlib.Data.Fintype.BigOperators /-! @@ -37,7 +40,7 @@ combination operator. ## TODO * Connect `Finset.expect` with the expectation over `s` in the probability theory sense. -* Give a formulation of Jensen's inequality and the Cauchy-Schwarz inequality in this language. +* Give a formulation of Jensen's inequality in this language. -/ open Finset Function @@ -98,7 +101,7 @@ to show the domain type when the expect is over `Finset.univ`. -/ `(bigOpBinder| $(.mk i):ident) `(𝔼 $binder:bigOpBinder, $body) else - let ss ← withNaryArg 3 <| delab + let ss ← withNaryArg 4 <| delab `(𝔼 $(.mk i):ident ∈ $ss, $body) end BigOperators @@ -159,6 +162,12 @@ lemma expect_ite_zero (s : Finset ι) (p : ι → Prop) [DecidablePred p] section DecidableEq variable [DecidableEq ι] +lemma expect_ite_mem (s t : Finset ι) (f : ι → M) : + 𝔼 i ∈ s, (if i ∈ t then f i else 0) = ((s ∩ t).card / s.card : ℚ≥0) • 𝔼 i ∈ s ∩ t, f i := by + obtain hst | hst := (s ∩ t).eq_empty_or_nonempty + · simp [expect, hst] + · simp [expect, smul_smul, ← inv_mul_eq_div, hst.card_ne_zero] + @[simp] lemma expect_dite_eq (i : ι) (f : ∀ j, i = j → M) : 𝔼 j ∈ s, (if h : i = j then f j h else 0) = if i ∈ s then f i rfl /ℚ s.card else 0 := by split_ifs <;> simp [expect, *] @@ -358,6 +367,11 @@ lemma expect_div (s : Finset ι) (f : ι → M) (a : M) : (𝔼 i ∈ s, f i) / simp_rw [div_eq_mul_inv, expect_mul] end Semifield + +@[simp] lemma expect_apply {α : Type*} {π : α → Type*} [∀ a, CommSemiring (π a)] + [∀ a, Module ℚ≥0 (π a)] (s : Finset ι) (f : ι → ∀ a, π a) (a : α) : + (𝔼 i ∈ s, f i) a = 𝔼 i ∈ s, f i a := by simp [expect] + end Finset namespace algebraMap @@ -399,6 +413,10 @@ lemma expect_ite_zero (p : ι → Prop) [DecidablePred p] (h : ∀ i j, p i → variable [DecidableEq ι] +@[simp] lemma expect_ite_mem (s : Finset ι) (f : ι → M) : + 𝔼 i, (if i ∈ s then f i else 0) = s.dens • 𝔼 i ∈ s, f i := by + simp [Finset.expect_ite_mem, dens] + lemma expect_dite_eq (i : ι) (f : ∀ j, i = j → M) : 𝔼 j, (if h : i = j then f j h else 0) = f i rfl /ℚ card ι := by simp [card_univ] @@ -416,7 +434,11 @@ end AddCommMonoid section Semiring variable [Semiring M] [Module ℚ≥0 M] -@[simp] lemma expect_one [Nonempty ι] : 𝔼 _i : ι, (1 : M) = 1 := expect_const _ +lemma expect_one [Nonempty ι] : 𝔼 _i : ι, (1 : M) = 1 := expect_const _ + +lemma expect_mul_expect [IsScalarTower ℚ≥0 M M] [SMulCommClass ℚ≥0 M M] (f : ι → M) + (g : κ → M) : (𝔼 i, f i) * 𝔼 j, g j = 𝔼 i, 𝔼 j, f i * g j := + Finset.expect_mul_expect .. end Semiring end Fintype diff --git a/Mathlib/Algebra/BigOperators/Finsupp.lean b/Mathlib/Algebra/BigOperators/Finsupp.lean index 35f43a5d0baa1..10fdcfb6979ea 100644 --- a/Mathlib/Algebra/BigOperators/Finsupp.lean +++ b/Mathlib/Algebra/BigOperators/Finsupp.lean @@ -249,12 +249,12 @@ theorem sum_apply [Zero M] [AddCommMonoid N] {f : α →₀ M} {g : α → M → finset_sum_apply _ _ _ -- Porting note: inserted ⇑ on the rhs -theorem coe_finset_sum [AddCommMonoid N] (S : Finset ι) (f : ι → α →₀ N) : +@[simp, norm_cast] theorem coe_finset_sum [AddCommMonoid N] (S : Finset ι) (f : ι → α →₀ N) : ⇑(∑ i ∈ S, f i) = ∑ i ∈ S, ⇑(f i) := map_sum (coeFnAddHom : (α →₀ N) →+ _) _ _ -- Porting note: inserted ⇑ on the rhs -theorem coe_sum [Zero M] [AddCommMonoid N] (f : α →₀ M) (g : α → M → β →₀ N) : +@[simp, norm_cast] theorem coe_sum [Zero M] [AddCommMonoid N] (f : α →₀ M) (g : α → M → β →₀ N) : ⇑(f.sum g) = f.sum fun a₁ b => ⇑(g a₁ b) := coe_finset_sum _ _ diff --git a/Mathlib/Algebra/BigOperators/Group/Finset.lean b/Mathlib/Algebra/BigOperators/Group/Finset.lean index c418a20c2dc75..ee1faae6ee2a2 100644 --- a/Mathlib/Algebra/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Finset.lean @@ -1478,6 +1478,11 @@ theorem sum_range_tsub [AddCommMonoid α] [PartialOrder α] [Sub α] [OrderedSub have h₂ : f 0 ≤ f n := h (Nat.zero_le _) rw [tsub_add_eq_add_tsub h₂, add_tsub_cancel_of_le h₁] +theorem sum_tsub_distrib [AddCommMonoid α] [PartialOrder α] [ExistsAddOfLE α] + [CovariantClass α α (· + ·) (· ≤ ·)] [ContravariantClass α α (· + ·) (· ≤ ·)] [Sub α] + [OrderedSub α] (s : Finset ι) {f g : ι → α} (hfg : ∀ x ∈ s, g x ≤ f x) : + ∑ x ∈ s, (f x - g x) = ∑ x ∈ s, f x - ∑ x ∈ s, g x := sum_map_tsub _ hfg + @[to_additive (attr := simp)] theorem prod_const (b : β) : ∏ _x ∈ s, b = b ^ s.card := (congr_arg _ <| s.val.map_const b).trans <| Multiset.prod_replicate s.card b @@ -2258,9 +2263,6 @@ theorem toAdd_prod (s : Finset ι) (f : ι → Multiplicative α) : end AddCommMonoid -@[deprecated (since := "2023-12-23")] alias Equiv.prod_comp' := Fintype.prod_equiv -@[deprecated (since := "2023-12-23")] alias Equiv.sum_comp' := Fintype.sum_equiv - theorem Finset.sum_sym2_filter_not_isDiag {ι α} [LinearOrder ι] [AddCommMonoid α] (s : Finset ι) (p : Sym2 ι → α) : ∑ i in s.sym2.filter (¬ ·.IsDiag), p i = diff --git a/Mathlib/Algebra/BigOperators/Group/List.lean b/Mathlib/Algebra/BigOperators/Group/List.lean index 00a2158bc6981..6a1a5fb8af68e 100644 --- a/Mathlib/Algebra/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/BigOperators/Group/List.lean @@ -125,7 +125,7 @@ theorem prod_replicate (n : ℕ) (a : M) : (replicate n a).prod = a ^ n := by @[to_additive sum_eq_card_nsmul] theorem prod_eq_pow_card (l : List M) (m : M) (h : ∀ x ∈ l, x = m) : l.prod = m ^ l.length := by - rw [← prod_replicate, ← List.eq_replicate.mpr ⟨rfl, h⟩] + rw [← prod_replicate, ← List.eq_replicate_iff.mpr ⟨rfl, h⟩] @[to_additive] theorem prod_hom_rel (l : List ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1) @@ -189,21 +189,14 @@ theorem prod_isUnit_iff {α : Type*} [CommMonoid α] {L : List α} : exact fun m' h' ↦ Or.elim (eq_or_mem_of_mem_cons h') (fun H => H.substr h.1) fun H => ih h.2 _ H @[to_additive (attr := simp)] -theorem prod_take_mul_prod_drop : ∀ (L : List M) (i : ℕ), (L.take i).prod * (L.drop i).prod = L.prod - | [], i => by simp [Nat.zero_le] - | L, 0 => by simp - | h :: t, n + 1 => by - dsimp - rw [prod_cons, prod_cons, mul_assoc, prod_take_mul_prod_drop t] +theorem prod_take_mul_prod_drop (L : List M) (i : ℕ) : + (L.take i).prod * (L.drop i).prod = L.prod := by + simp [← prod_append] @[to_additive (attr := simp)] -theorem prod_take_succ : - ∀ (L : List M) (i : ℕ) (p : i < L.length), (L.take (i + 1)).prod = (L.take i).prod * L[i] - | [], i, p => by cases p - | h :: t, 0, _ => rfl - | h :: t, n + 1, p => by - dsimp - rw [prod_cons, prod_cons, prod_take_succ t n (Nat.lt_of_succ_lt_succ p), mul_assoc] +theorem prod_take_succ (L : List M) (i : ℕ) (p : i < L.length) : + (L.take (i + 1)).prod = (L.take i).prod * L[i] := by + simp [take_succ, p] /-- A list with product not one must have positive length. -/ @[to_additive "A list with sum not zero must have positive length."] @@ -273,9 +266,9 @@ last. -/ @[to_additive "A variant of `sum_range_succ` which pulls off the first term in the sum rather than the last."] lemma prod_range_succ' (f : ℕ → M) (n : ℕ) : - ((range n.succ).map f).prod = f 0 * ((range n).map fun i ↦ f i.succ).prod := - Nat.recOn n (show 1 * f 0 = f 0 * 1 by rw [one_mul, mul_one]) fun _ hd => by - rw [List.prod_range_succ, hd, mul_assoc, ← List.prod_range_succ] + ((range n.succ).map f).prod = f 0 * ((range n).map fun i ↦ f i.succ).prod := by + rw [range_succ_eq_map] + simp [Function.comp_def] @[to_additive] lemma prod_eq_one (hl : ∀ x ∈ l, x = 1) : l.prod = 1 := by induction l with @@ -349,7 +342,7 @@ lemma prod_map_erase [DecidableEq α] (f : α → M) {a} : · simp only [map, erase_cons_tail (not_beq_of_ne ne.symm), prod_cons, prod_map_erase _ h, mul_left_comm (f a) (f b)] -@[to_additive] lemma Perm.prod_eq (h : Perm l₁ l₂) : prod l₁ = prod l₂ := h.fold_op_eq +@[to_additive] lemma Perm.prod_eq (h : Perm l₁ l₂) : prod l₁ = prod l₂ := h.foldl_op_eq @[to_additive] lemma prod_reverse (l : List M) : prod l.reverse = prod l := (reverse_perm l).prod_eq @@ -646,20 +639,15 @@ lemma ranges_join (l : List ℕ) : l.ranges.join = range l.sum := by simp [range lemma mem_mem_ranges_iff_lt_sum (l : List ℕ) {n : ℕ} : (∃ s ∈ l.ranges, n ∈ s) ↔ n < l.sum := by simp [mem_mem_ranges_iff_lt_natSum] -lemma countP_join (p : α → Bool) : ∀ L : List (List α), countP p L.join = (L.map (countP p)).sum - | [] => rfl - | a :: l => by rw [join, countP_append, map_cons, sum_cons, countP_join _ l] - -lemma count_join [BEq α] (L : List (List α)) (a : α) : L.join.count a = (L.map (count a)).sum := - countP_join _ _ - @[simp] theorem length_bind (l : List α) (f : α → List β) : length (List.bind l f) = sum (map (length ∘ f) l) := by rw [List.bind, length_join, map_map, Nat.sum_eq_listSum] lemma countP_bind (p : β → Bool) (l : List α) (f : α → List β) : - countP p (l.bind f) = sum (map (countP p ∘ f) l) := by rw [List.bind, countP_join, map_map] + countP p (l.bind f) = sum (map (countP p ∘ f) l) := by + rw [List.bind, countP_join, map_map] + simp lemma count_bind [BEq β] (l : List α) (f : α → List β) (x : β) : count x (l.bind f) = sum (map (count x ∘ f) l) := countP_bind _ _ _ diff --git a/Mathlib/Algebra/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/BigOperators/Group/Multiset.lean index 0a0e9b28703cd..b3ab0b0f8c124 100644 --- a/Mathlib/Algebra/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/BigOperators/Group/Multiset.lean @@ -294,4 +294,17 @@ theorem sum_int_mod (s : Multiset ℤ) (n : ℤ) : s.sum % n = (s.map (· % n)). theorem prod_int_mod (s : Multiset ℤ) (n : ℤ) : s.prod % n = (s.map (· % n)).prod % n := by induction s using Multiset.induction <;> simp [Int.mul_emod, *] +section OrderedSub + +theorem sum_map_tsub [AddCommMonoid α] [PartialOrder α] [ExistsAddOfLE α] + [CovariantClass α α (· + ·) (· ≤ ·)] [ContravariantClass α α (· + ·) (· ≤ ·)] [Sub α] + [OrderedSub α] (l : Multiset ι) {f g : ι → α} (hfg : ∀ x ∈ l, g x ≤ f x) : + (l.map fun x ↦ f x - g x).sum = (l.map f).sum - (l.map g).sum := + eq_tsub_of_add_eq <| by + rw [← sum_map_add] + congr 1 + exact map_congr rfl fun x hx => tsub_add_cancel_of_le <| hfg _ hx + +end OrderedSub + end Multiset diff --git a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean index 71d86a299d148..c969334d05c0a 100644 --- a/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean +++ b/Mathlib/Algebra/BigOperators/GroupWithZero/Action.lean @@ -104,7 +104,7 @@ theorem smul_prod (s : Finset β) (b : α) (f : β → β) : b ^ s.card • ∏ x in s, f x = ∏ x in s, b • f x := by have : Multiset.map (fun (x : β) ↦ b • f x) s.val = - Multiset.map (fun x ↦ b • x) (Multiset.map (fun x ↦ f x) s.val) := by + Multiset.map (fun x ↦ b • x) (Multiset.map f s.val) := by simp only [Multiset.map_map, Function.comp_apply] simp_rw [prod_eq_multiset_prod, card_def, this, ← Multiset.smul_prod _ b, Multiset.card_map] diff --git a/Mathlib/Algebra/BigOperators/Module.lean b/Mathlib/Algebra/BigOperators/Module.lean index fd9ddbeeb76ee..2329df72948f4 100644 --- a/Mathlib/Algebra/BigOperators/Module.lean +++ b/Mathlib/Algebra/BigOperators/Module.lean @@ -31,24 +31,9 @@ theorem sum_Ico_by_parts (hmn : m < n) : rw [← sum_Ico_sub_bot _ hmn, ← sum_Ico_succ_sub_top _ (Nat.le_sub_one_of_lt hmn), Nat.sub_add_cancel (pos_of_gt hmn), sub_add_cancel] rw [sum_eq_sum_Ico_succ_bot hmn] - -- Porting note: the following used to be done with `conv` - have h₃ : (Finset.sum (Ico (m + 1) n) fun i => f i • g i) = - (Finset.sum (Ico (m + 1) n) fun i => - f i • ((Finset.sum (Finset.range (i + 1)) g) - - (Finset.sum (Finset.range i) g))) := by - congr; funext; rw [← sum_range_succ_sub_sum g] - rw [h₃] + conv in (occs := 3) (f _ • g _) => rw [← sum_range_succ_sub_sum g] simp_rw [smul_sub, sum_sub_distrib, h₂, h₁] - -- Porting note: the following used to be done with `conv` - have h₄ : ((((Finset.sum (Ico m (n - 1)) fun i => f i • Finset.sum (range (i + 1)) fun i => g i) + - f (n - 1) • Finset.sum (range n) fun i => g i) - - f m • Finset.sum (range (m + 1)) fun i => g i) - - Finset.sum (Ico m (n - 1)) fun i => f (i + 1) • Finset.sum (range (i + 1)) fun i => g i) = - f (n - 1) • (range n).sum g - f m • (range (m + 1)).sum g + - Finset.sum (Ico m (n - 1)) (fun i => f i • (range (i + 1)).sum g - - f (i + 1) • (range (i + 1)).sum g) := by - rw [← add_sub, add_comm, ← add_sub, ← sum_sub_distrib] - rw [h₄] + conv_lhs => congr; rfl; rw [← add_sub, add_comm, ← add_sub, ← sum_sub_distrib] have : ∀ i, f i • G (i + 1) - f (i + 1) • G (i + 1) = -((f (i + 1) - f i) • G (i + 1)) := by intro i rw [sub_smul] diff --git a/Mathlib/Algebra/Bounds.lean b/Mathlib/Algebra/Bounds.lean deleted file mode 100644 index 8c9ff1cb53079..0000000000000 --- a/Mathlib/Algebra/Bounds.lean +++ /dev/null @@ -1,167 +0,0 @@ -/- -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.Algebra.Group.Pointwise.Set -import Mathlib.Algebra.Order.Group.OrderIso -import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual -import Mathlib.Order.Bounds.OrderIso -import Mathlib.Order.ConditionallyCompleteLattice.Basic - -/-! -# Upper/lower bounds in ordered monoids and groups - -In this file we prove a few facts like “`-s` is bounded above iff `s` is bounded below” -(`bddAbove_neg`). --/ - - -open Function Set - -open Pointwise - -section InvNeg - -variable {G : Type*} [Group G] [Preorder G] [CovariantClass G G (· * ·) (· ≤ ·)] - [CovariantClass G G (swap (· * ·)) (· ≤ ·)] {s : Set G} {a : G} - -@[to_additive (attr := simp)] -theorem bddAbove_inv : BddAbove s⁻¹ ↔ BddBelow s := - (OrderIso.inv G).bddAbove_preimage - -@[to_additive (attr := simp)] -theorem bddBelow_inv : BddBelow s⁻¹ ↔ BddAbove s := - (OrderIso.inv G).bddBelow_preimage - -@[to_additive] -theorem BddAbove.inv (h : BddAbove s) : BddBelow s⁻¹ := - bddBelow_inv.2 h - -@[to_additive] -theorem BddBelow.inv (h : BddBelow s) : BddAbove s⁻¹ := - bddAbove_inv.2 h - -@[to_additive (attr := simp)] -theorem isLUB_inv : IsLUB s⁻¹ a ↔ IsGLB s a⁻¹ := - (OrderIso.inv G).isLUB_preimage - -@[to_additive] -theorem isLUB_inv' : IsLUB s⁻¹ a⁻¹ ↔ IsGLB s a := - (OrderIso.inv G).isLUB_preimage' - -@[to_additive] -theorem IsGLB.inv (h : IsGLB s a) : IsLUB s⁻¹ a⁻¹ := - isLUB_inv'.2 h - -@[to_additive (attr := simp)] -theorem isGLB_inv : IsGLB s⁻¹ a ↔ IsLUB s a⁻¹ := - (OrderIso.inv G).isGLB_preimage - -@[to_additive] -theorem isGLB_inv' : IsGLB s⁻¹ a⁻¹ ↔ IsLUB s a := - (OrderIso.inv G).isGLB_preimage' - -@[to_additive] -theorem IsLUB.inv (h : IsLUB s a) : IsGLB s⁻¹ a⁻¹ := - isGLB_inv'.2 h - -@[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 - -variable {M : Type*} [Mul M] [Preorder M] [CovariantClass M M (· * ·) (· ≤ ·)] - [CovariantClass M M (swap (· * ·)) (· ≤ ·)] - -@[to_additive] -theorem mul_mem_upperBounds_mul {s t : Set M} {a b : M} (ha : a ∈ upperBounds s) - (hb : b ∈ upperBounds t) : a * b ∈ upperBounds (s * t) := - forall_image2_iff.2 fun _ hx _ hy => mul_le_mul' (ha hx) (hb hy) - -@[to_additive] -theorem subset_upperBounds_mul (s t : Set M) : - upperBounds s * upperBounds t ⊆ upperBounds (s * t) := - image2_subset_iff.2 fun _ hx _ hy => mul_mem_upperBounds_mul hx hy - -@[to_additive] -theorem mul_mem_lowerBounds_mul {s t : Set M} {a b : M} (ha : a ∈ lowerBounds s) - (hb : b ∈ lowerBounds t) : a * b ∈ lowerBounds (s * t) := - mul_mem_upperBounds_mul (M := Mᵒᵈ) ha hb - -@[to_additive] -theorem subset_lowerBounds_mul (s t : Set M) : - lowerBounds s * lowerBounds t ⊆ lowerBounds (s * t) := - subset_upperBounds_mul (M := Mᵒᵈ) _ _ - -@[to_additive] -theorem BddAbove.mul {s t : Set M} (hs : BddAbove s) (ht : BddAbove t) : BddAbove (s * t) := - (Nonempty.mul hs ht).mono (subset_upperBounds_mul s t) - -@[to_additive] -theorem BddBelow.mul {s t : Set M} (hs : BddBelow s) (ht : BddBelow t) : BddBelow (s * t) := - (Nonempty.mul hs ht).mono (subset_lowerBounds_mul s t) - -@[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 - -section Right - -variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] - [CovariantClass G G (Function.swap (· * ·)) (· ≤ ·)] [Nonempty ι] {f : ι → G} - -@[to_additive] -theorem ciSup_mul (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := - (OrderIso.mulRight a).map_ciSup hf - -@[to_additive] -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] - -@[to_additive] -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 (range f)) (a : G) : (⨅ i, f i) / a = ⨅ i, f i / a := by - simp only [div_eq_mul_inv, ciInf_mul hf] - -end Right - -section Left - -variable {ι : Sort*} {G : Type*} [Group G] [ConditionallyCompleteLattice G] - [CovariantClass G G (· * ·) (· ≤ ·)] [Nonempty ι] {f : ι → G} - -@[to_additive] -theorem mul_ciSup (hf : BddAbove (range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := - (OrderIso.mulLeft a).map_ciSup hf - -@[to_additive] -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 - -end ConditionallyCompleteLattice diff --git a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean index e0919abefa13d..36546a9af0623 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Basic.lean @@ -77,7 +77,7 @@ instance hasForgetToRing : HasForget₂ (AlgebraCat.{v} R) RingCat.{v} where instance hasForgetToModule : HasForget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R) where forget₂ := { obj := fun M => ModuleCat.of R M - map := fun f => ModuleCat.ofHom f.toLinearMap } + map := fun f => ModuleCat.asHom f.toLinearMap } @[simp] lemma forget₂_module_obj (X : AlgebraCat.{v} R) : @@ -86,7 +86,7 @@ lemma forget₂_module_obj (X : AlgebraCat.{v} R) : @[simp] lemma forget₂_module_map {X Y : AlgebraCat.{v} R} (f : X ⟶ Y) : - (forget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R)).map f = ModuleCat.ofHom f.toLinearMap := + (forget₂ (AlgebraCat.{v} R) (ModuleCat.{v} R)).map f = ModuleCat.asHom f.toLinearMap := rfl /-- The object in the category of R-algebras associated to a type equipped with the appropriate diff --git a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean index a2f702f99e183..7957211163d58 100644 --- a/Mathlib/Algebra/Category/AlgebraCat/Limits.lean +++ b/Mathlib/Algebra/Category/AlgebraCat/Limits.lean @@ -108,7 +108,7 @@ def limitConeIsLimit : IsLimit (limitCone.{v, w} F) := by ext j simp only [Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app, forget_map_eq_coe] - erw [map_one] + rw [map_one] rfl · intro x y simp only [Functor.comp_obj, Functor.mapCone_pt, Functor.mapCone_π_app] diff --git a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean index 3cf9cd5c6fcbe..0d3b3d8260dad 100644 --- a/Mathlib/Algebra/Category/BialgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/BialgebraCat/Basic.lean @@ -59,7 +59,7 @@ lemma of_counit {X : Type v} [Ring X] [Bialgebra R X] : /-- A type alias for `BialgHom` to avoid confusion between the categorical and algebraic spellings of composition. -/ @[ext] -structure Hom (V W : BialgebraCat.{v} R) := +structure Hom (V W : BialgebraCat.{v} R) where /-- The underlying `BialgHom` -/ toBialgHom : V →ₐc[R] W diff --git a/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean b/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean index 2e3227b072f57..cbf7f0ebab743 100644 --- a/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/CoalgebraCat/Basic.lean @@ -62,7 +62,7 @@ lemma of_counit {X : Type v} [AddCommGroup X] [Module R X] [Coalgebra R X] : /-- A type alias for `CoalgHom` to avoid confusion between the categorical and algebraic spellings of composition. -/ @[ext] -structure Hom (V W : CoalgebraCat.{v} R) := +structure Hom (V W : CoalgebraCat.{v} R) where /-- The underlying `CoalgHom` -/ toCoalgHom : V →ₗc[R] W diff --git a/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean b/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean index e6957905eb7f9..0a138d78803f1 100644 --- a/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean +++ b/Mathlib/Algebra/Category/CoalgebraCat/ComonEquivalence.lean @@ -38,8 +38,8 @@ variable {R : Type u} [CommRing R] /-- An `R`-coalgebra is a comonoid object in the category of `R`-modules. -/ @[simps] def toComonObj (X : CoalgebraCat R) : Comon_ (ModuleCat R) where X := ModuleCat.of R X - counit := ModuleCat.ofHom Coalgebra.counit - comul := ModuleCat.ofHom Coalgebra.comul + counit := ModuleCat.asHom Coalgebra.counit + comul := ModuleCat.asHom Coalgebra.comul counit_comul := by simpa only [ModuleCat.of_coe] using Coalgebra.rTensor_counit_comp_comul comul_counit := by simpa only [ModuleCat.of_coe] using Coalgebra.lTensor_counit_comp_comul comul_assoc := by simp_rw [ModuleCat.of_coe]; exact Coalgebra.coassoc.symm @@ -50,7 +50,7 @@ variable (R) in def toComon : CoalgebraCat R ⥤ Comon_ (ModuleCat R) where obj X := toComonObj X map f := - { hom := ModuleCat.ofHom f.1 + { hom := ModuleCat.asHom f.1 hom_counit := f.1.counit_comp hom_comul := f.1.map_comp_comul.symm } diff --git a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean index 01ae8aab6bb4d..50f9e8d2c035a 100644 --- a/Mathlib/Algebra/Category/FGModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/FGModuleCat/Basic.lean @@ -278,8 +278,8 @@ end FGModuleCat @[simp] theorem LinearMap.comp_id_fgModuleCat {R} [Ring R] {G : FGModuleCat.{u} R} {H : Type u} [AddCommGroup H] [Module R H] (f : G →ₗ[R] H) : f.comp (𝟙 G) = f := - Category.id_comp (ModuleCat.ofHom f) + Category.id_comp (ModuleCat.asHom f) @[simp] theorem LinearMap.id_fgModuleCat_comp {R} [Ring R] {G : Type u} [AddCommGroup G] [Module R G] {H : FGModuleCat.{u} R} (f : G →ₗ[R] H) : LinearMap.comp (𝟙 H) f = f := - Category.comp_id (ModuleCat.ofHom f) + Category.comp_id (ModuleCat.asHom f) diff --git a/Mathlib/Algebra/Category/Grp/Colimits.lean b/Mathlib/Algebra/Category/Grp/Colimits.lean index 52e9b257663ec..218f0d859b5ad 100644 --- a/Mathlib/Algebra/Category/Grp/Colimits.lean +++ b/Mathlib/Algebra/Category/Grp/Colimits.lean @@ -227,7 +227,7 @@ def colimitCoconeIsColimit : IsColimit (colimitCocone.{w} F) where rw [map_neg, map_neg, ih] | add x y ihx ihy => simp only [quot_add] - erw [m.map_add, (descMorphism F s).map_add, ihx, ihy] + rw [m.map_add, (descMorphism F s).map_add, ihx, ihy] end Colimits diff --git a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean index 7f0cd7d6755d1..c7caa5ef7b7ad 100644 --- a/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean +++ b/Mathlib/Algebra/Category/Grp/ForgetCorepresentable.lean @@ -95,18 +95,18 @@ def AddCommGrp.coyonedaObjIsoForget : coyoneda.obj (op (of (ULift.{u} ℤ))) ≅ forget AddCommGrp.{u} := (NatIso.ofComponents (fun M => (AddMonoidHom.fromULiftIntEquiv M.α).toIso)) -instance Grp.forget_corepresentable : - (forget Grp.{u}).Corepresentable where - has_corepresentation := ⟨_, ⟨Grp.coyonedaObjIsoForget⟩⟩ +instance Grp.forget_isCorepresentable : + (forget Grp.{u}).IsCorepresentable := + Functor.IsCorepresentable.mk' Grp.coyonedaObjIsoForget -instance CommGrp.forget_corepresentable : - (forget CommGrp.{u}).Corepresentable where - has_corepresentation := ⟨_, ⟨CommGrp.coyonedaObjIsoForget⟩⟩ +instance CommGrp.forget_isCorepresentable : + (forget CommGrp.{u}).IsCorepresentable := + Functor.IsCorepresentable.mk' CommGrp.coyonedaObjIsoForget -instance AddGrp.forget_corepresentable : - (forget AddGrp.{u}).Corepresentable where - has_corepresentation := ⟨_, ⟨AddGrp.coyonedaObjIsoForget⟩⟩ +instance AddGrp.forget_isCorepresentable : + (forget AddGrp.{u}).IsCorepresentable := + Functor.IsCorepresentable.mk' AddGrp.coyonedaObjIsoForget -instance AddCommGrp.forget_corepresentable : - (forget AddCommGrp.{u}).Corepresentable where - has_corepresentation := ⟨_, ⟨AddCommGrp.coyonedaObjIsoForget⟩⟩ +instance AddCommGrp.forget_isCorepresentable : + (forget AddCommGrp.{u}).IsCorepresentable := + Functor.IsCorepresentable.mk' AddCommGrp.coyonedaObjIsoForget diff --git a/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean b/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean index b690a7f5f0bb5..413f5f5b36aba 100644 --- a/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean +++ b/Mathlib/Algebra/Category/HopfAlgebraCat/Basic.lean @@ -58,7 +58,7 @@ lemma of_counit {X : Type v} [Ring X] [HopfAlgebra R X] : /-- A type alias for `BialgHom` to avoid confusion between the categorical and algebraic spellings of composition. -/ @[ext] -structure Hom (V W : HopfAlgebraCat.{v} R) := +structure Hom (V W : HopfAlgebraCat.{v} R) where /-- The underlying `BialgHom`. -/ toBialgHom : V →ₐc[R] W diff --git a/Mathlib/Algebra/Category/ModuleCat/Basic.lean b/Mathlib/Algebra/Category/ModuleCat/Basic.lean index 48187e0d55415..ec69a10b56fc3 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Basic.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Basic.lean @@ -151,18 +151,6 @@ theorem forget₂_map (X Y : ModuleCat R) (f : X ⟶ Y) : (forget₂ (ModuleCat R) AddCommGrp).map f = LinearMap.toAddMonoidHom f := rfl --- Porting note (#11215): TODO: `ofHom` and `asHom` are duplicates! - -/-- Typecheck a `LinearMap` as a morphism in `Module R`. -/ -def ofHom {R : Type u} [Ring R] {X Y : Type v} [AddCommGroup X] [Module R X] [AddCommGroup Y] - [Module R Y] (f : X →ₗ[R] Y) : of R X ⟶ of R Y := - f - -@[simp 1100] -theorem ofHom_apply {R : Type u} [Ring R] {X Y : Type v} [AddCommGroup X] [Module R X] - [AddCommGroup Y] [Module R Y] (f : X →ₗ[R] Y) (x : X) : ofHom f x = f x := - rfl - instance : Inhabited (ModuleCat R) := ⟨of R PUnit⟩ @@ -218,14 +206,25 @@ end ModuleCat variable {R} variable {X₁ X₂ : Type v} +open ModuleCat + /-- Reinterpreting a linear map in the category of `R`-modules. -/ def ModuleCat.asHom [AddCommGroup X₁] [Module R X₁] [AddCommGroup X₂] [Module R X₂] : (X₁ →ₗ[R] X₂) → (ModuleCat.of R X₁ ⟶ ModuleCat.of R X₂) := id +@[deprecated (since := "2024-10-06")] alias ModuleCat.ofHom := ModuleCat.asHom + /-- Reinterpreting a linear map in the category of `R`-modules -/ scoped[ModuleCat] notation "↟" f:1024 => ModuleCat.asHom f +@[simp 1100] +theorem ModuleCat.asHom_apply {R : Type u} [Ring R] {X Y : Type v} [AddCommGroup X] [Module R X] + [AddCommGroup Y] [Module R Y] (f : X →ₗ[R] Y) (x : X) : (↟ f) x = f x := + rfl + +@[deprecated (since := "2024-10-06")] alias ModuleCat.ofHom_apply := ModuleCat.asHom_apply + /-- Reinterpreting a linear map in the category of `R`-modules. -/ def ModuleCat.asHomRight [AddCommGroup X₁] [Module R X₁] {X₂ : ModuleCat.{v} R} : (X₁ →ₗ[R] X₂) → (ModuleCat.of R X₁ ⟶ X₂) := @@ -441,8 +440,9 @@ end ModuleCat @[simp] theorem LinearMap.comp_id_moduleCat {R} [Ring R] {G : ModuleCat.{u} R} {H : Type u} [AddCommGroup H] [Module R H] (f : G →ₗ[R] H) : f.comp (𝟙 G) = f := - Category.id_comp (ModuleCat.ofHom f) + Category.id_comp (ModuleCat.asHom f) @[simp] theorem LinearMap.id_moduleCat_comp {R} [Ring R] {G : Type u} [AddCommGroup G] [Module R G] {H : ModuleCat.{u} R} (f : G →ₗ[R] H) : LinearMap.comp (𝟙 H) f = f := - Category.comp_id (ModuleCat.ofHom f) + Category.comp_id (ModuleCat.asHom f) + diff --git a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean index 445b26e61ac33..4bb37bb584fd6 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Biproducts.lean @@ -152,8 +152,8 @@ of modules. -/ noncomputable def lequivProdOfRightSplitExact {f : B →ₗ[R] M} (hj : Function.Injective j) (exac : LinearMap.range j = LinearMap.ker g) (h : g.comp f = LinearMap.id) : (A × B) ≃ₗ[R] M := ((ShortComplex.Splitting.ofExactOfSection _ - (ShortComplex.Exact.moduleCat_of_range_eq_ker (ModuleCat.ofHom j) - (ModuleCat.ofHom g) exac) (asHom f) h + (ShortComplex.Exact.moduleCat_of_range_eq_ker (ModuleCat.asHom j) + (ModuleCat.asHom g) exac) (asHom f) h (by simpa only [ModuleCat.mono_iff_injective])).isoBinaryBiproduct ≪≫ biprodIsoProd _ _ ).symm.toLinearEquiv @@ -162,8 +162,8 @@ of modules. -/ noncomputable def lequivProdOfLeftSplitExact {f : M →ₗ[R] A} (hg : Function.Surjective g) (exac : LinearMap.range j = LinearMap.ker g) (h : f.comp j = LinearMap.id) : (A × B) ≃ₗ[R] M := ((ShortComplex.Splitting.ofExactOfRetraction _ - (ShortComplex.Exact.moduleCat_of_range_eq_ker (ModuleCat.ofHom j) - (ModuleCat.ofHom g) exac) (ModuleCat.ofHom f) h + (ShortComplex.Exact.moduleCat_of_range_eq_ker (ModuleCat.asHom j) + (ModuleCat.asHom g) exac) (ModuleCat.asHom f) h (by simpa only [ModuleCat.epi_iff_surjective] using hg)).isoBinaryBiproduct ≪≫ biprodIsoProd _ _).symm.toLinearEquiv diff --git a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean index 0948d11f47375..25c3bca193dcb 100644 --- a/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/ChangeOfRings.lean @@ -155,11 +155,11 @@ def restrictScalarsId'App (hf : f = RingHom.id R) (M : ModuleCat R) : variable (hf : f = RingHom.id R) -lemma restrictScalarsId'App_hom_apply (M : ModuleCat R) (x : M) : +@[simp] lemma restrictScalarsId'App_hom_apply (M : ModuleCat R) (x : M) : (restrictScalarsId'App f hf M).hom x = x := rfl -lemma restrictScalarsId'App_inv_apply (M : ModuleCat R) (x : M) : +@[simp] lemma restrictScalarsId'App_inv_apply (M : ModuleCat R) (x : M) : (restrictScalarsId'App f hf M).inv x = x := rfl @@ -202,11 +202,11 @@ def restrictScalarsComp'App (hgf : gf = g.comp f) (M : ModuleCat R₃) : variable (hgf : gf = g.comp f) -lemma restrictScalarsComp'App_hom_apply (M : ModuleCat R₃) (x : M) : +@[simp] lemma restrictScalarsComp'App_hom_apply (M : ModuleCat R₃) (x : M) : (restrictScalarsComp'App f g gf hgf M).hom x = x := rfl -lemma restrictScalarsComp'App_inv_apply (M : ModuleCat R₃) (x : M) : +@[simp] lemma restrictScalarsComp'App_inv_apply (M : ModuleCat R₃) (x : M) : (restrictScalarsComp'App f g gf hgf M).inv x = x := rfl @@ -531,7 +531,7 @@ protected def unit' : 𝟭 (ModuleCat S) ⟶ restrictScalars f ⋙ coextendScala Functor.comp_map] rw [coe_comp, coe_comp, Function.comp, Function.comp] conv_rhs => rw [← LinearMap.coe_toAddHom, ← AddHom.toFun_eq_coe] - erw [CoextendScalars.map_apply, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, + rw [CoextendScalars.map_apply, AddHom.toFun_eq_coe, LinearMap.coe_toAddHom, restrictScalars.map_apply f] change s • (g y) = g (s • y) rw [map_smul] diff --git a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean index b826d73a22b10..eef6ac3891d20 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Differentials/Presheaf.lean @@ -78,7 +78,7 @@ variable (d : M.Derivation φ) @[simps! d_apply] def postcomp (f : M ⟶ N) : N.Derivation φ where d := (f.app _).toAddMonoidHom.comp d.d - d_map _ _ := by simp [naturality_apply] + d_map {X Y} g x := by simpa using naturality_apply f g (d.d x) d_app {X} a := by dsimp erw [d_app, map_zero] @@ -175,50 +175,44 @@ end Derivation' namespace DifferentialsConstruction -/-- Auxiliary definition for `relativeDifferentials'`. -/ -noncomputable def relativeDifferentials'BundledCore : - BundledCorePresheafOfModules.{u} (R ⋙ forget₂ _ _) where - obj X := CommRingCat.KaehlerDifferential (φ'.app X) - map f := CommRingCat.KaehlerDifferential.map (φ'.naturality f) - /-- The presheaf of relative differentials of a morphism of presheaves of commutative rings. -/ +@[simps (config := .lemmasOnly)] noncomputable def relativeDifferentials' : - PresheafOfModules.{u} (R ⋙ forget₂ _ _) := - (relativeDifferentials'BundledCore φ').toPresheafOfModules - -@[simp] -lemma relativeDifferentials'_obj (X : Dᵒᵖ) : - (relativeDifferentials' φ').obj X = - CommRingCat.KaehlerDifferential (φ'.app X) := rfl + PresheafOfModules.{u} (R ⋙ forget₂ _ _) where + obj X := CommRingCat.KaehlerDifferential (φ'.app X) + map f := CommRingCat.KaehlerDifferential.map (φ'.naturality f) + map_id _ := by ext; simp; rfl + map_comp _ _ := by ext; simp; rfl --- Note: this cannot be a simp lemma because `dsimp` would --- simplify the composition of functors `R ⋙ forget₂ _ _` -lemma relativeDifferentials'_map_apply {X Y : Dᵒᵖ} (f : X ⟶ Y) - (x : CommRingCat.KaehlerDifferential (φ'.app X)) : - (relativeDifferentials' φ').map f x = - CommRingCat.KaehlerDifferential.map (φ'.naturality f) x := rfl +attribute [simp] relativeDifferentials'_obj -lemma relativeDifferentials'_map_d {X Y : Dᵒᵖ} (f : X ⟶ Y) - (x : R.obj X) : - (relativeDifferentials' φ').map f (CommRingCat.KaehlerDifferential.d x) = - CommRingCat.KaehlerDifferential.d (R.map f x) := by - rw [relativeDifferentials'_map_apply, CommRingCat.KaehlerDifferential.map_d] +@[simp] +lemma relativeDifferentials'_map_d {X Y : Dᵒᵖ} (f : X ⟶ Y) (x : R.obj X) : + DFunLike.coe (α := CommRingCat.KaehlerDifferential (φ'.app X)) + (β := fun _ ↦ CommRingCat.KaehlerDifferential (φ'.app Y)) + ((relativeDifferentials' φ').map f) (CommRingCat.KaehlerDifferential.d x) = + CommRingCat.KaehlerDifferential.d (R.map f x) := + CommRingCat.KaehlerDifferential.map_d (φ'.naturality f) _ /-- The universal derivation. -/ noncomputable def derivation' : (relativeDifferentials' φ').Derivation' φ' := - Derivation'.mk (fun X ↦ CommRingCat.KaehlerDifferential.D (φ'.app X)) (fun X Y f x ↦ by - rw [relativeDifferentials'_map_apply, CommRingCat.KaehlerDifferential.map_d]) + Derivation'.mk (fun X ↦ CommRingCat.KaehlerDifferential.D (φ'.app X)) + (fun _ _ f x ↦ (relativeDifferentials'_map_d φ' f x).symm) /-- The derivation `Derivation' φ'` is universal. -/ noncomputable def isUniversal' : (derivation' φ').Universal := Derivation'.Universal.mk - (fun {M'} d' ↦ Hom.mk'' (fun X ↦ (d'.app X).desc) (fun X Y f ↦ - CommRingCat.KaehlerDifferential.ext (fun b ↦ by - dsimp [ModuleCat.ofHom] - erw [restrictionApp_apply, restrictionApp_apply] - simp only [relativeDifferentials'_map_d, ModuleCat.Derivation.desc_d, - d'.app_apply, d'.d_map]))) + (fun {M'} d' ↦ + { app := fun X ↦ (d'.app X).desc + naturality := fun {X Y} f ↦ CommRingCat.KaehlerDifferential.ext (fun b ↦ by + dsimp + rw [ModuleCat.Derivation.desc_d, Derivation'.app_apply] + erw [relativeDifferentials'_map_d φ' f] + rw [ModuleCat.Derivation.desc_d] + dsimp + rw [Derivation.d_map] + dsimp) }) (fun {M'} d' ↦ by ext X b apply ModuleCat.Derivation.desc_d) diff --git a/Mathlib/Algebra/Category/ModuleCat/Free.lean b/Mathlib/Algebra/Category/ModuleCat/Free.lean index 0cf3303dd9713..9f822325b9425 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Free.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Free.lean @@ -26,7 +26,7 @@ linear algebra, module, free -/ -open CategoryTheory +open CategoryTheory Module namespace ModuleCat @@ -177,11 +177,11 @@ theorem free_shortExact_rank_add [Module.Free R S.X₁] [Module.Free R S.X₃] theorem free_shortExact_finrank_add {n p : ℕ} [Module.Free R S.X₁] [Module.Free R S.X₃] [Module.Finite R S.X₁] [Module.Finite R S.X₃] - (hN : FiniteDimensional.finrank R S.X₁ = n) - (hP : FiniteDimensional.finrank R S.X₃ = p) + (hN : Module.finrank R S.X₁ = n) + (hP : Module.finrank R S.X₃ = p) [StrongRankCondition R] : - FiniteDimensional.finrank R S.X₂ = n + p := by - apply FiniteDimensional.finrank_eq_of_rank_eq + finrank R S.X₂ = n + p := by + apply finrank_eq_of_rank_eq rw [free_shortExact_rank_add hS', ← hN, ← hP] simp only [Nat.cast_add, finrank_eq_rank] diff --git a/Mathlib/Algebra/Category/ModuleCat/Images.lean b/Mathlib/Algebra/Category/ModuleCat/Images.lean index f08f291b4ebfa..9a516ef12b9b4 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Images.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Images.lean @@ -97,12 +97,12 @@ noncomputable def imageIsoRange {G H : ModuleCat.{v} R} (f : G ⟶ H) : @[simp, reassoc, elementwise] theorem imageIsoRange_inv_image_ι {G H : ModuleCat.{v} R} (f : G ⟶ H) : - (imageIsoRange f).inv ≫ Limits.image.ι f = ModuleCat.ofHom f.range.subtype := + (imageIsoRange f).inv ≫ Limits.image.ι f = ModuleCat.asHom f.range.subtype := IsImage.isoExt_inv_m _ _ @[simp, reassoc, elementwise] theorem imageIsoRange_hom_subtype {G H : ModuleCat.{v} R} (f : G ⟶ H) : - (imageIsoRange f).hom ≫ ModuleCat.ofHom f.range.subtype = Limits.image.ι f := by - erw [← imageIsoRange_inv_image_ι f, Iso.hom_inv_id_assoc] + (imageIsoRange f).hom ≫ ModuleCat.asHom f.range.subtype = Limits.image.ι f := by + rw [← imageIsoRange_inv_image_ι f, Iso.hom_inv_id_assoc] end ModuleCat diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean index ecc5852be993d..caf2f760e93ea 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf.lean @@ -9,22 +9,18 @@ import Mathlib.Algebra.Category.Ring.Basic /-! # Presheaves of modules over a presheaf of rings. -We give a hands-on description of a presheaf of modules over a fixed presheaf of rings `R`, -as a presheaf of abelian groups with additional data. +Given a presheaf of rings `R : Cᵒᵖ ⥤ RingCat`, we define the category `PresheafOfModules R`. +An object `M : PresheafOfModules R` consists of a family of modules +`M.obj X : ModuleCat (R.obj X)` for all `X : Cᵒᵖ`, together with the data, for all `f : X ⟶ Y`, +of a functorial linear map `M.map f` from `M.obj X` to the restriction +of scalars of `M.obj Y` via `R.map f`. -We also provide two alternative constructors : -* When `M : CorePresheafOfModules R` consists of a family of unbundled modules over `R.obj X` -for all `X`, the corresponding presheaf of modules is `M.toPresheafOfModules`. -* When `M : BundledCorePresheafOfModules R` consists of a family of objects in -`ModuleCat (R.obj X)` for all `X`, the corresponding presheaf of modules -is `M.toPresheafOfModules`. ## Future work * Compare this to the definition as a presheaf of pairs `(R, M)` with specified first part. * Compare this to the definition as a module object of the presheaf of rings thought of as a monoid object. -* (Pre)sheaves of modules over a given sheaf of rings are an abelian category. * Presheaves of modules over a presheaf of commutative rings form a monoidal category. * Pushforward and pullback. -/ @@ -33,148 +29,191 @@ universe v v₁ u₁ u open CategoryTheory LinearMap Opposite -variable {C : Type u₁} [Category.{v₁} C] +variable {C : Type u₁} [Category.{v₁} C] {R : Cᵒᵖ ⥤ RingCat.{u}} -/-- A presheaf of modules over a given presheaf of rings, -described as a presheaf of abelian groups, and the extra data of the action at each object, -and a condition relating functoriality and scalar multiplication. -/ -structure PresheafOfModules (R : Cᵒᵖ ⥤ RingCat.{u}) where - presheaf : Cᵒᵖ ⥤ AddCommGrp.{v} - module : ∀ X : Cᵒᵖ, Module (R.obj X) (presheaf.obj X) := by infer_instance - map_smul : ∀ {X Y : Cᵒᵖ} (f : X ⟶ Y) (r : R.obj X) (x : presheaf.obj X), - presheaf.map f (r • x) = R.map f r • presheaf.map f x := by aesop_cat - -variable {R : Cᵒᵖ ⥤ RingCat.{u}} +variable (R) in +/-- A presheaf of modules over `R : Cᵒᵖ ⥤ RingCat` consists of family of +objects `obj X : ModuleCat (R.obj X)` for all `X : Cᵒᵖ` together with +functorial maps `obj X ⟶ (ModuleCat.restrictScalars (R.map f)).obj (obj Y)` +for all `f : X ⟶ Y` in `Cᵒᵖ`. -/ +structure PresheafOfModules where + /-- a family of modules over `R.obj X` for all `X` -/ + obj (X : Cᵒᵖ) : ModuleCat.{v} (R.obj X) + /-- the restriction maps of a presheaf of modules -/ + map {X Y : Cᵒᵖ} (f : X ⟶ Y) : obj X ⟶ (ModuleCat.restrictScalars (R.map f)).obj (obj Y) + map_id (X : Cᵒᵖ) : + map (𝟙 X) = (ModuleCat.restrictScalarsId' _ (R.map_id X)).inv.app _ := by aesop_cat + map_comp {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : + map (f ≫ g) = map f ≫ (ModuleCat.restrictScalars _).map (map g) ≫ + (ModuleCat.restrictScalarsComp' _ _ _ (R.map_comp f g)).inv.app _ := by aesop_cat namespace PresheafOfModules -attribute [instance] PresheafOfModules.module - -/-- The bundled module over an object `X`. -/ -def obj (P : PresheafOfModules R) (X : Cᵒᵖ) : ModuleCat (R.obj X) := - ModuleCat.of _ (P.presheaf.obj X) - -/-- -If `P` is a presheaf of modules over a presheaf of rings `R`, both over some category `C`, -and `f : X ⟶ Y` is a morphism in `Cᵒᵖ`, we construct the `R.map f`-semilinear map -from the `R.obj X`-module `P.presheaf.obj X` to the `R.obj Y`-module `P.presheaf.obj Y`. - -/ -def map (P : PresheafOfModules R) {X Y : Cᵒᵖ} (f : X ⟶ Y) : - P.obj X →ₛₗ[R.map f] P.obj Y := - { toAddHom := (P.presheaf.map f).toAddHom, - map_smul' := P.map_smul f, } - -theorem map_apply (P : PresheafOfModules R) {X Y : Cᵒᵖ} (f : X ⟶ Y) (x) : - P.map f x = (P.presheaf.map f) x := - rfl +attribute [simp] map_id map_comp +attribute [reassoc] map_comp -instance (X : Cᵒᵖ) : RingHomId (R.map (𝟙 X)) where - eq_id := R.map_id X +variable (M M₁ M₂ : PresheafOfModules.{v} R) -instance {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : - RingHomCompTriple (R.map f) (R.map g) (R.map (f ≫ g)) where - comp_eq := (R.map_comp f g).symm +lemma map_smul {X Y : Cᵒᵖ} (f : X ⟶ Y) (r : R.obj X) (m : M.obj X) : + M.map f (r • m) = R.map f r • M.map f m := by simp -@[simp] -theorem map_id (P : PresheafOfModules R) (X : Cᵒᵖ) : - P.map (𝟙 X) = LinearMap.id' := by - ext - simp [map_apply] +lemma congr_map_apply {X Y : Cᵒᵖ} {f g : X ⟶ Y} (h : f = g) (m : M.obj X) : + M.map f m = M.map g m := by rw [h] -@[simp] -theorem map_comp (P : PresheafOfModules R) {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : - P.map (f ≫ g) = (P.map g).comp (P.map f) := by - ext - simp [map_apply] +/-- A morphism of presheaves of modules consists of a family of linear maps which +satisfy the naturality condition. -/ +@[ext] +structure Hom where + /-- a family of linear maps `M₁.obj X ⟶ M₂.obj X` for all `X`. -/ + app (X : Cᵒᵖ) : M₁.obj X ⟶ M₂.obj X + naturality {X Y : Cᵒᵖ} (f : X ⟶ Y) : + M₁.map f ≫ (ModuleCat.restrictScalars (R.map f)).map (app Y) = + app X ≫ M₂.map f := by aesop_cat -/-- A morphism of presheaves of modules. -/ -structure Hom (P Q : PresheafOfModules R) where - hom : P.presheaf ⟶ Q.presheaf - map_smul : ∀ (X : Cᵒᵖ) (r : R.obj X) (x : P.presheaf.obj X), hom.app X (r • x) = r • hom.app X x +attribute [reassoc (attr := simp)] Hom.naturality -namespace Hom +instance : Category (PresheafOfModules.{v} R) where + Hom := Hom + id _ := { app := fun _ ↦ 𝟙 _ } + comp f g := { app := fun _ ↦ f.app _ ≫ g.app _ } -/-- The identity morphism on a presheaf of modules. -/ -def id (P : PresheafOfModules R) : Hom P P where - hom := 𝟙 _ - map_smul _ _ _ := rfl +variable {M₁ M₂} -/-- Composition of morphisms of presheaves of modules. -/ -def comp {P Q R : PresheafOfModules R} (f : Hom P Q) (g : Hom Q R) : Hom P R where - hom := f.hom ≫ g.hom - map_smul _ _ _ := by simp [Hom.map_smul] +@[ext] +lemma hom_ext {f g : M₁ ⟶ M₂} (h : ∀ (X : Cᵒᵖ), f.app X = g.app X) : + f = g := Hom.ext (by ext1; apply h) -end Hom +@[simp] +lemma id_app (M : PresheafOfModules R) (X : Cᵒᵖ) : Hom.app (𝟙 M) X = 𝟙 _ := by + rfl -instance : Category (PresheafOfModules R) where - Hom := Hom - id := Hom.id - comp f g := Hom.comp f g +@[simp] +lemma comp_app {M₁ M₂ M₃ : PresheafOfModules R} (f : M₁ ⟶ M₂) (g : M₂ ⟶ M₃) (X : Cᵒᵖ) : + (f ≫ g).app X = f.app X ≫ g.app X := by + rfl -namespace Hom +lemma naturality_apply (f : M₁ ⟶ M₂) {X Y : Cᵒᵖ} (g : X ⟶ Y) (x : M₁.obj X) : + Hom.app f Y (M₁.map g x) = M₂.map g (Hom.app f X x) := + congr_fun ((forget _).congr_map (Hom.naturality f g)) x -variable {P Q T : PresheafOfModules R} +/-- The underlying presheaf of abelian groups of a presheaf of modules. -/ +def presheaf : Cᵒᵖ ⥤ Ab where + obj X := (forget₂ _ _).obj (M.obj X) + map f := AddMonoidHom.mk' (M.map f) (by simp) -variable (P) in @[simp] -lemma id_hom : Hom.hom (𝟙 P) = 𝟙 _ := rfl - -@[simp, reassoc] -lemma comp_hom (f : P ⟶ Q) (g : Q ⟶ T) : (f ≫ g).hom = f.hom ≫ g.hom := rfl - -/-- -The `(X : Cᵒᵖ)`-component of morphism between presheaves of modules -over a presheaf of rings `R`, as an `R.obj X`-linear map. -/ -def app (f : Hom P Q) (X : Cᵒᵖ) : P.obj X →ₗ[R.obj X] Q.obj X := - { toAddHom := (f.hom.app X).toAddHom - map_smul' := f.map_smul X } +lemma presheaf_obj_coe (X : Cᵒᵖ) : + (M.presheaf.obj X : Type _) = M.obj X := rfl @[simp] -lemma comp_app (f : P ⟶ Q) (g : Q ⟶ T) (X : Cᵒᵖ) : - (f ≫ g).app X = (g.app X).comp (f.app X) := rfl +lemma presheaf_map_apply_coe {X Y : Cᵒᵖ} (f : X ⟶ Y) (x : M.obj X) : + DFunLike.coe (α := M.obj X) (β := fun _ ↦ M.obj Y) (M.presheaf.map f) x = M.map f x := rfl -@[ext] -theorem ext {f g : P ⟶ Q} (w : ∀ X, f.app X = g.app X) : f = g := by - cases f; cases g - congr - ext X x - exact LinearMap.congr_fun (w X) x +instance (M : PresheafOfModules R) (X : Cᵒᵖ) : + Module (R.obj X) (M.presheaf.obj X) := + inferInstanceAs (Module (R.obj X) (M.obj X)) -instance : Zero (P ⟶ Q) := ⟨mk 0 (by - intros - simp only [Limits.zero_app, AddMonoidHom.zero_apply, smul_zero])⟩ +variable (R) in +/-- The forgetful functor `PresheafOfModules R ⥤ Cᵒᵖ ⥤ Ab`. -/ +def toPresheaf : PresheafOfModules.{v} R ⥤ Cᵒᵖ ⥤ Ab where + obj M := M.presheaf + map f := + { app := fun X ↦ AddMonoidHom.mk' (Hom.app f X) (by simp) + naturality := fun X Y g ↦ by ext x; exact naturality_apply f g x } -variable (P Q) +@[simp] +lemma toPresheaf_obj_coe (X : Cᵒᵖ) : + (((toPresheaf R).obj M).obj X : Type _) = M.obj X := rfl @[simp] -lemma zero_app (X : Cᵒᵖ) : (0 : P ⟶ Q).app X = 0 := rfl +lemma toPresheaf_map_app_apply (f : M₁ ⟶ M₂) (X : Cᵒᵖ) (x : M₁.obj X) : + DFunLike.coe (α := M₁.obj X) (β := fun _ ↦ M₂.obj X) + (((toPresheaf R).map f).app X) x = f.app X x := rfl -variable {P Q} +instance : (toPresheaf R).Faithful where + map_injective {_ _ f g} h := by + ext X x + exact congr_fun (((evaluation _ _).obj X ⋙ forget _).congr_map h) x -instance : Add (P ⟶ Q) := ⟨fun f g => mk (f.hom + g.hom) (by - intros - simp only [NatTrans.app_add, AddCommGrp.hom_add_apply, map_smul, smul_add])⟩ +section -@[simp] -lemma add_app (f g : P ⟶ Q) (X : Cᵒᵖ) : (f + g).app X = f.app X + g.app X := rfl +variable (M : Cᵒᵖ ⥤ Ab.{v}) [∀ X, Module (R.obj X) (M.obj X)] + (map_smul : ∀ ⦃X Y : Cᵒᵖ⦄ (f : X ⟶ Y) (r : R.obj X) (m : M.obj X), + M.map f (r • m) = R.map f r • M.map f m) -instance : Sub (P ⟶ Q) := ⟨fun f g => mk (f.hom - g.hom) (by - intros - rw [NatTrans.app_sub, AddMonoidHom.sub_apply, AddMonoidHom.sub_apply, - smul_sub, map_smul, map_smul])⟩ +/-- The object in `PresheafOfModules R` that is obtained from `M : Cᵒᵖ ⥤ Ab.{v}` such +that for all `X : Cᵒᵖ`, `M.obj X` is a `R.obj X` module, in such a way that the +restriction maps are semilinear. (This constructor should be used only in cases +when the preferred constructor `PresheafOfModules.mk` is not as convenient as this one.) -/ +@[simps] +def ofPresheaf : PresheafOfModules.{v} R where + obj X := ModuleCat.of _ (M.obj X) + map f := + { toFun := fun x ↦ M.map f x + map_add' := by simp + map_smul' := fun r m ↦ map_smul f r m } @[simp] -lemma sub_app (f g : P ⟶ Q) (X : Cᵒᵖ) : (f - g).app X = f.app X - g.app X := rfl +lemma ofPresheaf_presheaf : (ofPresheaf M map_smul).presheaf = M := rfl -instance : Neg (P ⟶ Q) := ⟨fun f => mk (-f.hom) (by - intros - rw [NatTrans.app_neg, AddMonoidHom.neg_apply, AddMonoidHom.neg_apply, - map_smul, smul_neg])⟩ - -@[simp] -lemma neg_app (f : P ⟶ Q) (X : Cᵒᵖ) : (-f).app X = -f.app X := rfl +end -instance : AddCommGroup (P ⟶ Q) where +/-- The morphism of presheaves of modules `M₁ ⟶ M₂` given by a morphism +of abelian presheaves `M₁.presheaf ⟶ M₂.presheaf` +which satisfy a suitable linearity condition. -/ +@[simps] +def homMk (φ : M₁.presheaf ⟶ M₂.presheaf) + (hφ : ∀ (X : Cᵒᵖ) (r : R.obj X) (m : M₁.obj X), φ.app X (r • m) = r • φ.app X m) : + M₁ ⟶ M₂ where + app X := + { toFun := φ.app X + map_add' := by simp + map_smul' := hφ X } + naturality := fun f ↦ by + ext x + exact congr_fun ((forget _).congr_map (φ.naturality f)) x + +instance : Zero (M₁ ⟶ M₂) where + zero := { app := fun _ ↦ 0 } + +variable (M₁ M₂) in +@[simp] lemma zero_app (X : Cᵒᵖ) : (0 : M₁ ⟶ M₂).app X = 0 := rfl + +instance : Neg (M₁ ⟶ M₂) where + neg f := + { app := fun X ↦ -f.app X + naturality := fun {X Y} h ↦ by + ext x + dsimp + erw [map_neg] + rw [← naturality_apply] + rfl } + +instance : Add (M₁ ⟶ M₂) where + add f g := + { app := fun X ↦ f.app X + g.app X + naturality := fun {X Y} h ↦ by + ext x + dsimp + erw [map_add] + rw [← naturality_apply, ← naturality_apply] + rfl } + +instance : Sub (M₁ ⟶ M₂) where + sub f g := + { app := fun X ↦ f.app X - g.app X + naturality := fun {X Y} h ↦ by + ext x + dsimp + erw [map_sub] + rw [← naturality_apply, ← naturality_apply] + rfl } + +@[simp] lemma neg_app (f : M₁ ⟶ M₂) (X : Cᵒᵖ) : (-f).app X = -f.app X := rfl +@[simp] lemma add_app (f g : M₁ ⟶ M₂) (X : Cᵒᵖ) : (f + g).app X = f.app X + g.app X := rfl +@[simp] lemma sub_app (f g : M₁ ⟶ M₂) (X : Cᵒᵖ) : (f - g).app X = f.app X - g.app X := rfl + +instance : AddCommGroup (M₁ ⟶ M₂) where add_assoc := by intros; ext1; simp only [add_app, add_assoc] zero_add := by intros; ext1; simp only [add_app, zero_app, zero_add] neg_add_cancel := by intros; ext1; simp only [add_app, neg_app, neg_add_cancel, zero_app] @@ -185,41 +224,14 @@ instance : AddCommGroup (P ⟶ Q) where zsmul := zsmulRec instance : Preadditive (PresheafOfModules R) where - add_comp := by intros; ext1; simp only [comp_app, add_app, comp_add] - comp_add := by intros; ext1; simp only [comp_app, add_app, add_comp] - -end Hom - -lemma naturality_apply {P Q : PresheafOfModules R} (f : P ⟶ Q) - {X Y : Cᵒᵖ} (g : X ⟶ Y) (x : P.obj X) : - f.app Y (P.map g x) = Q.map g (f.app X x) := - congr_fun ((forget _).congr_map (f.hom.naturality g)) x - -variable (R) - -/-- The functor from presheaves of modules over a specified presheaf of rings, -to presheaves of abelian groups. --/ -@[simps obj] -def toPresheaf : PresheafOfModules.{v} R ⥤ (Cᵒᵖ ⥤ AddCommGrp.{v}) where - obj P := P.presheaf - map f := f.hom - -variable {R} - -@[simp] -lemma toPresheaf_map_app {P Q : PresheafOfModules R} - (f : P ⟶ Q) (X : Cᵒᵖ) : - ((toPresheaf R).map f).app X = (f.app X).toAddMonoidHom := rfl instance : (toPresheaf R).Additive where -instance : (toPresheaf R).Faithful where - map_injective {P Q} f g h := by - ext X x - have eq := congr_app h X - simp only [toPresheaf_obj, toPresheaf_map_app] at eq - simp only [← toAddMonoidHom_coe, eq] +lemma zsmul_app (n : ℤ) (f : M₁ ⟶ M₂) (X : Cᵒᵖ) : (n • f).app X = n • f.app X := by + ext x + change (toPresheaf R ⋙ (evaluation _ _).obj X).map (n • f) x = _ + rw [Functor.map_zsmul] + rfl variable (R) @@ -230,215 +242,22 @@ def evaluation (X : Cᵒᵖ) : PresheafOfModules.{v} R ⥤ ModuleCat (R.obj X) w obj M := M.obj X map f := f.app X -instance (X : Cᵒᵖ) : (evaluation R X).Additive where - -variable {R} - -/-- Given a presheaf of modules `M` on a category `C` and `f : X ⟶ Y` in `Cᵒᵖ`, this -is the restriction map `M.obj X ⟶ M.obj Y`, considered as a linear map to -the restriction of scalars of `M.obj Y`. -/ -noncomputable def restrictionApp {X Y : Cᵒᵖ} (f : X ⟶ Y) (M : PresheafOfModules.{v} R) : - M.obj X ⟶ (ModuleCat.restrictScalars (R.map f)).obj (M.obj Y) := - ModuleCat.semilinearMapAddEquiv (R.map f) _ _ (M.map f) - -lemma restrictionApp_apply {X Y : Cᵒᵖ} (f : X ⟶ Y) (M : PresheafOfModules R) (x : M.obj X) : - restrictionApp f M x = M.map f x := by - rfl - -variable (R) +instance (X : Cᵒᵖ) : (evaluation.{v} R X).Additive where /-- The restriction natural transformation on presheaves of modules, considered as linear maps to restriction of scalars. -/ @[simps] noncomputable def restriction {X Y : Cᵒᵖ} (f : X ⟶ Y) : evaluation R X ⟶ evaluation R Y ⋙ ModuleCat.restrictScalars (R.map f) where - app := restrictionApp f - naturality := fun M N φ => by - ext x - exact (congr_hom (φ.hom.naturality f) x).symm - -variable {R} - -@[reassoc (attr := simp)] -lemma restrictionApp_naturality {X Y : Cᵒᵖ} (f : X ⟶ Y) - {M N : PresheafOfModules R} (φ : M ⟶ N) : - restrictionApp f M ≫ (ModuleCat.restrictScalars (R.map f)).map (Hom.app φ Y) = - ModuleCat.ofHom (Hom.app φ X) ≫ restrictionApp f N := - ((restriction R f).naturality φ).symm - -attribute [local simp] restrictionApp_apply - -lemma restrictionApp_id (M : PresheafOfModules R) (X : Cᵒᵖ) : - restrictionApp (𝟙 X) M = - (ModuleCat.restrictScalarsId' (R.map (𝟙 X)) (R.map_id X)).inv.app (M.obj X) := by aesop - -lemma restrictionApp_comp (M : PresheafOfModules R) {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : - restrictionApp (f ≫ g) M = - restrictionApp f M ≫ - (ModuleCat.restrictScalars (R.map f)).map (restrictionApp g M) ≫ - (ModuleCat.restrictScalarsComp' _ _ _ (R.map_comp f g)).inv.app (M.obj Z) := by aesop - -namespace Hom - -variable {P Q : PresheafOfModules R} (app : ∀ X, P.obj X →ₗ[R.obj X] Q.obj X) - -section - -variable (naturality : ∀ ⦃X Y : Cᵒᵖ⦄ (f : X ⟶ Y) (x : P.obj X), - app Y (P.map f x) = Q.map f (app X x)) - -/-- A constructor for morphisms in `PresheafOfModules R` that is based on the data -of a family of linear maps over the various rings `R.obj X`. -/ -def mk' : P ⟶ Q where - hom := - { app := fun X => (app X).toAddMonoidHom - naturality := fun _ _ f => AddCommGrp.ext (naturality f) } - map_smul X := (app X).map_smul - -@[simp] -lemma mk'_app : (mk' app naturality).app = app := rfl - -end - -/-- A constructor for morphisms in `PresheafOfModules R` that is based on the data -of a family of linear maps over the various rings `R.obj X`, and for which the -naturality condition is stated using the restriction of scalars. -/ -abbrev mk'' - (naturality : ∀ ⦃X Y : Cᵒᵖ⦄ (f : X ⟶ Y), - restrictionApp f P ≫ (ModuleCat.restrictScalars (R.map f)).map (app Y) = - ModuleCat.ofHom (app X) ≫ restrictionApp f Q) : - P ⟶ Q := - mk' app (fun _ _ f x => congr_hom (naturality f) x) - -end Hom - -end PresheafOfModules - -variable (R) in -/-- This structure contains the data and axioms in order to -produce a `PresheafOfModules R` from a collection of types -equipped with module structures over the various rings `R.obj X`. -(See the constructor `PresheafOfModules.mk'`.) -/ -structure CorePresheafOfModules where - /-- the datum of a type for each object in `Cᵒᵖ` -/ - obj (X : Cᵒᵖ) : Type v - /-- the abelian group structure on the types `obj X` -/ - addCommGroup (X : Cᵒᵖ) : AddCommGroup (obj X) := by infer_instance - /-- the module structure on the types `obj X` over the various rings `R.obj X` -/ - module (X : Cᵒᵖ) : Module (R.obj X) (obj X) := by infer_instance - /-- the semi-linear restriction maps -/ - map {X Y : Cᵒᵖ} (f : X ⟶ Y) : obj X →ₛₗ[R.map f] obj Y - /-- `map` is compatible with the identities -/ - map_id (X : Cᵒᵖ) (x : obj X) : map (𝟙 X) x = x := by aesop_cat - /-- `map` is compatible with the composition -/ - map_comp {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) (x : obj X) : - map (f ≫ g) x = map g (map f x) := by aesop_cat - --- this example is meant to test automation: the axioms for `CorePresheafOfModules` are --- automatically found if we use the data from `M : PresheafOfModules R` -example (M : PresheafOfModules R) : CorePresheafOfModules R where - obj X := M.obj X - map f := M.map f - -namespace CorePresheafOfModules - -attribute [instance] addCommGroup module -attribute [simp] map_id map_comp - -variable (M : CorePresheafOfModules R) - -/-- The presheaf of abelian groups attached to a `CorePresheafOfModules R`. -/ -@[simps] -def presheaf : Cᵒᵖ ⥤ AddCommGrp.{v} where - obj X := AddCommGrp.of (M.obj X) - map f := AddCommGrp.ofHom (M.map f).toAddMonoidHom - -instance (X : Cᵒᵖ) : Module (R.obj X) (M.presheaf.obj X) := M.module X - -/-- Constructor for `PresheafOfModules R` based on a collection of types -equipped with module structures over the various rings `R.obj X`, see -the structure `CorePresheafOfModules`. -/ -def toPresheafOfModules : PresheafOfModules R where - presheaf := M.presheaf - -@[simp] -lemma toPresheafOfModules_obj (X : Cᵒᵖ) : - M.toPresheafOfModules.obj X = ModuleCat.of _ (M.obj X) := rfl - -@[simp] -lemma toPresheafOfModules_presheaf_map_apply {X Y : Cᵒᵖ} (f : X ⟶ Y) (x : M.obj X) : - M.toPresheafOfModules.presheaf.map f x = M.map f x := rfl - -end CorePresheafOfModules - -variable (R) in -/-- This structure contains the data and axioms in order to -produce a `PresheafOfModules R` from a collection of objects -of type `ModuleCat (R.obj X)` for all `X`, and restriction -maps expressed as linear maps to restriction of scalars. -(See the constructor `PresheafOfModules.mk''`.) -/ -structure BundledCorePresheafOfModules where - /-- the datum of a `ModuleCat (R.obj X)` for each object in `Cᵒᵖ` -/ - obj (X : Cᵒᵖ) : ModuleCat.{v} (R.obj X) - /-- the restriction maps as linear maps to restriction of scalars -/ - map {X Y : Cᵒᵖ} (f : X ⟶ Y) : obj X ⟶ (ModuleCat.restrictScalars (R.map f)).obj (obj Y) - /-- `map` is compatible with the identities -/ - map_id (X : Cᵒᵖ) : - map (𝟙 X) = (ModuleCat.restrictScalarsId' (R.map (𝟙 X)) (R.map_id X)).inv.app (obj X) := by - aesop - /-- `map` is compatible with the composition -/ - map_comp {X Y Z : Cᵒᵖ} (f : X ⟶ Y) (g : Y ⟶ Z) : - map (f ≫ g) = map f ≫ (ModuleCat.restrictScalars (R.map f)).map (map g) ≫ - (ModuleCat.restrictScalarsComp' (R.map f) (R.map g) (R.map (f ≫ g)) - (R.map_comp f g)).inv.app (obj Z) := by aesop - -namespace BundledCorePresheafOfModules - -variable (M : BundledCorePresheafOfModules R) - -attribute [local simp] map_id map_comp - -/-- The obvious map `BundledCorePresheafOfModules R → CorePresheafOfModules R`. -/ -noncomputable def toCorePresheafOfModules : CorePresheafOfModules R where - obj X := (M.obj X).carrier - map {X Y} f := (ModuleCat.semilinearMapAddEquiv (R.map f) (M.obj X) (M.obj Y)).symm (M.map f) - -/-- Constructor for `PresheafOfModules R` based on a collection of objects -of type `ModuleCat (R.obj X)` for all `X`, and restriction maps expressed -as linear maps to restriction of scalars, see -the structure `BundledCorePresheafOfModules`. -/ -noncomputable def toPresheafOfModules : PresheafOfModules R := - M.toCorePresheafOfModules.toPresheafOfModules - -@[simp] -lemma toPresheafOfModules_obj (X : Cᵒᵖ) : - M.toPresheafOfModules.obj X = (M.obj X).carrier := rfl - -@[simp] -lemma toPresheafOfModules_presheaf_map_apply {X Y : Cᵒᵖ} (f : X ⟶ Y) (x : M.obj X) : - M.toPresheafOfModules.presheaf.map f x = M.map f x := rfl - -@[simp] -lemma restrictionApp_toPresheafOfModules {X Y : Cᵒᵖ} (f : X ⟶ Y) : - PresheafOfModules.restrictionApp f M.toPresheafOfModules = M.map f := rfl - -end BundledCorePresheafOfModules - -namespace PresheafOfModules - -variable (R) - -/-- Auxiliary definition for `unit`. -/ -def unitCore : CorePresheafOfModules R where - obj X := R.obj X - map {X Y} f := by - exact - { toFun := (R.map f).toFun - map_add' := by simp - map_smul' := by simp } + app M := M.map f /-- The obvious free presheaf of modules of rank `1`. -/ -abbrev unit : PresheafOfModules R := (unitCore R).toPresheafOfModules +def unit : PresheafOfModules R where + obj X := ModuleCat.of _ (R.obj X) + map {X Y } f := + { toFun := fun x ↦ R.map f x + map_add' := by simp + map_smul' := by aesop_cat } lemma unit_map_one {X Y : Cᵒᵖ} (f : X ⟶ Y) : (unit R).map f (1 : R.obj X) = (1 : R.obj Y) := (R.map f).map_one @@ -448,6 +267,10 @@ variable {R} /-- The type of sections of a presheaf of modules. -/ def sections (M : PresheafOfModules.{v} R) : Type _ := (M.presheaf ⋙ forget _).sections +/-- Given a presheaf of modules `M`, `s : M.sections` and `X : Cᵒᵖ`, this is the induced +element in `M.obj X`. -/ +abbrev sections.eval {M : PresheafOfModules.{v} R} (s : M.sections) (X : Cᵒᵖ) : M.obj X := s.1 X + @[simp] lemma sections_property {M : PresheafOfModules.{v} R} (s : M.sections) {X Y : Cᵒᵖ} (f : X ⟶ Y) : M.map f (s.1 X) = s.1 Y := s.2 f @@ -484,12 +307,12 @@ def unitHomEquiv (M : PresheafOfModules R) : (unit R ⟶ M) ≃ M.sections where toFun f := sectionsMk (fun X ↦ Hom.app f X (1 : R.obj X)) (by intros; rw [← naturality_apply, unit_map_one]) - invFun s := Hom.mk' - (fun X => (LinearMap.ringLmapEquivSelf (R.obj X) ℤ (M.obj X)).symm (s.val X)) (by - intro X Y p (x : R.obj X) - dsimp - rw [map_apply, M.map_smul, ← s.2 p] - rfl) + invFun s := + { app := fun X ↦ (LinearMap.ringLmapEquivSelf (R.obj X) ℤ (M.obj X)).symm (s.val X) + naturality := fun {X Y} f ↦ by + ext (x : R.obj X) + change R.map f x • s.eval Y = M.map f (x • s.eval X) + simp } left_inv f := by ext1 X exact (LinearMap.ringLmapEquivSelf (R.obj X) ℤ (M.obj X)).symm_apply_apply (f.app X) @@ -499,6 +322,8 @@ def unitHomEquiv (M : PresheafOfModules R) : section module_over_initial +variable (X : Cᵒᵖ) (hX : Limits.IsInitial X) + /-! ## `PresheafOfModules R ⥤ Cᵒᵖ ⥤ ModuleCat (R.obj X)` when `X` is initial @@ -506,6 +331,36 @@ When `X` is initial, we have `Module (R.obj X) (M.obj c)` for any `c : Cᵒᵖ`. -/ +section + +variable (M : PresheafOfModules.{v} R) + +/-- Auxiliary definition for `forgetToPresheafModuleCatObj`. -/ +noncomputable abbrev forgetToPresheafModuleCatObjObj (Y : Cᵒᵖ) : ModuleCat (R.obj X) := + (ModuleCat.restrictScalars (R.map (hX.to Y))).obj (M.obj Y) + +@[simp] +lemma forgetToPresheafModuleCatObjObj_coe (Y : Cᵒᵖ) : + (forgetToPresheafModuleCatObjObj X hX M Y : Type _) = M.obj Y := rfl + +/-- Auxiliary definition for `forgetToPresheafModuleCatObj`. -/ +def forgetToPresheafModuleCatObjMap {Y Z : Cᵒᵖ} (f : Y ⟶ Z) : + forgetToPresheafModuleCatObjObj X hX M Y ⟶ + forgetToPresheafModuleCatObjObj X hX M Z where + toFun x := M.map f x + map_add' := by simp + map_smul' r x := by + simp only [ModuleCat.restrictScalars.smul_def, AddHom.toFun_eq_coe, AddHom.coe_mk, + RingHom.id_apply, M.map_smul] + rw [← CategoryTheory.comp_apply, ← R.map_comp] + congr + apply hX.hom_ext + +@[simp] +lemma forgetToPresheafModuleCatObjMap_apply {Y Z : Cᵒᵖ} (f : Y ⟶ Z) (m : M.obj Y) : + DFunLike.coe (α := M.obj Y) (β := fun _ ↦ M.obj Z) + (forgetToPresheafModuleCatObjMap X hX M f) m = M.map f m := rfl + /-- Implementation of the functor `PresheafOfModules R ⥤ Cᵒᵖ ⥤ ModuleCat (R.obj X)` when `X` is initial. @@ -517,20 +372,11 @@ morphism level `(f : M ⟶ N) ↦ (c ↦ f(c))`. @[simps] noncomputable def forgetToPresheafModuleCatObj (X : Cᵒᵖ) (hX : Limits.IsInitial X) (M : PresheafOfModules.{v} R) : - Cᵒᵖ ⥤ ModuleCat (R.1.obj X) where - obj c := - ModuleCat.restrictScalars (R.1.map (hX.to c)) |>.obj <| M.obj c - map := fun {c₁ c₂} f => - { toFun := fun x => M.presheaf.map f x - map_add' := M.presheaf.map f |>.map_add - map_smul' := fun r (m : ModuleCat.restrictScalars _ |>.obj _) => by - simp only [ModuleCat.restrictScalars.smul_def, RingHom.id_apply, M.map_smul] - rw [← CategoryTheory.comp_apply, ← R.map_comp] - congr - apply hX.hom_ext } - map_id := fun c => by ext; simp_rw [M.presheaf.map_id]; rfl - map_comp := fun {c₁ c₂ c₃} f g => by - ext x; simp_rw [M.presheaf.map_comp]; rfl + Cᵒᵖ ⥤ ModuleCat (R.obj X) where + obj Y := forgetToPresheafModuleCatObjObj X hX M Y + map f := forgetToPresheafModuleCatObjMap X hX M f + +end /-- Implementation of the functor `PresheafOfModules R ⥤ Cᵒᵖ ⥤ ModuleCat (R.obj X)` @@ -541,15 +387,15 @@ on `M(c)` is given by restriction of scalars along the unique morphism `R(c) ⟶ morphism level `(f : M ⟶ N) ↦ (c ↦ f(c))`. -/ noncomputable def forgetToPresheafModuleCatMap - (X : Cᵒᵖ) (hX : Limits.IsInitial X) {M N : PresheafOfModules.{v} R} - (f : M ⟶ N) : - forgetToPresheafModuleCatObj X hX M ⟶ - forgetToPresheafModuleCatObj X hX N := - { app := fun c => - { toFun := f.app c - map_add' := (f.app c).map_add - map_smul' := fun r (m : M.presheaf.obj c) => (f.app c).map_smul (R.1.map (hX.to c) _) m } - naturality := fun {c₁ c₂} i => by ext x; exact congr($(f.hom.naturality i) x) } + (X : Cᵒᵖ) (hX : Limits.IsInitial X) {M N : PresheafOfModules.{v} R} (f : M ⟶ N) : + forgetToPresheafModuleCatObj X hX M ⟶ forgetToPresheafModuleCatObj X hX N where + app Y := + { toFun := f.app Y + map_add' := by simp + map_smul' := fun r ↦ (f.app Y).map_smul (R.1.map (hX.to Y) _) } + naturality Y Z g := by + ext x + exact naturality_apply f g x /-- The forgetful functor from presheaves of modules over a presheaf of rings `R` to presheaves of @@ -561,7 +407,7 @@ morphism level `(f : M ⟶ N) ↦ (c ↦ f(c))`. -/ @[simps] noncomputable def forgetToPresheafModuleCat (X : Cᵒᵖ) (hX : Limits.IsInitial X) : - PresheafOfModules.{v} R ⥤ Cᵒᵖ ⥤ ModuleCat (R.1.obj X) where + PresheafOfModules.{v} R ⥤ Cᵒᵖ ⥤ ModuleCat (R.obj X) where obj M := forgetToPresheafModuleCatObj X hX M map f := forgetToPresheafModuleCatMap X hX f diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/ChangeOfRings.lean index c71d1bdc5ca09..987578da8c709 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/ChangeOfRings.lean @@ -25,34 +25,29 @@ variable {C : Type u'} [Category.{v'} C] {R R' : Cᵒᵖ ⥤ RingCat.{u}} /-- The restriction of scalars of presheaves of modules, on objects. -/ @[simps] -noncomputable def restrictScalarsBundledCore (M' : PresheafOfModules R') (α : R ⟶ R') : - BundledCorePresheafOfModules R where - obj X := (ModuleCat.restrictScalars (α.app X)).obj (M'.obj X) - map {X Y} f := +noncomputable def restrictScalarsObj (M' : PresheafOfModules.{v} R') (α : R ⟶ R') : + PresheafOfModules R where + obj := fun X ↦ (ModuleCat.restrictScalars (α.app X)).obj (M'.obj X) + map := fun {X Y} f ↦ { toFun := M'.map f map_add' := map_add _ - map_smul' := fun r x ↦ by + map_smul' := fun r x ↦ (M'.map_smul f (α.app _ r) x).trans (by have eq := RingHom.congr_fun (α.naturality f) r - apply (M'.map_smul f (α.app _ r) x).trans - dsimp at eq ⊢ + dsimp at eq rw [← eq] - rfl } - map_id X := by - ext x - exact LinearMap.congr_fun (M'.map_id X) x - map_comp f g := by - ext x - exact LinearMap.congr_fun (M'.map_comp f g) x + rfl ) } /-- The restriction of scalars functor `PresheafOfModules R' ⥤ PresheafOfModules R` induced by a morphism of presheaves of rings `R ⟶ R'`. -/ @[simps] noncomputable def restrictScalars (α : R ⟶ R') : PresheafOfModules.{v} R' ⥤ PresheafOfModules.{v} R where - obj M' := (M'.restrictScalarsBundledCore α).toPresheafOfModules - map {M₁' M₂'} φ := - { hom := φ.hom - map_smul := fun X r ↦ φ.map_smul X (α.app _ r) } + obj M' := M'.restrictScalarsObj α + map φ' := + { app := fun X ↦ (ModuleCat.restrictScalars (α.app X)).map (Hom.app φ' X) + naturality := fun {X Y} f ↦ by + ext x + exact naturality_apply φ' f x } instance (α : R ⟶ R') : (restrictScalars.{v} α).Additive where @@ -61,4 +56,9 @@ instance : (restrictScalars (𝟙 R)).Full := inferInstanceAs (𝟭 _).Full instance (α : R ⟶ R') : (restrictScalars α).Faithful where map_injective h := (toPresheaf R').map_injective ((toPresheaf R).congr_map h) +/-- The isomorphism `restrictScalars α ⋙ toPresheaf R ≅ toPresheaf R'` for any +morphism of presheaves of rings `α : R ⟶ R'`. -/ +noncomputable def restrictScalarsCompToPresheaf (α : R ⟶ R') : + restrictScalars.{v} α ⋙ toPresheaf R ≅ toPresheaf R' := Iso.refl _ + end PresheafOfModules diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Colimits.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Colimits.lean index ac5a7ef32dde8..26b9df8025f49 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Colimits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Colimits.lean @@ -32,13 +32,14 @@ variable [∀ {X Y : Cᵒᵖ} (f : X ⟶ Y), PreservesColimit (F ⋙ evaluation of the functors `evaluation R X` for all `X`. -/ def evaluationJointlyReflectsColimits (c : Cocone F) (hc : ∀ (X : Cᵒᵖ), IsColimit ((evaluation R X).mapCocone c)) : IsColimit c where - desc s := Hom.mk'' (fun X => (hc X).desc ((evaluation R X).mapCocone s)) (fun X Y f => by - apply (hc X).hom_ext - intro j - erw [(hc X).fac_assoc ((evaluation R X).mapCocone s) j, ← restrictionApp_naturality_assoc] - rw [← Functor.map_comp] - erw [(hc Y).fac ((evaluation R Y).mapCocone s), restrictionApp_naturality] - rfl) + desc s := + { app := fun X => (hc X).desc ((evaluation R X).mapCocone s) + naturality := fun {X Y} f ↦ (hc X).hom_ext (fun j ↦ by + rw [(hc X).fac_assoc ((evaluation R X).mapCocone s) j] + have h₁ := (c.ι.app j).naturality f + have h₂ := (hc Y).fac ((evaluation R Y).mapCocone s) + dsimp at h₁ h₂ ⊢ + simp only [← reassoc_of% h₁, ← Functor.map_comp, h₂, Hom.naturality]) } fac s j := by ext1 X exact (hc X).fac ((evaluation R X).mapCocone s) j @@ -57,10 +58,10 @@ instance {X Y : Cᵒᵖ} (f : X ⟶ Y) : ⟨_, isColimitOfPreserves (ModuleCat.restrictScalars (R.map f)) (colimit.isColimit (F ⋙ evaluation R Y))⟩ -/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the `BundledCorePresheafOfModules R` which -corresponds to the presheaf of modules which sends `X` to the colimit of `F ⋙ evaluation R X`. -/ +/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the presheaf of modules obtained by +taking a colimit in the category of modules over `R.obj X` for all `X`. -/ @[simps] -noncomputable def colimitBundledCore : BundledCorePresheafOfModules R where +noncomputable def colimitPresheafOfModules : PresheafOfModules R where obj X := colimit (F ⋙ evaluation R X) map {X Y} f := colimMap (whiskerLeft F (restriction R f)) ≫ (preservesColimitIso (ModuleCat.restrictScalars (R.map f)) (F ⋙ evaluation R Y)).inv @@ -69,8 +70,8 @@ noncomputable def colimitBundledCore : BundledCorePresheafOfModules R where rw [ι_colimMap_assoc, whiskerLeft_app, restriction_app] erw [ι_preservesColimitsIso_inv (G := ModuleCat.restrictScalars (R.map (𝟙 X))), ModuleCat.restrictScalarsId'App_inv_naturality] - rw [restrictionApp_id] - rfl) + rw [map_id] + dsimp) map_comp {X Y Z} f g := colimit.hom_ext (fun j => by dsimp rw [ι_colimMap_assoc, whiskerLeft_app, restriction_app, assoc, ι_colimMap_assoc] @@ -78,32 +79,26 @@ noncomputable def colimitBundledCore : BundledCorePresheafOfModules R where ι_preservesColimitsIso_inv_assoc (G := ModuleCat.restrictScalars (R.map f))] rw [← Functor.map_comp_assoc, ι_colimMap_assoc] erw [ι_preservesColimitsIso_inv (G := ModuleCat.restrictScalars (R.map g))] - rw [restrictionApp_comp, ModuleCat.restrictScalarsComp'_inv_app, assoc, assoc, + rw [map_comp, ModuleCat.restrictScalarsComp'_inv_app, assoc, assoc, whiskerLeft_app, whiskerLeft_app, restriction_app, restriction_app] simp only [Functor.map_comp, assoc] rfl) -/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the canonical map -`F.obj j ⟶ (colimitBundledCore F).toPresheafOfModules` for all `j : J`. -/ -noncomputable def colimitCoconeιApp (j : J) : - F.obj j ⟶ (colimitBundledCore F).toPresheafOfModules := - PresheafOfModules.Hom.mk'' (fun X => colimit.ι (F ⋙ evaluation R X) j) (fun X Y f => by - dsimp - erw [colimit.ι_desc_assoc, assoc, ← ι_preservesColimitsIso_inv] - rfl) - -@[reassoc (attr := simp)] -lemma colimitCoconeιApp_naturality {i j : J} (f : i ⟶ j) : - F.map f ≫ colimitCoconeιApp F j = colimitCoconeιApp F i := by - ext1 X - exact colimit.w (F ⋙ evaluation R X) f - /-- The (colimit) cocone for `F : J ⥤ PresheafOfModules.{v} R` that is constructed from the colimit of `F ⋙ evaluation R X` for all `X`. -/ @[simps] noncomputable def colimitCocone : Cocone F where - pt := (colimitBundledCore F).toPresheafOfModules - ι := { app := colimitCoconeιApp F } + pt := colimitPresheafOfModules F + ι := + { app := fun j ↦ + { app := fun X ↦ colimit.ι (F ⋙ evaluation R X) j + naturality := fun {X Y} f ↦ by + dsimp + erw [colimit.ι_desc_assoc, assoc, ← ι_preservesColimitsIso_inv] + rfl } + naturality := fun {X Y} f ↦ by + ext1 X + simpa using colimit.w (F ⋙ evaluation R X) f } /-- The cocone `colimitCocone F` is colimit for any `F : J ⥤ PresheafOfModules.{v} R`. -/ noncomputable def isColimitColimitCocone : IsColimit (colimitCocone F) := diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean index d547a5c07236e..a8c8858cd5bfe 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Limits.lean @@ -33,12 +33,16 @@ variable [∀ X, Small.{v} ((F ⋙ evaluation R X) ⋙ forget _).sections] of the functors `evaluation R X` for all `X`. -/ def evaluationJointlyReflectsLimits (c : Cone F) (hc : ∀ (X : Cᵒᵖ), IsLimit ((evaluation R X).mapCone c)) : IsLimit c where - lift s := Hom.mk'' (fun X => (hc X).lift ((evaluation R X).mapCone s)) (fun X Y f => by - apply (isLimitOfPreserves (ModuleCat.restrictScalars (R.map f)) (hc Y)).hom_ext - intro j - rw [Functor.mapCone_π_app, assoc, assoc, ← Functor.map_comp] - erw [restrictionApp_naturality, IsLimit.fac, restrictionApp_naturality, IsLimit.fac_assoc] - rfl) + lift s := + { app := fun X => (hc X).lift ((evaluation R X).mapCone s) + naturality := fun {X Y} f ↦ by + apply (isLimitOfPreserves (ModuleCat.restrictScalars (R.map f)) (hc Y)).hom_ext + intro j + have h₁ := (c.π.app j).naturality f + have h₂ := (hc X).fac ((evaluation R X).mapCone s) j + rw [Functor.mapCone_π_app, assoc, assoc, ← Functor.map_comp, IsLimit.fac] + dsimp at h₁ h₂ ⊢ + rw [h₁, reassoc_of% h₂, Hom.naturality] } fac s j := by ext1 X exact (hc X).fac ((evaluation R X).mapCone s) j @@ -47,19 +51,17 @@ def evaluationJointlyReflectsLimits (c : Cone F) apply (hc X).uniq ((evaluation R X).mapCone s) intro j dsimp - rw [← hm] - rfl + rw [← hm, comp_app] instance {X Y : Cᵒᵖ} (f : X ⟶ Y) : HasLimit (F ⋙ evaluation R Y ⋙ ModuleCat.restrictScalars (R.map f)) := by change HasLimit ((F ⋙ evaluation R Y) ⋙ ModuleCat.restrictScalars (R.map f)) infer_instance -set_option backward.isDefEq.lazyWhnfCore false in -- See https://github.com/leanprover-community/mathlib4/issues/12534 -/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the `BundledCorePresheafOfModules R` which -corresponds to the presheaf of modules which sends `X` to the limit of `F ⋙ evaluation R X`. -/ +/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the presheaf of modules obtained by +taking a limit in the category of modules over `R.obj X` for all `X`. -/ @[simps] -noncomputable def limitBundledCore : BundledCorePresheafOfModules R where +noncomputable def limitPresheafOfModules : PresheafOfModules R where obj X := limit (F ⋙ evaluation R X) map {X Y} f := limMap (whiskerLeft F (restriction R f)) ≫ (preservesLimitIso (ModuleCat.restrictScalars (R.map f)) (F ⋙ evaluation R Y)).inv @@ -72,7 +74,8 @@ noncomputable def limitBundledCore : BundledCorePresheafOfModules R where simp only [limMap_π, Functor.comp_obj, evaluation_obj, whiskerLeft_app, restriction_app, assoc] erw [preservesLimitsIso_hom_π] - rw [← ModuleCat.restrictScalarsId'App_inv_naturality, restrictionApp_id] + rw [← ModuleCat.restrictScalarsId'App_inv_naturality, map_id, + ModuleCat.restrictScalarsId'_inv_app] dsimp map_comp {X Y Z} f g := by dsimp @@ -81,8 +84,9 @@ noncomputable def limitBundledCore : BundledCorePresheafOfModules R where apply limit.hom_ext intro j simp only [Functor.comp_obj, evaluation_obj, limMap_π, whiskerLeft_app, restriction_app, - Functor.map_comp, assoc, restrictionApp_comp] - erw [preservesLimitsIso_hom_π, ← ModuleCat.restrictScalarsComp'App_inv_naturality] + map_comp, ModuleCat.restrictScalarsComp'_inv_app, Functor.map_comp, assoc] + erw [preservesLimitsIso_hom_π] + rw [← ModuleCat.restrictScalarsComp'App_inv_naturality] dsimp rw [← Functor.map_comp_assoc, ← Functor.map_comp_assoc, assoc, preservesLimitsIso_inv_π] @@ -92,27 +96,21 @@ noncomputable def limitBundledCore : BundledCorePresheafOfModules R where erw [limMap_π_assoc] dsimp -/-- Given `F : J ⥤ PresheafOfModules.{v} R`, this is the canonical map -`(limitBundledCore F).toPresheafOfModules ⟶ F.obj j` for all `j : J`. -/ -noncomputable def limitConeπApp (j : J) : - (limitBundledCore F).toPresheafOfModules ⟶ F.obj j := - PresheafOfModules.Hom.mk'' (fun X => limit.π (F ⋙ evaluation R X) j) (fun X Y f => by - dsimp - simp only [assoc, preservesLimitsIso_inv_π] - apply limMap_π) - -@[reassoc (attr := simp)] -lemma limitConeπApp_naturality {i j : J} (f : i ⟶ j) : - limitConeπApp F i ≫ F.map f = limitConeπApp F j := by - ext1 X - exact limit.w (F ⋙ evaluation R X) f - -/-- The (limit) cone for `F : J ⥤ PresheafOfModules.{v} R` that is constructed for the limit +/-- The (limit) cone for `F : J ⥤ PresheafOfModules.{v} R` that is constructed from the limit of `F ⋙ evaluation R X` for all `X`. -/ @[simps] noncomputable def limitCone : Cone F where - pt := (limitBundledCore F).toPresheafOfModules - π := { app := limitConeπApp F } + pt := limitPresheafOfModules F + π := + { app := fun j ↦ + { app := fun X ↦ limit.π (F ⋙ evaluation R X) j + naturality := fun {X Y} f ↦ by + dsimp + simp only [assoc, preservesLimitsIso_inv_π] + apply limMap_π } + naturality := fun {j j'} f ↦ by + ext1 X + simpa using (limit.w (F ⋙ evaluation R X) f).symm } /-- The cone `limitCone F` is limit for any `F : J ⥤ PresheafOfModules.{v} R`. -/ noncomputable def isLimitLimitCone : IsLimit (limitCone F) := diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean index dd5f7c91a4e3b..ae8b9e272a34a 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Pushforward.lean @@ -26,10 +26,6 @@ variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D] namespace PresheafOfModules -instance {R : Dᵒᵖ ⥤ RingCat.{u}} (P : PresheafOfModules.{v} R) (F : C ⥤ D) (X : Cᵒᵖ) : - Module ((F.op ⋙ R).obj X) ((F.op ⋙ P.presheaf).obj X) := - inferInstanceAs (Module (R.obj (F.op.obj X)) (P.presheaf.obj (F.op.obj X))) - variable (F : C ⥤ D) /-- The pushforward functor on presheaves of modules for a functor `F : C ⥤ D` and @@ -37,12 +33,16 @@ variable (F : C ⥤ D) by the precomposition with `F.op`. -/ def pushforward₀ (R : Dᵒᵖ ⥤ RingCat.{u}) : PresheafOfModules.{v} R ⥤ PresheafOfModules.{v} (F.op ⋙ R) where - obj P := - { presheaf := F.op ⋙ P.presheaf - map_smul := by intros; apply P.map_smul } - map {P Q} φ := - { hom := whiskerLeft F.op φ.hom - map_smul := by intros; apply φ.map_smul } + obj M := + { obj := fun X ↦ ModuleCat.of _ (M.obj (F.op.obj X)) + map := fun {X Y} f ↦ M.map (F.op.map f) + map_id := fun X ↦ by + ext x + exact (M.congr_map_apply (F.op.map_id X) x).trans (by simp) + map_comp := fun f g ↦ by + ext x + exact (M.congr_map_apply (F.op.map_comp f g) x).trans (by simp) } + map {M₁ M₂} φ := { app := fun X ↦ φ.app _ } /-- The pushforward of presheaves of modules commutes with the forgetful functor to presheaves of abelian groups. -/ @@ -53,8 +53,10 @@ def pushforward₀CompToPresheaf (R : Dᵒᵖ ⥤ RingCat.{u}) : variable {F} variable {R : Dᵒᵖ ⥤ RingCat.{u}} {S : Cᵒᵖ ⥤ RingCat.{u}} (φ : S ⟶ F.op ⋙ R) +attribute [local simp] pushforward₀ in /-- The pushforward functor `PresheafOfModules R ⥤ PresheafOfModules S` induced by a morphism of presheaves of rings `S ⟶ F.op ⋙ R`. -/ +@[simps! obj_obj] noncomputable def pushforward : PresheafOfModules.{v} R ⥤ PresheafOfModules.{v} S := pushforward₀ F R ⋙ restrictScalars φ @@ -64,21 +66,22 @@ noncomputable def pushforwardCompToPresheaf : pushforward.{v} φ ⋙ toPresheaf _ ≅ toPresheaf _ ⋙ (whiskeringLeft _ _ _).obj F.op := Iso.refl _ --- unfortunately, `pushforward_obj_obj` and `pushforward_obj_map` cannot be both simp lemmas -lemma pushforward_obj_obj (M : PresheafOfModules.{v} R) (X : Cᵒᵖ) : - ((pushforward φ).obj M).obj X = - (ModuleCat.restrictScalars (φ.app X)).obj (M.obj (Opposite.op (F.obj X.unop))) := rfl - @[simp] lemma pushforward_obj_map_apply (M : PresheafOfModules.{v} R) {X Y : Cᵒᵖ} (f : X ⟶ Y) (m : (ModuleCat.restrictScalars (φ.app X)).obj (M.obj (Opposite.op (F.obj X.unop)))) : - ((pushforward φ).obj M).map f m = M.map (F.map f.unop).op m := by - rfl + DFunLike.coe + (α := (ModuleCat.restrictScalars (φ.app X)).obj (M.obj (Opposite.op (F.obj X.unop)))) + (β := fun _ ↦ (ModuleCat.restrictScalars (φ.app Y)).obj + (M.obj (Opposite.op (F.obj Y.unop)))) (((pushforward φ).obj M).map f) m = + M.map (F.map f.unop).op m := rfl @[simp] lemma pushforward_map_app_apply {M N : PresheafOfModules.{v} R} (α : M ⟶ N) (X : Cᵒᵖ) (m : (ModuleCat.restrictScalars (φ.app X)).obj (M.obj (Opposite.op (F.obj X.unop)))) : - ((pushforward φ).map α).app X m = α.app (Opposite.op (F.obj X.unop)) m := by - rfl + DFunLike.coe + (α := (ModuleCat.restrictScalars (φ.app X)).obj (M.obj (Opposite.op (F.obj X.unop)))) + (β := fun _ ↦ (ModuleCat.restrictScalars (φ.app X)).obj + (N.obj (Opposite.op (F.obj X.unop)))) + (((pushforward φ).map α).app X) m = α.app (Opposite.op (F.obj X.unop)) m := rfl end PresheafOfModules diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafification.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafification.lean index 3d447a8010649..db55107701398 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafification.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafification.lean @@ -43,15 +43,19 @@ the associated sheaf of modules functor `PresheafOfModules.{v} R₀ ⥤ SheafOfM @[simps! (config := .lemmasOnly) map] noncomputable def sheafification : PresheafOfModules.{v} R₀ ⥤ SheafOfModules.{v} R where obj M₀ := sheafify α (CategoryTheory.toSheafify J M₀.presheaf) - map f := sheafifyMap _ _ _ f ((presheafToSheaf J AddCommGrp).map f.hom) (by simp) + map f := sheafifyMap _ _ _ f + ((toPresheaf R₀ ⋙ presheafToSheaf J AddCommGrp).map f) + (by apply toSheafify_naturality) map_id M₀ := by ext1 apply (toPresheaf _).map_injective - simp [toPresheaf, sheafify] + simp + rfl map_comp _ _ := by ext1 apply (toPresheaf _).map_injective - simp [toPresheaf, sheafify] + simp + rfl /-- The sheafification of presheaves of modules commutes with the functor which forgets the module structures. -/ @@ -75,19 +79,19 @@ noncomputable def sheafificationHomEquiv (P ⟶ (restrictScalars α).obj ((SheafOfModules.forget _).obj F)) := by apply sheafifyHomEquiv -lemma sheafificationHomEquiv_hom' +lemma toPresheaf_map_sheafificationHomEquiv_def {P : PresheafOfModules.{v} R₀} {F : SheafOfModules.{v} R} (f : (sheafification α).obj P ⟶ F) : - (sheafificationHomEquiv α f).hom = - CategoryTheory.toSheafify J P.presheaf ≫ f.val.hom := rfl + (toPresheaf R₀).map (sheafificationHomEquiv α f) = + CategoryTheory.toSheafify J P.presheaf ≫ (toPresheaf R.val).map f.val := rfl -lemma sheafificationHomEquiv_hom +lemma toPresheaf_map_sheafificationHomEquiv {P : PresheafOfModules.{v} R₀} {F : SheafOfModules.{v} R} (f : (sheafification α).obj P ⟶ F) : - (sheafificationHomEquiv α f).hom = + (toPresheaf R₀).map (sheafificationHomEquiv α f) = (sheafificationAdjunction J AddCommGrp).homEquiv P.presheaf ((SheafOfModules.toSheaf _).obj F) ((SheafOfModules.toSheaf _).map f) := by - rw [sheafificationHomEquiv_hom', Adjunction.homEquiv_unit] + rw [toPresheaf_map_sheafificationHomEquiv_def, Adjunction.homEquiv_unit] dsimp lemma toSheaf_map_sheafificationHomEquiv_symm @@ -95,7 +99,7 @@ lemma toSheaf_map_sheafificationHomEquiv_symm (g : P ⟶ (restrictScalars α).obj ((SheafOfModules.forget _).obj F)) : (SheafOfModules.toSheaf _).map ((sheafificationHomEquiv α).symm g) = (((sheafificationAdjunction J AddCommGrp).homEquiv - P.presheaf ((SheafOfModules.toSheaf R).obj F)).symm g.hom) := by + P.presheaf ((SheafOfModules.toSheaf R).obj F)).symm ((toPresheaf R₀).map g)) := by obtain ⟨f, rfl⟩ := (sheafificationHomEquiv α).surjective g apply ((sheafificationAdjunction J AddCommGrp).homEquiv _ _).injective rw [Equiv.apply_symm_apply, Adjunction.homEquiv_unit, Equiv.symm_apply_apply] @@ -112,23 +116,22 @@ noncomputable def sheafificationAdjunction : apply (SheafOfModules.toSheaf _).map_injective rw [Functor.map_comp] erw [toSheaf_map_sheafificationHomEquiv_symm, - toSheaf_map_sheafificationHomEquiv_symm] - apply Adjunction.homEquiv_naturality_left_symm + toSheaf_map_sheafificationHomEquiv_symm α g] + rw [Functor.map_comp] + apply (CategoryTheory.sheafificationAdjunction J + AddCommGrp.{v}).homEquiv_naturality_left_symm homEquiv_naturality_right := fun {P₀ M N} f g ↦ by apply (toPresheaf _).map_injective - dsimp [toPresheaf] - erw [sheafificationHomEquiv_hom, sheafificationHomEquiv_hom] - rw [Functor.map_comp] - apply Adjunction.homEquiv_naturality_right } + erw [toPresheaf_map_sheafificationHomEquiv] } lemma sheaififcationAdjunction_homEquiv_apply {P : PresheafOfModules.{v} R₀} {F : SheafOfModules.{v} R} (f : (sheafification α).obj P ⟶ F) : (sheafificationAdjunction α).homEquiv P F f = sheafificationHomEquiv α f := rfl @[simp] -lemma sheafificationAdjunction_unit_app_hom (M₀ : PresheafOfModules.{v} R₀) : - ((sheafificationAdjunction α).unit.app M₀).hom = CategoryTheory.toSheafify J M₀.presheaf := by - rfl +lemma toPresheaf_map_sheafificationAdjunction_unit_app (M₀ : PresheafOfModules.{v} R₀) : + (toPresheaf _).map ((sheafificationAdjunction α).unit.app M₀) = + CategoryTheory.toSheafify J M₀.presheaf := rfl instance : (sheafification.{v} α).IsLeftAdjoint := (sheafificationAdjunction α).isLeftAdjoint diff --git a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean index 0d10d6d1547c9..fb4312736f67f 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Presheaf/Sheafify.lean @@ -16,7 +16,7 @@ of the underlying presheaf of abelian groups of `M₀`, i.e. we have a locally b map `φ : M₀.presheaf ⟶ A.val`, then we endow `A` with the structure of a sheaf of modules over `R`: this is `PresheafOfModules.sheafify α φ`. -In many application, the morphism `α` shall be the identity, but this more +In many applications, the morphism `α` shall be the identity, but this more general construction allows the sheafification of both the presheaf of rings and the presheaf of modules. @@ -42,7 +42,7 @@ variable {R : Cᵒᵖ ⥤ RingCat.{u}} {M : PresheafOfModules.{v} R} {X : C} {P /-- The scalar multiplication of family of elements of a presheaf of modules `M` over `R` by a family of elements of `R`. -/ def smul : FamilyOfElements (M.presheaf ⋙ forget _) P := fun Y f hf => - HSMul.hSMul (α := R.obj (Opposite.op Y)) (β := M.presheaf.obj (Opposite.op Y)) (r f hf) (m f hf) + HSMul.hSMul (α := R.obj (Opposite.op Y)) (β := M.obj (Opposite.op Y)) (r f hf) (m f hf) end smul @@ -57,7 +57,7 @@ include hA lemma _root_.PresheafOfModules.Sheafify.app_eq_of_isLocallyInjective {Y : C} (r₀ r₀' : R₀.obj (Opposite.op Y)) - (m₀ m₀' : M₀.presheaf.obj (Opposite.op Y)) + (m₀ m₀' : M₀.obj (Opposite.op Y)) (hr₀ : α.app _ r₀ = α.app _ r₀') (hm₀ : φ.app _ m₀ = φ.app _ m₀') : φ.app _ (r₀ • m₀) = φ.app _ (r₀' • m₀') := by @@ -72,16 +72,15 @@ lemma _root_.PresheafOfModules.Sheafify.app_eq_of_isLocallyInjective lemma isCompatible_map_smul_aux {Y Z : C} (f : Y ⟶ X) (g : Z ⟶ Y) (r₀ : R₀.obj (Opposite.op Y)) (r₀' : R₀.obj (Opposite.op Z)) - (m₀ : M₀.presheaf.obj (Opposite.op Y)) (m₀' : M₀.presheaf.obj (Opposite.op Z)) + (m₀ : M₀.obj (Opposite.op Y)) (m₀' : M₀.obj (Opposite.op Z)) (hr₀ : α.app _ r₀ = R.map f.op r) (hr₀' : α.app _ r₀' = R.map (f.op ≫ g.op) r) (hm₀ : φ.app _ m₀ = A.map f.op m) (hm₀' : φ.app _ m₀' = A.map (f.op ≫ g.op) m) : - φ.app _ (M₀.presheaf.map g.op (r₀ • m₀)) = φ.app _ (r₀' • m₀') := by + φ.app _ (M₀.map g.op (r₀ • m₀)) = φ.app _ (r₀' • m₀') := by rw [← PresheafOfModules.Sheafify.app_eq_of_isLocallyInjective α φ hA (R₀.map g.op r₀) r₀' - (M₀.presheaf.map g.op m₀) m₀', M₀.map_smul] + (M₀.map g.op m₀) m₀', M₀.map_smul] · rw [hr₀', R.map_comp, comp_apply, ← hr₀, NatTrans.naturality_apply] · rw [hm₀', A.map_comp, AddCommGrp.coe_comp, Function.comp_apply, ← hm₀] erw [NatTrans.naturality_apply] - rfl variable (hr₀ : (r₀.map (whiskerRight α (forget _))).IsAmalgamation r) (hm₀ : (m₀.map (whiskerRight φ (forget _))).IsAmalgamation m) @@ -105,7 +104,6 @@ lemma isCompatible_map_smul : ((r₀.smul m₀).map (whiskerRight φ (forget _)) have hb₀ : (φ.app (Opposite.op Z)) b₀ = (A.map (f₁.op ≫ g₁.op)) m := by dsimp [b₀] erw [NatTrans.naturality_apply, hb₁, Functor.map_comp, comp_apply] - rfl have ha₀' : (α.app (Opposite.op Z)) a₀ = (R.map (f₂.op ≫ g₂.op)) r := by rw [ha₀, ← op_comp, fac, op_comp] have hb₀' : (φ.app (Opposite.op Z)) b₀ = (A.map (f₂.op ≫ g₂.op)) m := by @@ -222,9 +220,7 @@ lemma map_smul_eq {Y : Cᵒᵖ} (f : X ⟶ Y) (r₀ : R₀.obj Y) (hr₀ : α.ap protected lemma one_smul : smul α φ 1 m = m := by apply A.isSeparated _ _ (Presheaf.imageSieve_mem J φ m) rintro Y f ⟨m₀, hm₀⟩ - rw [← hm₀] - erw [map_smul_eq α φ 1 m f.op 1 (by simp) m₀ hm₀, one_smul] - rfl + rw [← hm₀, map_smul_eq α φ 1 m f.op 1 (by simp) m₀ hm₀, one_smul] protected lemma zero_smul : smul α φ 0 m = 0 := by apply A.isSeparated _ _ (Presheaf.imageSieve_mem J φ m) @@ -244,11 +240,11 @@ protected lemma smul_add : smul α φ r (m + m') = smul α φ r m + smul α φ r refine J.intersection_covering (J.intersection_covering ?_ ?_) ?_ all_goals apply Presheaf.imageSieve_mem apply A.isSeparated _ _ hS - rintro Y f ⟨⟨⟨r₀, hr₀⟩, ⟨m₀ : M₀.presheaf.obj _, hm₀⟩⟩, ⟨m₀' : M₀.presheaf.obj _, hm₀'⟩⟩ + rintro Y f ⟨⟨⟨r₀, hr₀⟩, ⟨m₀ : M₀.obj _, hm₀⟩⟩, ⟨m₀' : M₀.obj _, hm₀'⟩⟩ erw [(A.val.map f.op).map_add, map_smul_eq α φ r m f.op r₀ hr₀ m₀ hm₀, map_smul_eq α φ r m' f.op r₀ hr₀ m₀' hm₀', map_smul_eq α φ r (m + m') f.op r₀ hr₀ (m₀ + m₀') - (by erw [map_add, map_add, hm₀, hm₀']; rfl), + (by rw [map_add, map_add, hm₀, hm₀']), smul_add, map_add] protected lemma add_smul : smul α φ (r + r') m = smul α φ r m + smul α φ r' m := by @@ -269,7 +265,7 @@ protected lemma mul_smul : smul α φ (r * r') m = smul α φ r (smul α φ r' m refine J.intersection_covering (J.intersection_covering ?_ ?_) ?_ all_goals apply Presheaf.imageSieve_mem apply A.isSeparated _ _ hS - rintro Y f ⟨⟨⟨r₀ : R₀.obj _, hr₀⟩, ⟨r₀' : R₀.obj _, hr₀'⟩⟩, ⟨m₀ : M₀.presheaf.obj _, hm₀⟩⟩ + rintro Y f ⟨⟨⟨r₀ : R₀.obj _, hr₀⟩, ⟨r₀' : R₀.obj _, hr₀'⟩⟩, ⟨m₀ : M₀.obj _, hm₀⟩⟩ erw [map_smul_eq α φ (r * r') m f.op (r₀ * r₀') (by rw [map_mul, map_mul, hr₀, hr₀']) m₀ hm₀, mul_smul, map_smul_eq α φ r (smul α φ r' m) f.op r₀ hr₀ (r₀' • m₀) @@ -298,7 +294,7 @@ lemma map_smul : rintro Y f ⟨⟨r₀, hr₀⟩, ⟨m₀, hm₀⟩⟩ erw [← comp_apply, ← Functor.map_comp, map_smul_eq α φ r m (π ≫ f.op) r₀ (by rw [hr₀, Functor.map_comp, comp_apply]) m₀ - (by erw [hm₀, Functor.map_comp, comp_apply]; rfl), + (by rw [hm₀, Functor.map_comp, comp_apply]), map_smul_eq α φ (R.val.map π r) (A.val.map π m) f.op r₀ hr₀ m₀ hm₀] end Sheafify @@ -309,25 +305,28 @@ sheaf of abelian groups of a presheaf of modules `M₀` over `R₀`, this is the sheaf of modules over `R` which is obtained by endowing the sections of `A.val` with a scalar multiplication. -/ noncomputable def sheafify : SheafOfModules.{v} R where - val := - { presheaf := A.val - module := Sheafify.module α φ - map_smul := fun _ _ _ => by apply Sheafify.map_smul } + val := letI := Sheafify.module α φ; ofPresheaf A.val (Sheafify.map_smul _ _) isSheaf := A.cond /-- The canonical morphism from a presheaf of modules to its associated sheaf. -/ -@[simps] -def toSheafify : M₀ ⟶ (restrictScalars α).obj (sheafify α φ).val where - hom := φ - map_smul X r₀ m₀ := by +def toSheafify : M₀ ⟶ (restrictScalars α).obj (sheafify α φ).val := + homMk φ (fun X r₀ m₀ ↦ by simpa using (Sheafify.map_smul_eq α φ (α.app _ r₀) (φ.app _ m₀) (𝟙 _) - r₀ (by aesop) m₀ (by simp)).symm + r₀ (by aesop) m₀ (by simp)).symm) + +@[simp] +lemma toSheafify_app_apply (X : Cᵒᵖ) (x : M₀.obj X) : + DFunLike.coe (α := M₀.obj X) (β := fun _ ↦ A.val.obj X) + ((toSheafify α φ).app X) x = φ.app X x := rfl + +@[simp] +lemma toPresheaf_map_toSheafify : (toPresheaf R₀).map (toSheafify α φ) = φ := rfl -instance : Presheaf.IsLocallyInjective J (toSheafify α φ).hom := by - dsimp; infer_instance +instance : IsLocallyInjective J (toSheafify α φ) := by + dsimp [IsLocallyInjective]; infer_instance -instance : Presheaf.IsLocallySurjective J (toSheafify α φ).hom := by - dsimp; infer_instance +instance : IsLocallySurjective J (toSheafify α φ) := by + dsimp [IsLocallySurjective]; infer_instance variable [J.WEqualsLocallyBijective AddCommGrp.{v}] @@ -341,10 +340,10 @@ noncomputable def sheafifyHomEquiv' {F : PresheafOfModules.{v} R.val} (homEquivOfIsLocallyBijective (f := toSheafify α φ) (N := (restrictScalars α).obj F) hF) -lemma comp_sheafifyHomEquiv'_symm_hom {F : PresheafOfModules.{v} R.val} +lemma comp_toPresheaf_map_sheafifyHomEquiv'_symm_hom {F : PresheafOfModules.{v} R.val} (hF : Presheaf.IsSheaf J F.presheaf) (f : M₀ ⟶ (restrictScalars α).obj F) : - φ ≫ ((sheafifyHomEquiv' α φ hF).symm f).hom = f.hom := - congr_arg Hom.hom ((sheafifyHomEquiv' α φ hF).apply_symm_apply f) + φ ≫ (toPresheaf R.val).map ((sheafifyHomEquiv' α φ hF).symm f) = (toPresheaf R₀).map f := + (toPresheaf _).congr_map ((sheafifyHomEquiv' α φ hF).apply_symm_apply f) /-- The bijection `(sheafify α φ ⟶ F) ≃ (M₀ ⟶ (restrictScalars α).obj ((SheafOfModules.forget _).obj F))` @@ -367,17 +366,15 @@ variable {M₀' : PresheafOfModules.{v} R₀} {A' : Sheaf J AddCommGrp.{v}} induced by morphisms `τ₀ : M₀ ⟶ M₀'` and `τ : A ⟶ A'` which satisfy `τ₀.hom ≫ φ' = φ ≫ τ.val`. -/ @[simps] -def sheafifyMap (fac : τ₀.hom ≫ φ' = φ ≫ τ.val) : sheafify α φ ⟶ sheafify α φ' where - val := - { hom := τ.val - map_smul := by - let f := (sheafifyHomEquiv' α φ (by exact A'.cond)).symm (τ₀ ≫ toSheafify α φ') - have eq : τ.val = f.hom := ((J.W_of_isLocallyBijective φ).homEquiv _ A'.cond).injective - (by - dsimp [f] - erw [comp_sheafifyHomEquiv'_symm_hom] - simp only [← fac, toSheafify_hom, Hom.comp_hom]) - convert f.map_smul } +def sheafifyMap (fac : (toPresheaf R₀).map τ₀ ≫ φ' = φ ≫ τ.val) : + sheafify α φ ⟶ sheafify α φ' where + val := homMk τ.val (fun X r m ↦ by + let f := (sheafifyHomEquiv' α φ (by exact A'.cond)).symm (τ₀ ≫ toSheafify α φ') + suffices τ.val = (toPresheaf _).map f by simpa only [this] using (f.app X).map_smul r m + apply ((J.W_of_isLocallyBijective φ).homEquiv _ A'.cond).injective + dsimp [f] + erw [comp_toPresheaf_map_sheafifyHomEquiv'_symm_hom] + rw [← fac, Functor.map_comp, toPresheaf_map_toSheafify]) end diff --git a/Mathlib/Algebra/Category/ModuleCat/Sheaf.lean b/Mathlib/Algebra/Category/ModuleCat/Sheaf.lean index fb6b24bc7f604..3a23ba4b4c02e 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Sheaf.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Sheaf.lean @@ -15,12 +15,6 @@ import Mathlib.CategoryTheory.Sites.Whiskering In this file, we define the category `SheafOfModules R` when `R : Sheaf J RingCat` is a sheaf of rings on a category `C` equipped with a Grothendieck topology `J`. -## TODO -* construct the associated sheaf: more precisely, given a morphism of `α : P ⟶ R.val` -where `P` is a presheaf of rings and `R` a sheaf of rings such that `α` identifies -`R` to the associated sheaf of `P`, then construct a sheafification functor -`PresheafOfModules P ⥤ SheafOfModules R`. - -/ universe v v₁ u₁ u w @@ -91,7 +85,7 @@ def evaluation (X : Cᵒᵖ) : SheafOfModules.{v} R ⥤ ModuleCat.{v} (R.val.obj @[simps] def toSheaf : SheafOfModules.{v} R ⥤ Sheaf J AddCommGrp.{v} where obj M := ⟨_, M.isSheaf⟩ - map f := { val := f.val.hom } + map f := { val := (forget R ⋙ PresheafOfModules.toPresheaf R.val).map f } /-- The forgetful functor from sheaves of modules over sheaf of ring `R` to sheaves of `R(X)`-module @@ -185,36 +179,55 @@ end SheafOfModules namespace PresheafOfModules -variable {R : Cᵒᵖ ⥤ RingCat.{u}} {M₁ M₂ : PresheafOfModules.{v} R} - (f : M₁ ⟶ M₂) {N : PresheafOfModules.{v} R} - (hN : Presheaf.IsSheaf J N.presheaf) - [J.WEqualsLocallyBijective AddCommGrp.{v}] - [Presheaf.IsLocallySurjective J f.hom] - [Presheaf.IsLocallyInjective J f.hom] +variable (J) +variable {R : Cᵒᵖ ⥤ RingCat.{u}} {M₁ M₂ : PresheafOfModules.{v} R} (f : M₁ ⟶ M₂) + +/-- A morphism of presheaves of modules is locally surjective +if the underlying morphism of presheaves of abelian groups is. -/ +abbrev IsLocallySurjective : Prop := + Presheaf.IsLocallySurjective J ((PresheafOfModules.toPresheaf R).map f) + +/-- A morphism of presheaves of modules is locally injective +if the underlying morphism of presheaves of abelian groups is. -/ +abbrev IsLocallyInjective : Prop := + Presheaf.IsLocallyInjective J ((PresheafOfModules.toPresheaf R).map f) + +variable {N : PresheafOfModules.{v} R} (hN : Presheaf.IsSheaf J N.presheaf) + [J.WEqualsLocallyBijective AddCommGrp.{v}] + [IsLocallySurjective J f] [IsLocallyInjective J f] + +variable {J} /-- The bijection `(M₂ ⟶ N) ≃ (M₁ ⟶ N)` induced by a locally bijective morphism `f : M₁ ⟶ M₂` of presheaves of modules, when `N` is a sheaf. -/ @[simps] noncomputable def homEquivOfIsLocallyBijective : (M₂ ⟶ N) ≃ (M₁ ⟶ N) where toFun φ := f ≫ φ - invFun ψ := - { hom := ((J.W_of_isLocallyBijective f.hom).homEquiv _ hN).symm ψ.hom - map_smul := by - obtain ⟨φ, hφ⟩ := ((J.W_of_isLocallyBijective f.hom).homEquiv _ hN).surjective ψ.hom + invFun ψ := homMk (((J.W_of_isLocallyBijective + ((PresheafOfModules.toPresheaf R).map f)).homEquiv _ hN).symm + ((PresheafOfModules.toPresheaf R).map ψ)) (by + obtain ⟨φ, hφ⟩ := ((J.W_of_isLocallyBijective + ((PresheafOfModules.toPresheaf R).map f)).homEquiv _ hN).surjective + ((PresheafOfModules.toPresheaf R).map ψ) simp only [← hφ, Equiv.symm_apply_apply] - dsimp at hφ + replace hφ : ∀ (Z : Cᵒᵖ) (x : M₁.obj Z), φ.app Z (f.app Z x) = ψ.app Z x := + fun Z x ↦ congr_fun ((forget _).congr_map (congr_app hφ Z)) x intro X r y - apply hN.isSeparated _ _ (Presheaf.imageSieve_mem J f.hom y) - rintro Y p ⟨x, hx⟩ - have eq := ψ.map_smul _ (R.map p.op r) x - simp only [← hφ] at eq - dsimp at eq - erw [← NatTrans.naturality_apply φ p.op (r • y), N.map_smul, M₂.map_smul, - ← NatTrans.naturality_apply φ p.op y, ← hx, ← eq, f.map_smul] - rfl } + apply hN.isSeparated _ _ + (Presheaf.imageSieve_mem J ((toPresheaf R).map f) y) + rintro Y p ⟨x : M₁.obj _, hx : f.app _ x = M₂.map p.op y⟩ + have hφ' : ∀ (z : M₂.obj X), φ.app _ (M₂.map p.op z) = + N.map p.op (φ.app _ z) := congr_fun ((forget _).congr_map (φ.naturality p.op)) + change N.map p.op (φ.app X (r • y)) = N.map p.op (r • φ.app X y) + rw [← hφ', M₂.map_smul, ← hx, ← (f.app _).map_smul, hφ, (ψ.app _).map_smul, + ← hφ, hx, N.map_smul, hφ']) left_inv φ := (toPresheaf _).map_injective - (((J.W_of_isLocallyBijective f.hom).homEquiv _ hN).left_inv φ.hom) + (((J.W_of_isLocallyBijective + ((PresheafOfModules.toPresheaf R).map f)).homEquiv _ hN).left_inv + ((PresheafOfModules.toPresheaf R).map φ)) right_inv ψ := (toPresheaf _).map_injective - (((J.W_of_isLocallyBijective f.hom).homEquiv _ hN).right_inv ψ.hom) + (((J.W_of_isLocallyBijective + ((PresheafOfModules.toPresheaf R).map f)).homEquiv _ hN).right_inv + ((PresheafOfModules.toPresheaf R).map ψ)) end PresheafOfModules diff --git a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean index 906a646c6048c..53503eb352661 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Sheaf/ChangeOfRings.lean @@ -45,22 +45,23 @@ namespace PresheafOfModules variable {R R' : Cᵒᵖ ⥤ RingCat.{u}} (α : R ⟶ R') {M₁ M₂ : PresheafOfModules.{v} R'} -/-- The functor `PresheafOfModules.restrictScalars α` induces bijection on +/-- The functor `PresheafOfModules.restrictScalars α` induces bijections on morphisms if `α` is locally surjective and the target presheaf is a sheaf. -/ noncomputable def restrictHomEquivOfIsLocallySurjective (hM₂ : Presheaf.IsSheaf J M₂.presheaf) [Presheaf.IsLocallySurjective J α] : (M₁ ⟶ M₂) ≃ ((restrictScalars α).obj M₁ ⟶ (restrictScalars α).obj M₂) where toFun f := (restrictScalars α).map f - invFun g := - { hom := g.hom - map_smul := fun X r' m => by - apply hM₂.isSeparated _ _ (Presheaf.imageSieve_mem J α r') - rintro Y p ⟨r : R.obj _, hr⟩ - erw [M₂.map_smul, ← NatTrans.naturality_apply g.hom p.op m, - ← hr, ← g.map_smul _ r (M₁.presheaf.map p.op m), - ← NatTrans.naturality_apply g.hom p.op (r' • m), - M₁.map_smul p.op r' m, ← hr] - rfl } + invFun g := homMk ((toPresheaf R).map g) (fun X r' m ↦ by + apply hM₂.isSeparated _ _ (Presheaf.imageSieve_mem J α r') + rintro Y p ⟨r : R.obj _, hr⟩ + have hg : ∀ (z : M₁.obj X), g.app _ (M₁.map p.op z) = M₂.map p.op (g.app X z) := + fun z ↦ congr_fun ((forget _).congr_map (g.naturality p.op)) z + change M₂.map p.op (g.app X (r' • m)) = M₂.map p.op (r' • show M₂.obj X from g.app X m) + dsimp at hg ⊢ + rw [← hg, M₂.map_smul, ← hg, ← hr] + erw [← (g.app _).map_smul] + rw [M₁.map_smul, ← hr] + rfl) left_inv _ := rfl right_inv _ := rfl diff --git a/Mathlib/Algebra/Category/ModuleCat/Simple.lean b/Mathlib/Algebra/Category/ModuleCat/Simple.lean index dcccbac0230b4..a36bd8151ab84 100644 --- a/Mathlib/Algebra/Category/ModuleCat/Simple.lean +++ b/Mathlib/Algebra/Category/ModuleCat/Simple.lean @@ -34,7 +34,7 @@ instance simple_of_isSimpleModule [IsSimpleModule R M] : Simple (of R M) := instance isSimpleModule_of_simple (M : ModuleCat R) [Simple M] : IsSimpleModule R M := simple_iff_isSimpleModule.mp (Simple.of_iso (ofSelfIso M)) -open FiniteDimensional +open Module attribute [local instance] moduleOfAlgebraModule isScalarTower_of_algebra_moduleCat diff --git a/Mathlib/Algebra/Category/Ring/Basic.lean b/Mathlib/Algebra/Category/Ring/Basic.lean index 59221b72fb4e2..4e1a2a7998aae 100644 --- a/Mathlib/Algebra/Category/Ring/Basic.lean +++ b/Mathlib/Algebra/Category/Ring/Basic.lean @@ -47,10 +47,6 @@ instance bundledHom : BundledHom AssocRingHom where --deriving instance LargeCategory, ConcreteCategory for SemiRingCat -- see https://github.com/leanprover-community/mathlib4/issues/5020 --- Porting note: Hinting to Lean that `forget R` and `R` are the same -unif_hint forget_obj_eq_coe (R : SemiRingCat) where ⊢ - (forget SemiRingCat).obj R ≟ R - instance instSemiring (X : SemiRingCat) : Semiring X := X.str instance instFunLike {X Y : SemiRingCat} : FunLike (X ⟶ Y) X Y := @@ -176,10 +172,6 @@ instance : BundledHom.ParentProjection @Ring.toSemiring := instance (X : RingCat) : Ring X := X.str --- Porting note: Hinting to Lean that `forget R` and `R` are the same -unif_hint forget_obj_eq_coe (R : RingCat) where ⊢ - (forget RingCat).obj R ≟ R - instance instRing (X : RingCat) : Ring X := X.str instance instFunLike {X Y : RingCat} : FunLike (X ⟶ Y) X Y := @@ -273,7 +265,7 @@ instance hasForgetToAddCommGrp : HasForget₂ RingCat AddCommGrp where end RingCat /-- The category of commutative semirings. -/ -def CommSemiRingCat : Type (u + 1) := +abbrev CommSemiRingCat : Type (u + 1) := Bundled CommSemiring namespace CommSemiRingCat @@ -294,10 +286,6 @@ instance : CoeSort CommSemiRingCat Type* where instance (X : CommSemiRingCat) : CommSemiring X := X.str --- Porting note: Hinting to Lean that `forget R` and `R` are the same -unif_hint forget_obj_eq_coe (R : CommSemiRingCat) where ⊢ - (forget CommSemiRingCat).obj R ≟ R - instance instCommSemiring (X : CommSemiRingCat) : CommSemiring X := X.str instance instCommSemiring' (X : CommSemiRingCat) : CommSemiring <| (forget CommSemiRingCat).obj X := @@ -412,7 +400,7 @@ instance forgetReflectIsos : (forget CommSemiRingCat).ReflectsIsomorphisms where end CommSemiRingCat /-- The category of commutative rings. -/ -def CommRingCat : Type (u + 1) := +abbrev CommRingCat : Type (u + 1) := Bundled CommRing namespace CommRingCat @@ -424,17 +412,6 @@ instance : BundledHom.ParentProjection @CommRing.toRing := -- see https://github.com/leanprover-community/mathlib4/issues/5020 deriving instance LargeCategory for CommRingCat -instance : ConcreteCategory CommRingCat := by - dsimp [CommRingCat] - infer_instance - -instance : CoeSort CommRingCat Type* where - coe X := X.α - --- Porting note: Hinting to Lean that `forget R` and `R` are the same -unif_hint forget_obj_eq_coe (R : CommRingCat) where ⊢ - (forget CommRingCat).obj R ≟ R - instance instCommRing (X : CommRingCat) : CommRing X := X.str instance instCommRing' (X : CommRingCat) : CommRing <| (forget CommRingCat).obj X := X.str @@ -546,6 +523,12 @@ theorem coe_of (R : Type u) [CommRing R] : (CommRingCat.of R : Type u) = R := instance hasForgetToRingCat : HasForget₂ CommRingCat RingCat := BundledHom.forget₂ _ _ +@[simp] lemma forgetToRingCat_obj (A : CommRingCat.{u}) : + ((forget₂ _ RingCat).obj A : Type _) = A := rfl + +@[simp] lemma forgetToRingCat_map_apply {A B : CommRingCat.{u}} (f : A ⟶ B) (a : A) : + DFunLike.coe (α := A) (β := fun _ ↦ B) ((forget₂ _ RingCat).map f) a = f a := rfl + /-- The forgetful functor from commutative rings to (multiplicative) commutative monoids. -/ instance hasForgetToCommSemiRingCat : HasForget₂ CommRingCat CommSemiRingCat := HasForget₂.mk' (fun R : CommRingCat => CommSemiRingCat.of R) (fun R => rfl) diff --git a/Mathlib/Algebra/Category/Ring/Instances.lean b/Mathlib/Algebra/Category/Ring/Instances.lean index c1e005f022104..fc588d27c8248 100644 --- a/Mathlib/Algebra/Category/Ring/Instances.lean +++ b/Mathlib/Algebra/Category/Ring/Instances.lean @@ -38,7 +38,7 @@ instance Localization.epi' {R : CommRingCat} (M : Submonoid R) : instance CommRingCat.isLocalRingHom_comp {R S T : CommRingCat} (f : R ⟶ S) (g : S ⟶ T) [IsLocalRingHom g] [IsLocalRingHom f] : IsLocalRingHom (f ≫ g) := - _root_.isLocalRingHom_comp _ _ + RingHom.isLocalRingHom_comp _ _ theorem isLocalRingHom_of_iso {R S : CommRingCat} (f : R ≅ S) : IsLocalRingHom f.hom := { map_nonunit := fun a ha => by diff --git a/Mathlib/Algebra/CharP/Defs.lean b/Mathlib/Algebra/CharP/Defs.lean index d470a6086987e..e597077cdd70e 100644 --- a/Mathlib/Algebra/CharP/Defs.lean +++ b/Mathlib/Algebra/CharP/Defs.lean @@ -11,6 +11,8 @@ import Mathlib.Data.Nat.Cast.Prod import Mathlib.Data.Nat.Find import Mathlib.Data.Nat.Prime.Defs import Mathlib.Data.ULift +import Mathlib.Tactic.NormNum.Basic +import Mathlib.Order.Interval.Set.Basic /-! # Characteristic of semirings @@ -102,10 +104,10 @@ lemma intCast_injOn_Ico [IsRightCancelAdd R] : InjOn (Int.cast : ℤ → R) (Ico lemma intCast_eq_zero_iff (a : ℤ) : (a : R) = 0 ↔ (p : ℤ) ∣ a := by rcases lt_trichotomy a 0 with (h | rfl | h) - · rw [← neg_eq_zero, ← Int.cast_neg, ← dvd_neg] + · rw [← neg_eq_zero, ← Int.cast_neg, ← Int.dvd_neg] lift -a to ℕ using neg_nonneg.mpr (le_of_lt h) with b rw [Int.cast_natCast, CharP.cast_eq_zero_iff R p, Int.natCast_dvd_natCast] - · simp only [Int.cast_zero, eq_self_iff_true, dvd_zero] + · simp only [Int.cast_zero, eq_self_iff_true, Int.dvd_zero] · lift a to ℕ using le_of_lt h with b rw [Int.cast_natCast, CharP.cast_eq_zero_iff R p, Int.natCast_dvd_natCast] diff --git a/Mathlib/Algebra/CharZero/Defs.lean b/Mathlib/Algebra/CharZero/Defs.lean index 8f2cf74d4cef2..c82356e6fa6e7 100644 --- a/Mathlib/Algebra/CharZero/Defs.lean +++ b/Mathlib/Algebra/CharZero/Defs.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Int.Cast.Defs -import Mathlib.Algebra.NeZero import Mathlib.Logic.Function.Basic /-! diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean index 34d81f490bea6..73f695ecae794 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/ApproximationCorollaries.lean @@ -97,9 +97,9 @@ theorem of_convergence_epsilon : 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 + 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 - calc 1 < ε * (N' : K) := (div_lt_iff' ε_pos).mp one_div_ε_lt_N' + calc 1 < ε * (N' : K) := (div_lt_iff₀' ε_pos).mp one_div_ε_lt_N' _ ≤ ε * (B * nB) := ?_ -- cancel `ε` gcongr diff --git a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean index be6b7195e1964..e2e525d76dcdc 100644 --- a/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean +++ b/Mathlib/Algebra/ContinuedFractions/Computation/Approximations.lean @@ -94,12 +94,9 @@ theorem one_le_succ_nth_stream_b {ifp_succ_n : IntFractPair K} ∃ ifp_n, IntFractPair.stream v n = some ifp_n ∧ ifp_n.fr ≠ 0 ∧ IntFractPair.of ifp_n.fr⁻¹ = ifp_succ_n := succ_nth_stream_eq_some_iff.1 succ_nth_stream_eq - suffices 1 ≤ ifp_n.fr⁻¹ by rwa [IntFractPair.of, le_floor, cast_one] - suffices ifp_n.fr ≤ 1 by - have h : 0 < ifp_n.fr := - lt_of_le_of_ne (nth_stream_fr_nonneg nth_stream_eq) stream_nth_fr_ne_zero.symm - apply one_le_inv h this - simp only [le_of_lt (nth_stream_fr_lt_one nth_stream_eq)] + rw [IntFractPair.of, le_floor, cast_one, one_le_inv₀ + ((nth_stream_fr_nonneg nth_stream_eq).lt_of_ne' stream_nth_fr_ne_zero)] + exact (nth_stream_fr_lt_one nth_stream_eq).le /-- Shows that the `n + 1`th integer part `bₙ₊₁` of the stream is smaller or equal than the inverse of diff --git a/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean b/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean index 2adf582909701..99e76fa64a5f5 100644 --- a/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean +++ b/Mathlib/Algebra/ContinuedFractions/ConvergentsEquiv.lean @@ -166,9 +166,6 @@ theorem succ_succ_nth_conv'Aux_eq_succ_nth_conv'Aux_squashSeq : gp_head.a / (gp_head.b + convs'Aux s.tail (m + 2)) = convs'Aux (squashSeq s (m + 1)) (m + 2) by simpa only [convs'Aux, s_head_eq] - have : convs'Aux s.tail (m + 2) = convs'Aux (squashSeq s.tail m) (m + 1) := by - refine IH gp_succ_n ?_ - simpa [Stream'.Seq.get?_tail] using s_succ_nth_eq have : (squashSeq s (m + 1)).head = some gp_head := (squashSeq_nth_of_lt m.succ_pos).trans s_head_eq simp_all [convs'Aux, squashSeq_succ_n_tail_eq_squashSeq_tail_n] diff --git a/Mathlib/Algebra/DirectLimit.lean b/Mathlib/Algebra/DirectLimit.lean index f1aa6c7623464..bcbcb659f05d8 100644 --- a/Mathlib/Algebra/DirectLimit.lean +++ b/Mathlib/Algebra/DirectLimit.lean @@ -316,12 +316,8 @@ theorem of.zero_exact_aux [∀ i (k : G i), Decidable (k ≠ 0)] [Nonempty ι] [ ⟨k, fun l hl => (Finset.mem_union.1 (DFinsupp.support_add hl)).elim (fun hl => le_trans (hi _ hl) hik) fun hl => le_trans (hj _ hl) hjk, by - -- Porting note: this had been - -- simp [LinearMap.map_add, hxi, hyj, toModule_totalize_of_le hik hi, - -- toModule_totalize_of_le hjk hj] - simp only [map_add] - rw [toModule_totalize_of_le hik hi, toModule_totalize_of_le hjk hj] - simp [hxi, hyj]⟩) + simp [LinearMap.map_add, hxi, hyj, toModule_totalize_of_le hik hi, + toModule_totalize_of_le hjk hj]⟩) fun a x ⟨i, hi, hxi⟩ => ⟨i, fun k hk => hi k (DirectSum.support_smul _ _ hk), by simp [LinearMap.map_smul, hxi]⟩ @@ -721,9 +717,7 @@ theorem of.zero_exact_aux [Nonempty ι] [IsDirected ι (· ≤ ·)] {x : FreeCom dsimp only rw [(f' i i _).map_mul] · exact sub_self _ - all_goals tauto - -- Porting note: was - --exacts [sub_self _, Or.inl rfl, Or.inr (Or.inr rfl), Or.inr (Or.inl rfl)] + exacts [Or.inl rfl, Or.inr (Or.inr rfl), Or.inr (Or.inl rfl)] · refine Nonempty.elim (by infer_instance) fun ind : ι => ?_ refine ⟨ind, ∅, fun _ => False.elim, isSupported_zero, fun [_] => ?_⟩ -- Porting note: `RingHom.map_zero` was `(restriction _).map_zero` @@ -944,7 +938,7 @@ instance nontrivial [DirectedSystem G fun i j h => f' i j h] : theorem exists_inv {p : Ring.DirectLimit G f} : p ≠ 0 → ∃ y, p * y = 1 := Ring.DirectLimit.induction_on p fun i x H => ⟨Ring.DirectLimit.of G f i x⁻¹, by - erw [← (Ring.DirectLimit.of _ _ _).map_mul, + rw [← (Ring.DirectLimit.of _ _ _).map_mul, mul_inv_cancel₀ fun h : x = 0 => H <| by rw [h, (Ring.DirectLimit.of _ _ _).map_zero], (Ring.DirectLimit.of _ _ _).map_one]⟩ diff --git a/Mathlib/Algebra/DirectSum/LinearMap.lean b/Mathlib/Algebra/DirectSum/LinearMap.lean index c3b5c570dd966..25ffc82193de4 100644 --- a/Mathlib/Algebra/DirectSum/LinearMap.lean +++ b/Mathlib/Algebra/DirectSum/LinearMap.lean @@ -78,12 +78,12 @@ lemma trace_eq_sum_trace_restrict' (h : IsInternal N) (hN : {i | N i ≠ ⊥}.Fi rw [← Finset.sum_coe_sort, trace_eq_sum_trace_restrict (isInternal_ne_bot_iff.mpr h) _] exact Fintype.sum_equiv hN.subtypeEquivToFinset _ _ (fun i ↦ rfl) -lemma trace_eq_zero_of_mapsTo_ne (h : IsInternal N) [hn : IsNoetherian R M] +lemma trace_eq_zero_of_mapsTo_ne (h : IsInternal N) [IsNoetherian R M] (σ : ι → ι) (hσ : ∀ i, σ i ≠ i) {f : Module.End R M} (hf : ∀ i, MapsTo f (N i) (N <| σ i)) : trace R M f = 0 := by - have hN : {i | N i ≠ ⊥}.Finite := CompleteLattice.WellFounded.finite_ne_bot_of_independent - hn.wf h.submodule_independent + have hN : {i | N i ≠ ⊥}.Finite := CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent + h.submodule_independent let s := hN.toFinset let κ := fun i ↦ Module.Free.ChooseBasisIndex R (N i) let b : (i : s) → Basis (κ i) R (N i) := fun i ↦ Module.Free.chooseBasis R (N i) @@ -100,27 +100,26 @@ lemma trace_comp_eq_zero_of_commute_of_trace_restrict_eq_zero [IsDomain R] [IsPrincipalIdealRing R] [Module.Free R M] [Module.Finite R M] {f g : Module.End R M} (h_comm : Commute f g) - (hf : ⨆ μ, ⨆ k, f.genEigenspace μ k = ⊤) - (hg : ∀ μ, trace R _ (g.restrict (f.mapsTo_iSup_genEigenspace_of_comm h_comm μ)) = 0) : + (hf : ⨆ μ, f.maxGenEigenspace μ = ⊤) + (hg : ∀ μ, trace R _ (g.restrict (f.mapsTo_maxGenEigenspace_of_comm h_comm μ)) = 0) : trace R _ (g ∘ₗ f) = 0 := by have hfg : ∀ μ, - MapsTo (g ∘ₗ f) ↑(⨆ k, f.genEigenspace μ k) ↑(⨆ k, f.genEigenspace μ k) := - fun μ ↦ (f.mapsTo_iSup_genEigenspace_of_comm h_comm μ).comp - (f.mapsTo_iSup_genEigenspace_of_comm rfl μ) + MapsTo (g ∘ₗ f) ↑(f.maxGenEigenspace μ) ↑(f.maxGenEigenspace μ) := + fun μ ↦ (f.mapsTo_maxGenEigenspace_of_comm h_comm μ).comp + (f.mapsTo_maxGenEigenspace_of_comm rfl μ) suffices ∀ μ, trace R _ ((g ∘ₗ f).restrict (hfg μ)) = 0 by classical have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top - f.independent_genEigenspace hf - have h_fin : {μ | ⨆ k, f.genEigenspace μ k ≠ ⊥}.Finite := - CompleteLattice.WellFounded.finite_ne_bot_of_independent IsWellFounded.wf - f.independent_genEigenspace + f.independent_maxGenEigenspace hf + have h_fin : {μ | f.maxGenEigenspace μ ≠ ⊥}.Finite := + CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent f.independent_maxGenEigenspace simp [trace_eq_sum_trace_restrict' hds h_fin hfg, this] intro μ - replace h_comm : Commute (g.restrict (f.mapsTo_iSup_genEigenspace_of_comm h_comm μ)) - (f.restrict (f.mapsTo_iSup_genEigenspace_of_comm rfl μ)) := + replace h_comm : Commute (g.restrict (f.mapsTo_maxGenEigenspace_of_comm h_comm μ)) + (f.restrict (f.mapsTo_maxGenEigenspace_of_comm rfl μ)) := restrict_commute h_comm.symm _ _ rw [restrict_comp, trace_comp_eq_mul_of_commute_of_isNilpotent μ h_comm - (f.isNilpotent_restrict_iSup_sub_algebraMap μ), hg, mul_zero] + (f.isNilpotent_restrict_maxGenEigenspace_sub_algebraMap μ), hg, mul_zero] lemma mapsTo_biSup_of_mapsTo {ι : Type*} {N : ι → Submodule R M} (s : Set ι) {f : Module.End R M} (hf : ∀ i, MapsTo f (N i) (N i)) : diff --git a/Mathlib/Algebra/DirectSum/Module.lean b/Mathlib/Algebra/DirectSum/Module.lean index bda16093f4ab9..291bd79759b1b 100644 --- a/Mathlib/Algebra/DirectSum/Module.lean +++ b/Mathlib/Algebra/DirectSum/Module.lean @@ -279,7 +279,7 @@ theorem coeLinearMap_eq_dfinsupp_sum [DecidableEq M] (x : DirectSum ι fun i => simp only [coeLinearMap, toModule, DFinsupp.lsum, LinearEquiv.coe_mk, LinearMap.coe_mk, AddHom.coe_mk] rw [DFinsupp.sumAddHom_apply] - simp only [LinearMap.toAddMonoidHom_coe, Submodule.coeSubtype] + simp only [LinearMap.toAddMonoidHom_coe, Submodule.coe_subtype] @[simp] theorem coeLinearMap_of (i : ι) (x : A i) : DirectSum.coeLinearMap A (of (fun i ↦ A i) i x) = x := @@ -349,7 +349,7 @@ theorem IsInternal.collectedBasis_coe (h : IsInternal A) {α : ι → Type*} simp only [DFinsupp.mapRange_single, Basis.repr_symm_apply, linearCombination_single, one_smul, toModule] erw [DFinsupp.lsum_single] - simp only [Submodule.coeSubtype] + simp only [Submodule.coe_subtype] theorem IsInternal.collectedBasis_mem (h : IsInternal A) {α : ι → Type*} (v : ∀ i, Basis (α i) R (A i)) (a : Σi, α i) : h.collectedBasis v a ∈ A a.1 := by simp diff --git a/Mathlib/Algebra/Field/Basic.lean b/Mathlib/Algebra/Field/Basic.lean index 570a5278b9b56..420cf3c602577 100644 --- a/Mathlib/Algebra/Field/Basic.lean +++ b/Mathlib/Algebra/Field/Basic.lean @@ -167,7 +167,7 @@ end DivisionRing section Semifield -variable [Semifield K] {a b c d : K} +variable [Semifield K] {a b d : K} theorem div_add_div (a : K) (c : K) (hb : b ≠ 0) (hd : d ≠ 0) : a / b + c / d = (a * d + b * c) / (b * d) := @@ -274,9 +274,9 @@ protected abbrev divisionRing [DivisionRing L] (zero : f 0 = 0) (one : f 1 = 1) toRing := hf.ring f zero one add mul neg sub nsmul zsmul npow natCast intCast __ := hf.groupWithZero f zero one mul inv div npow zpow __ := hf.divisionSemiring f zero one add mul inv div nsmul nnqsmul npow zpow natCast nnratCast - ratCast_def q := hf <| by erw [ratCast, div, intCast, natCast, Rat.cast_def] + ratCast_def q := hf <| by rw [ratCast, div, intCast, natCast, Rat.cast_def] qsmul := (· • ·) - qsmul_def q a := hf <| by erw [qsmul, mul, Rat.smul_def, ratCast] + qsmul_def q a := hf <| by rw [qsmul, mul, Rat.smul_def, ratCast] /-- Pullback a `Field` along an injective function. -/ -- See note [reducible non-instances] diff --git a/Mathlib/Algebra/Field/Defs.lean b/Mathlib/Algebra/Field/Defs.lean index 834f25d5fc450..4bb07df74d908 100644 --- a/Mathlib/Algebra/Field/Defs.lean +++ b/Mathlib/Algebra/Field/Defs.lean @@ -45,8 +45,8 @@ field, division ring, skew field, skew-field, skewfield assert_not_imported Mathlib.Tactic.Common --- `NeZero` should not be needed in the basic algebraic hierarchy. -assert_not_exists NeZero +-- `NeZero` theory should not be needed in the basic algebraic hierarchy +assert_not_imported Mathlib.Algebra.NeZero assert_not_exists MonoidHom @@ -194,7 +194,7 @@ variable (K) end NNRat namespace Rat -variable [DivisionRing K] {a b : K} +variable [DivisionRing K] lemma cast_def (q : ℚ) : (q : K) = q.num / q.den := DivisionRing.ratCast_def _ diff --git a/Mathlib/Algebra/Field/Subfield.lean b/Mathlib/Algebra/Field/Subfield.lean index 63adf4ac50a55..30b6731d7f52c 100644 --- a/Mathlib/Algebra/Field/Subfield.lean +++ b/Mathlib/Algebra/Field/Subfield.lean @@ -126,20 +126,20 @@ variable (S) /-- A subfield inherits a division ring structure -/ instance (priority := 75) toDivisionRing (s : S) : DivisionRing s := Subtype.coe_injective.divisionRing ((↑) : s → K) - (by rfl) (by rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) - (by intros; rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) - (by intros; rfl) (coe_nnqsmul _) (coe_qsmul _) (by intros; rfl) (by intros; rfl) - (by intros; rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) + rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) + (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + (fun _ _ ↦ rfl) (coe_nnqsmul _) (coe_qsmul _) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + (fun _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) -- Prefer subclasses of `Field` over subclasses of `SubfieldClass`. /-- A subfield of a field inherits a field structure -/ instance (priority := 75) toField {K} [Field K] [SetLike S K] [SubfieldClass S K] (s : S) : Field s := Subtype.coe_injective.field ((↑) : s → K) - (by rfl) (by rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) - (by intros; rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) (by intros; rfl) - (coe_nnqsmul _) (coe_qsmul _) (by intros; rfl) (by intros; rfl) (by intros; rfl) - (by intros; rfl) (by intros; rfl) (by intros; rfl) + rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) + (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) + (coe_nnqsmul _) (coe_qsmul _) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) + (fun _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) end SubfieldClass @@ -313,15 +313,15 @@ instance : Pow s ℤ := instance toDivisionRing (s : Subfield K) : DivisionRing s := Subtype.coe_injective.divisionRing ((↑) : s → K) rfl rfl (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) - (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (by intros; rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) - (by intros; rfl) fun _ ↦ rfl + (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ _ ↦ rfl) (fun _ ↦ rfl) (fun _ ↦ rfl) + (fun _ ↦ rfl) fun _ ↦ rfl /-- A subfield inherits a field structure -/ instance toField {K} [Field K] (s : Subfield K) : Field s := Subtype.coe_injective.field ((↑) : s → K) rfl rfl (fun _ _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) - (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (by intros; rfl) (fun _ => rfl) - (fun _ => rfl) (by intros; rfl) fun _ => rfl + (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ => rfl) (fun _ _ ↦ rfl) (fun _ => rfl) + (fun _ => rfl) (fun _ ↦ rfl) fun _ => rfl @[simp, norm_cast] theorem coe_add (x y : s) : (↑(x + y) : K) = ↑x + ↑y := diff --git a/Mathlib/Algebra/Free.lean b/Mathlib/Algebra/Free.lean index 1b0f927525cca..134a4e81ed9ff 100644 --- a/Mathlib/Algebra/Free.lean +++ b/Mathlib/Algebra/Free.lean @@ -6,7 +6,6 @@ Authors: Kenny Lau import Mathlib.Algebra.Group.Equiv.Basic import Mathlib.Control.Applicative import Mathlib.Control.Traversable.Basic -import Mathlib.Data.List.Basic import Mathlib.Logic.Equiv.Defs import Mathlib.Tactic.AdaptationNote diff --git a/Mathlib/Algebra/GCDMonoid/Basic.lean b/Mathlib/Algebra/GCDMonoid/Basic.lean index f578796cbf0ff..fee781f192238 100644 --- a/Mathlib/Algebra/GCDMonoid/Basic.lean +++ b/Mathlib/Algebra/GCDMonoid/Basic.lean @@ -589,8 +589,8 @@ theorem exists_associated_pow_of_mul_eq_pow [GCDMonoid α] {a b c : α} (hab : I use Units.mkOfMulEqOne _ _ h' rw [Units.val_mkOfMulEqOne, ha'] -theorem exists_eq_pow_of_mul_eq_pow [GCDMonoid α] [Unique αˣ] {a b c : α} (hab : IsUnit (gcd a b)) - {k : ℕ} (h : a * b = c ^ k) : ∃ d : α, a = d ^ k := +theorem exists_eq_pow_of_mul_eq_pow [GCDMonoid α] [Subsingleton αˣ] + {a b c : α} (hab : IsUnit (gcd a b)) {k : ℕ} (h : a * b = c ^ k) : ∃ d : α, a = d ^ k := let ⟨d, hd⟩ := exists_associated_pow_of_mul_eq_pow hab h ⟨d, (associated_iff_eq.mp hd).symm⟩ @@ -820,7 +820,7 @@ end GCDMonoid section UniqueUnit -variable [CancelCommMonoidWithZero α] [Unique αˣ] +variable [CancelCommMonoidWithZero α] [Subsingleton αˣ] -- see Note [lower instance priority] instance (priority := 100) normalizationMonoidOfUniqueUnits : NormalizationMonoid α where diff --git a/Mathlib/Algebra/GeomSum.lean b/Mathlib/Algebra/GeomSum.lean index 62bd098ce1152..70a08526df06e 100644 --- a/Mathlib/Algebra/GeomSum.lean +++ b/Mathlib/Algebra/GeomSum.lean @@ -482,7 +482,7 @@ theorem geom_sum_pos' [LinearOrderedRing α] (hx : 0 < x + 1) (hn : n ≠ 0) : theorem Odd.geom_sum_pos [LinearOrderedRing α] (h : Odd n) : 0 < ∑ i ∈ range n, x ^ i := by rcases n with (_ | _ | k) - · exact ((show ¬Odd 0 by decide) h).elim + · exact (Nat.not_odd_zero h).elim · simp only [zero_add, range_one, sum_singleton, pow_zero, zero_lt_one] rw [← Nat.not_even_iff_odd] at h rcases lt_trichotomy (x + 1) 0 with (hx | hx | hx) diff --git a/Mathlib/Algebra/Group/Action/Defs.lean b/Mathlib/Algebra/Group/Action/Defs.lean index 91a530d0f239f..733f6bd366afc 100644 --- a/Mathlib/Algebra/Group/Action/Defs.lean +++ b/Mathlib/Algebra/Group/Action/Defs.lean @@ -48,7 +48,7 @@ assert_not_exists MonoidWithZero open Function (Injective Surjective) -variable {M N G H A B α β γ δ : Type*} +variable {M N G H α β γ δ : Type*} /-! ### Faithful actions -/ @@ -487,7 +487,7 @@ lemma smul_inv_smul (g : G) (a : α) : g • g⁻¹ • a = a := by rw [smul_smu ⟨fun h ↦ by rw [h, smul_inv_smul], fun h ↦ by rw [← h, inv_smul_smul]⟩ section Mul -variable [Mul H] [MulAction G H] [SMulCommClass G H H] [IsScalarTower G H H] {g : G} {a b : H} +variable [Mul H] [MulAction G H] [SMulCommClass G H H] [IsScalarTower G H H] {a b : H} @[simp] lemma Commute.smul_right_iff : Commute a (g • b) ↔ Commute a b := ⟨fun h ↦ inv_smul_smul g b ▸ h.smul_right g⁻¹, fun h ↦ h.smul_right g⟩ diff --git a/Mathlib/Algebra/Group/Action/Opposite.lean b/Mathlib/Algebra/Group/Action/Opposite.lean index 8092a68ff91c7..1217487ac1eda 100644 --- a/Mathlib/Algebra/Group/Action/Opposite.lean +++ b/Mathlib/Algebra/Group/Action/Opposite.lean @@ -27,7 +27,7 @@ With `open scoped RightActions`, this provides: assert_not_exists MonoidWithZero -variable {R M N α : Type*} +variable {M N α β : Type*} /-! ### Actions _on_ the opposite type @@ -97,7 +97,7 @@ In lemma names this is still called `op_vadd`. -/ scoped notation3:73 m:73 " <+ᵥ " r:74 => AddOpposite.op r +ᵥ m section examples -variable {α β : Type*} [SMul α β] [SMul αᵐᵒᵖ β] [VAdd α β] [VAdd αᵃᵒᵖ β] {a a₁ a₂ a₃ a₄ : α} {b : β} +variable [SMul α β] [SMul αᵐᵒᵖ β] [VAdd α β] [VAdd αᵃᵒᵖ β] {a a₁ a₂ a₃ a₄ : α} {b : β} -- Left and right actions are just notation around the general `•` and `+ᵥ` notations example : a •> b = a • b := rfl @@ -124,7 +124,7 @@ end examples end RightActions section -variable {α β : Type*} [Monoid α] [MulAction αᵐᵒᵖ β] +variable [Monoid α] [MulAction αᵐᵒᵖ β] open scoped RightActions diff --git a/Mathlib/Algebra/Group/Action/Sum.lean b/Mathlib/Algebra/Group/Action/Sum.lean index 5bc1602680cfc..0286b8e19b6e9 100644 --- a/Mathlib/Algebra/Group/Action/Sum.lean +++ b/Mathlib/Algebra/Group/Action/Sum.lean @@ -20,7 +20,7 @@ This file defines instances for additive and multiplicative actions on the binar assert_not_exists MonoidWithZero -variable {M N P α β γ : Type*} +variable {M N α β : Type*} namespace Sum diff --git a/Mathlib/Algebra/Group/AddChar.lean b/Mathlib/Algebra/Group/AddChar.lean index 28c90b17cfdf1..f9a1d383c185c 100644 --- a/Mathlib/Algebra/Group/AddChar.lean +++ b/Mathlib/Algebra/Group/AddChar.lean @@ -195,6 +195,16 @@ instance instZero : Zero (AddChar A M) := ⟨1⟩ lemma one_eq_zero : (1 : AddChar A M) = (0 : AddChar A M) := rfl +@[simp, norm_cast] lemma coe_eq_one : ⇑ψ = 1 ↔ ψ = 0 := by rw [← coe_zero, DFunLike.coe_fn_eq] + +@[simp] lemma toMonoidHomEquiv_zero : toMonoidHomEquiv (0 : AddChar A M) = 1 := rfl +@[simp] lemma toMonoidHomEquiv_symm_one : + toMonoidHomEquiv.symm (1 : Multiplicative A →* M) = 0 := rfl + +@[simp] lemma toAddMonoidHomEquiv_zero : toAddMonoidHomEquiv (0 : AddChar A M) = 0 := rfl +@[simp] lemma toAddMonoidHomEquiv_symm_zero : + toAddMonoidHomEquiv.symm (0 : A →+ Additive M) = 0 := rfl + instance instInhabited : Inhabited (AddChar A M) := ⟨1⟩ /-- Composing a `MonoidHom` with an `AddChar` yields another `AddChar`. -/ @@ -252,6 +262,8 @@ set_option linter.deprecated false in lemma isNontrivial_iff_ne_trivial (ψ : AddChar A M) : IsNontrivial ψ ↔ ψ ≠ 1 := not_forall.symm.trans (DFunLike.ext_iff (f := ψ) (g := 1)).symm.not +noncomputable instance : DecidableEq (AddChar A M) := Classical.decEq _ + end Basic section toCommMonoid @@ -291,6 +303,11 @@ lemma mul_eq_add (ψ χ : AddChar A M) : ψ * χ = ψ + χ := rfl lemma pow_eq_nsmul (ψ : AddChar A M) (n : ℕ) : ψ ^ n = n • ψ := rfl lemma prod_eq_sum (s : Finset ι) (ψ : ι → AddChar A M) : ∏ i in s, ψ i = ∑ i in s, ψ i := rfl +@[simp] lemma toMonoidHomEquiv_add (ψ φ : AddChar A M) : + toMonoidHomEquiv (ψ + φ) = toMonoidHomEquiv ψ * toMonoidHomEquiv φ := rfl +@[simp] lemma toMonoidHomEquiv_symm_mul (ψ φ : Multiplicative A →* M) : + toMonoidHomEquiv.symm (ψ * φ) = toMonoidHomEquiv.symm ψ + toMonoidHomEquiv.symm φ := rfl + /-- The natural equivalence to `(Multiplicative A →* M)` is a monoid isomorphism. -/ def toMonoidHomMulEquiv : AddChar A M ≃* (Multiplicative A →* M) := { toMonoidHomEquiv with map_mul' := fun φ ψ ↦ by rfl } @@ -356,8 +373,8 @@ instance : AddCommGroup (AddChar A M) := Additive.addCommGroup @[simp] lemma inv_apply (ψ : AddChar A M) (a : A) : ψ⁻¹ a = ψ (-a) := rfl @[simp] lemma neg_apply (ψ : AddChar A M) (a : A) : (-ψ) a = ψ (-a) := rfl -@[simp] lemma div_apply (ψ χ : AddChar A M) (a : A) : (ψ / χ) a = ψ a * χ (-a) := rfl -@[simp] lemma sub_apply (ψ χ : AddChar A M) (a : A) : (ψ - χ) a = ψ a * χ (-a) := rfl +lemma div_apply (ψ χ : AddChar A M) (a : A) : (ψ / χ) a = ψ a * χ (-a) := rfl +lemma sub_apply (ψ χ : AddChar A M) (a : A) : (ψ - χ) a = ψ a * χ (-a) := rfl end fromAddCommGroup @@ -387,8 +404,7 @@ lemma map_zsmul_eq_zpow (ψ : AddChar A M) (n : ℤ) (a : A) : ψ (n • a) = ( end fromAddGrouptoDivisionMonoid -section fromAddGrouptoDivisionCommMonoid - +section fromAddCommGrouptoDivisionCommMonoid variable {A M : Type*} [AddCommGroup A] [DivisionCommMonoid M] lemma inv_apply' (ψ : AddChar A M) (a : A) : ψ⁻¹ a = (ψ a)⁻¹ := by rw [inv_apply, map_neg_eq_inv] @@ -400,13 +416,18 @@ lemma div_apply' (ψ χ : AddChar A M) (a : A) : (ψ / χ) a = ψ a / χ a := by lemma sub_apply' (ψ χ : AddChar A M) (a : A) : (ψ - χ) a = ψ a / χ a := by rw [sub_apply, map_neg_eq_inv, div_eq_mul_inv] +@[simp] lemma zsmul_apply (n : ℤ) (ψ : AddChar A M) (a : A) : (n • ψ) a = ψ a ^ n := by + cases n <;> simp [-neg_apply, neg_apply'] + +@[simp] lemma zpow_apply (ψ : AddChar A M) (n : ℤ) (a : A) : (ψ ^ n) a = ψ a ^ n := zsmul_apply .. + lemma map_sub_eq_div (ψ : AddChar A M) (a b : A) : ψ (a - b) = ψ a / ψ b := ψ.toMonoidHom.map_div _ _ lemma injective_iff {ψ : AddChar A M} : Injective ψ ↔ ∀ ⦃x⦄, ψ x = 1 → x = 0 := ψ.toMonoidHom.ker_eq_bot_iff.symm.trans eq_bot_iff -end fromAddGrouptoDivisionCommMonoid +end fromAddCommGrouptoDivisionCommMonoid section MonoidWithZero variable {A M₀ : Type*} [AddGroup A] [MonoidWithZero M₀] [Nontrivial M₀] diff --git a/Mathlib/Algebra/Group/Basic.lean b/Mathlib/Algebra/Group/Basic.lean index 1fd34ff37fdbc..244c63da588ad 100644 --- a/Mathlib/Algebra/Group/Basic.lean +++ b/Mathlib/Algebra/Group/Basic.lean @@ -172,7 +172,7 @@ end CommSemigroup attribute [local simp] mul_assoc sub_eq_add_neg section Monoid -variable [Monoid M] {a b c : M} {m n : ℕ} +variable [Monoid M] {a b : M} {m n : ℕ} @[to_additive boole_nsmul] lemma pow_boole (P : Prop) [Decidable P] (a : M) : @@ -316,7 +316,7 @@ end InvolutiveInv section DivInvMonoid -variable [DivInvMonoid G] {a b c : G} +variable [DivInvMonoid G] @[to_additive, field_simps] -- The attributes are out of order on purpose theorem inv_eq_one_div (x : G) : x⁻¹ = 1 / x := by rw [div_eq_mul_inv, one_mul] diff --git a/Mathlib/Algebra/Group/Center.lean b/Mathlib/Algebra/Group/Center.lean index de1591f22ebe2..786c03ef1f1db 100644 --- a/Mathlib/Algebra/Group/Center.lean +++ b/Mathlib/Algebra/Group/Center.lean @@ -70,7 +70,7 @@ attribute [to_additive existing] isMulCentral_iff namespace IsMulCentral -variable {a b c : M} [Mul M] +variable {a c : M} [Mul M] -- cf. `Commute.left_comm` @[to_additive] diff --git a/Mathlib/Algebra/Group/Commute/Defs.lean b/Mathlib/Algebra/Group/Commute/Defs.lean index b7bcb09ff56a4..324484366c26a 100644 --- a/Mathlib/Algebra/Group/Commute/Defs.lean +++ b/Mathlib/Algebra/Group/Commute/Defs.lean @@ -181,7 +181,7 @@ end Monoid section DivisionMonoid -variable [DivisionMonoid G] {a b c d : G} +variable [DivisionMonoid G] {a b : G} @[to_additive] protected theorem mul_inv (hab : Commute a b) : (a * b)⁻¹ = a⁻¹ * b⁻¹ := by rw [hab.eq, mul_inv_rev] diff --git a/Mathlib/Algebra/Group/Defs.lean b/Mathlib/Algebra/Group/Defs.lean index 810e4ced7a7a0..7f7d7ece643cd 100644 --- a/Mathlib/Algebra/Group/Defs.lean +++ b/Mathlib/Algebra/Group/Defs.lean @@ -35,7 +35,7 @@ actions and register the following instances: - `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)`. +See the module `Algebra.AddTorsor` for a motivating example for the name `VAdd` (vector addition). ## Notation @@ -552,7 +552,7 @@ instance AddMonoid.toNatSMul {M : Type*} [AddMonoid M] : SMul ℕ M := attribute [to_additive existing toNatSMul] Monoid.toNatPow section Monoid -variable {M : Type*} [Monoid M] {a b c : M} {m n : ℕ} +variable {M : Type*} [Monoid M] {a b c : M} @[to_additive (attr := simp) nsmul_eq_smul] theorem npow_eq_pow (n : ℕ) (x : M) : Monoid.npow n x = x ^ n := @@ -807,7 +807,7 @@ class DivInvMonoid (G : Type u) extends Monoid G, Inv G, Div G where /-- `a ^ 0 = 1` -/ protected zpow_zero' : ∀ a : G, zpow 0 a = 1 := by intros; rfl /-- `a ^ (n + 1) = a ^ n * a` -/ - protected zpow_succ' (n : ℕ) (a : G) : zpow (Int.ofNat n.succ) a = zpow (Int.ofNat n) a * a := by + protected zpow_succ' (n : ℕ) (a : G) : zpow n.succ a = zpow n a * a := by intros; rfl /-- `a ^ -(n + 1) = (a ^ (n + 1))⁻¹` -/ protected zpow_neg' (n : ℕ) (a : G) : zpow (Int.negSucc n) a = (zpow n.succ a)⁻¹ := by intros; rfl @@ -848,7 +848,7 @@ class SubNegMonoid (G : Type u) extends AddMonoid G, Neg G, Sub G where protected zsmul : ℤ → G → G protected zsmul_zero' : ∀ a : G, zsmul 0 a = 0 := by intros; rfl protected zsmul_succ' (n : ℕ) (a : G) : - zsmul (Int.ofNat n.succ) a = zsmul (Int.ofNat n) a + a := by + zsmul n.succ a = zsmul n a + a := by intros; rfl protected zsmul_neg' (n : ℕ) (a : G) : zsmul (Int.negSucc n) a = -zsmul n.succ a := by intros; rfl @@ -879,7 +879,7 @@ theorem exists_zpow_surjective (G : Type*) [Pow G ℤ] [IsCyclic G] : section DivInvMonoid -variable [DivInvMonoid G] {a b : G} +variable [DivInvMonoid G] @[to_additive (attr := simp) zsmul_eq_smul] theorem zpow_eq_pow (n : ℤ) (x : G) : DivInvMonoid.zpow n x = x ^ n := @@ -1050,7 +1050,7 @@ attribute [to_additive] Group section Group -variable [Group G] {a b c : G} +variable [Group G] {a b : G} @[to_additive (attr := simp)] theorem inv_mul_cancel (a : G) : a⁻¹ * a = 1 := diff --git a/Mathlib/Algebra/Group/Equiv/Basic.lean b/Mathlib/Algebra/Group/Equiv/Basic.lean index 242b93f9ace47..cb72fdfe7db40 100644 --- a/Mathlib/Algebra/Group/Equiv/Basic.lean +++ b/Mathlib/Algebra/Group/Equiv/Basic.lean @@ -28,7 +28,7 @@ Equiv, MulEquiv, AddEquiv open Function -variable {F α β A B M N P Q G H : Type*} +variable {F α β M N P G H : Type*} /-- Makes a `OneHom` inverse from the bijective inverse of a `OneHom` -/ @[to_additive (attr := simps) @@ -130,7 +130,6 @@ instance (priority := 100) instMonoidHomClass _ = e (EquivLike.inv e (1 : N)) := by rw [← map_mul, one_mul] _ = 1 := EquivLike.right_inv e 1 } -variable [EquivLike F α β] variable {F} @[to_additive (attr := simp)] @@ -169,7 +168,7 @@ theorem MulEquivClass.toMulEquiv_injective [Mul α] [Mul β] [MulEquivClass F α namespace MulEquiv section Mul -variable [Mul M] [Mul N] [Mul P] [Mul Q] +variable [Mul M] [Mul N] [Mul P] section coe @@ -389,6 +388,18 @@ theorem symm_comp_eq {α : Type*} (e : M ≃* N) (f : α → M) (g : α → N) : e.symm ∘ g = f ↔ g = e ∘ f := e.toEquiv.symm_comp_eq f g +@[to_additive (attr := simp)] +theorem _root_.MulEquivClass.apply_coe_symm_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] + [MulEquivClass F α β] (e : F) (x : β) : + e ((e : α ≃* β).symm x) = x := + (e : α ≃* β).right_inv x + +@[to_additive (attr := simp)] +theorem _root_.MulEquivClass.coe_symm_apply_apply {α β} [Mul α] [Mul β] {F} [EquivLike F α β] + [MulEquivClass F α β] (e : F) (x : α) : + (e : α ≃* β).symm (e x) = x := + (e : α ≃* β).left_inv x + end symm section simps diff --git a/Mathlib/Algebra/Group/Even.lean b/Mathlib/Algebra/Group/Even.lean index 428970edc8bf0..5bd24647c2f65 100644 --- a/Mathlib/Algebra/Group/Even.lean +++ b/Mathlib/Algebra/Group/Even.lean @@ -34,7 +34,7 @@ assert_not_exists DenselyOrdered open MulOpposite -variable {F α β R : Type*} +variable {F α β : Type*} section Mul variable [Mul α] diff --git a/Mathlib/Algebra/Group/Fin/Basic.lean b/Mathlib/Algebra/Group/Fin/Basic.lean index d9710b7aedc23..9385f63b70721 100644 --- a/Mathlib/Algebra/Group/Fin/Basic.lean +++ b/Mathlib/Algebra/Group/Fin/Basic.lean @@ -23,7 +23,7 @@ assert_not_exists MonoidWithZero open Nat namespace Fin -variable {m n : ℕ} +variable {n : ℕ} /-! ### Instances -/ diff --git a/Mathlib/Algebra/Group/Hom/Basic.lean b/Mathlib/Algebra/Group/Hom/Basic.lean index 148098efacb87..9eb317e8d7b71 100644 --- a/Mathlib/Algebra/Group/Hom/Basic.lean +++ b/Mathlib/Algebra/Group/Hom/Basic.lean @@ -14,9 +14,9 @@ import Mathlib.Algebra.Group.Hom.Defs -- `NeZero` cannot be additivised, hence its theory should be developed outside of the -- `Algebra.Group` folder. -assert_not_exists NeZero +assert_not_imported Mathlib.Algebra.NeZero -variable {α β M N P : Type*} +variable {α M N P : Type*} -- monoids variable {G : Type*} {H : Type*} @@ -98,7 +98,7 @@ end MulHom namespace MonoidHom section Group -variable [Group G] [CommGroup H] +variable [Group G] /-- A homomorphism from a group to a monoid is injective iff its kernel is trivial. For the iff statement on the triviality of the kernel, see `injective_iff_map_eq_one'`. -/ @@ -125,8 +125,6 @@ theorem _root_.injective_iff_map_eq_one' {G H} [Group G] [MulOneClass H] (injective_iff_map_eq_one f).trans <| forall_congr' fun _ => ⟨fun h => ⟨h, fun H => H.symm ▸ map_one f⟩, Iff.mp⟩ -variable [MulOneClass M] - /-- Makes a group homomorphism from a proof that the map preserves right division `fun x y => x * y⁻¹`. See also `MonoidHom.of_map_div` for a version using `fun x y => x / y`. -/ diff --git a/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean b/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean index 5f9f1cea90e7a..0bdd4b963dd4a 100644 --- a/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean +++ b/Mathlib/Algebra/Group/Hom/CompTypeclasses.lean @@ -39,7 +39,7 @@ section MonoidHomCompTriple namespace MonoidHom /-- Class of composing triples -/ -class CompTriple {M N P : Type*} [Monoid M] [Monoid N] [Monoid P] +class CompTriple {M N P : Type*} [Monoid M] [Monoid N] [Monoid P] (φ : M →* N) (ψ : N →* P) (χ : outParam (M →* P)) : Prop where /-- The maps form a commuting triangle -/ comp_eq : ψ.comp φ = χ @@ -48,7 +48,6 @@ attribute [simp] CompTriple.comp_eq namespace CompTriple -variable {M' : Type*} [Monoid M'] variable {M N P : Type*} [Monoid M] [Monoid N] [Monoid P] /-- Class of Id maps -/ diff --git a/Mathlib/Algebra/Group/Hom/Defs.lean b/Mathlib/Algebra/Group/Hom/Defs.lean index f495bba039807..1a3bf932f98fd 100644 --- a/Mathlib/Algebra/Group/Hom/Defs.lean +++ b/Mathlib/Algebra/Group/Hom/Defs.lean @@ -143,8 +143,9 @@ homomorphisms. You should also extend this typeclass when you extend `AddMonoidHom`. -/ -class AddMonoidHomClass (F M N : Type*) [AddZeroClass M] [AddZeroClass N] [FunLike F M N] - extends AddHomClass F M N, ZeroHomClass F M N : Prop +class AddMonoidHomClass (F : Type*) (M N : outParam Type*) + [AddZeroClass M] [AddZeroClass N] [FunLike F M N] + extends AddHomClass F M N, ZeroHomClass F M N : Prop -- Instances and lemmas are defined below through `@[to_additive]`. end add_zero @@ -452,7 +453,7 @@ theorem map_pow [Monoid G] [Monoid H] [MonoidHomClass F G H] (f : F) (a : G) : | n + 1 => by rw [pow_succ, pow_succ, map_mul, map_pow f a n] @[to_additive (attr := simp)] -lemma map_comp_pow [Group G] [DivisionMonoid H] [MonoidHomClass F G H] (f : F) (g : ι → G) (n : ℕ) : +lemma map_comp_pow [Monoid G] [Monoid H] [MonoidHomClass F G H] (f : F) (g : ι → G) (n : ℕ) : f ∘ (g ^ n) = f ∘ g ^ n := by ext; simp @[to_additive] @@ -958,8 +959,6 @@ instance [MulOneClass M] [MulOneClass N] : Inhabited (M →* N) := ⟨1⟩ namespace MonoidHom -variable [Group G] [CommGroup H] - @[to_additive (attr := simp)] theorem one_comp [MulOneClass M] [MulOneClass N] [MulOneClass P] (f : M →* N) : (1 : N →* P).comp f = 1 := rfl diff --git a/Mathlib/Algebra/Group/Hom/End.lean b/Mathlib/Algebra/Group/Hom/End.lean index 00405f5550e0e..caa7de5333f3d 100644 --- a/Mathlib/Algebra/Group/Hom/End.lean +++ b/Mathlib/Algebra/Group/Hom/End.lean @@ -19,9 +19,9 @@ They are separate, and if someone would like to split this file in two that may -/ -universe uM uN uP uQ +universe uM -variable {M : Type uM} {N : Type uN} {P : Type uP} {Q : Type uQ} +variable {M : Type uM} namespace AddMonoid.End @@ -121,7 +121,7 @@ end Semiring section CommSemiring -variable {R S : Type*} [NonUnitalNonAssocCommSemiring R] +variable {R : Type*} [NonUnitalNonAssocCommSemiring R] namespace AddMonoid.End diff --git a/Mathlib/Algebra/Group/InjSurj.lean b/Mathlib/Algebra/Group/InjSurj.lean index a47bbde22c75a..c25210c59545a 100644 --- a/Mathlib/Algebra/Group/InjSurj.lean +++ b/Mathlib/Algebra/Group/InjSurj.lean @@ -55,7 +55,7 @@ a semigroup. See note [reducible non-instances]. -/ injective map that preserves `+` to an additive semigroup."] protected abbrev semigroup [Semigroup M₂] (f : M₁ → M₂) (hf : Injective f) (mul : ∀ x y, f (x * y) = f x * f y) : Semigroup M₁ := - { ‹Mul M₁› with mul_assoc := fun x y z => hf <| by erw [mul, mul, mul, mul, mul_assoc] } + { ‹Mul M₁› with mul_assoc := fun x y z => hf <| by rw [mul, mul, mul, mul, mul_assoc] } /-- A type endowed with `*` is a commutative magma, if it admits a surjective map that preserves `*` from a commutative magma. -/ @@ -83,7 +83,7 @@ semigroup, if it admits an injective map that preserves `+` to an additive left protected abbrev leftCancelSemigroup [LeftCancelSemigroup M₂] (f : M₁ → M₂) (hf : Injective f) (mul : ∀ x y, f (x * y) = f x * f y) : LeftCancelSemigroup M₁ := { hf.semigroup f mul with - mul_left_cancel := fun x y z H => hf <| (mul_right_inj (f x)).1 <| by erw [← mul, ← mul, H] } + mul_left_cancel := fun x y z H => hf <| (mul_right_inj (f x)).1 <| by rw [← mul, ← mul, H] } /-- A type endowed with `*` is a right cancel semigroup, if it admits an injective map that preserves `*` to a right cancel semigroup. See note [reducible non-instances]. -/ @@ -93,7 +93,7 @@ semigroup."] protected abbrev rightCancelSemigroup [RightCancelSemigroup M₂] (f : M₁ → M₂) (hf : Injective f) (mul : ∀ x y, f (x * y) = f x * f y) : RightCancelSemigroup M₁ := { hf.semigroup f mul with - mul_right_cancel := fun x y z H => hf <| (mul_left_inj (f y)).1 <| by erw [← mul, ← mul, H] } + mul_right_cancel := fun x y z H => hf <| (mul_left_inj (f y)).1 <| by rw [← mul, ← mul, H] } variable [One M₁] @@ -105,8 +105,8 @@ injective map that preserves `0` and `+` to an `AddZeroClass`."] protected abbrev mulOneClass [MulOneClass M₂] (f : M₁ → M₂) (hf : Injective f) (one : f 1 = 1) (mul : ∀ x y, f (x * y) = f x * f y) : MulOneClass M₁ := { ‹One M₁›, ‹Mul M₁› with - one_mul := fun x => hf <| by erw [mul, one, one_mul], - mul_one := fun x => hf <| by erw [mul, one, mul_one] } + one_mul := fun x => hf <| by rw [mul, one, one_mul], + mul_one := fun x => hf <| by rw [mul, one, mul_one] } variable [Pow M₁ ℕ] @@ -120,8 +120,8 @@ protected abbrev monoid [Monoid M₂] (f : M₁ → M₂) (hf : Injective f) (on (mul : ∀ x y, f (x * y) = f x * f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) : Monoid M₁ := { hf.mulOneClass f one mul, hf.semigroup f mul with npow := fun n x => x ^ n, - npow_zero := fun x => hf <| by erw [npow, one, pow_zero], - npow_succ := fun n x => hf <| by erw [npow, pow_succ, mul, npow] } + npow_zero := fun x => hf <| by rw [npow, one, pow_zero], + npow_succ := fun n x => hf <| by rw [npow, pow_succ, mul, npow] } /-- A type endowed with `0`, `1` and `+` is an additive monoid with one, if it admits an injective map that preserves `0`, `1` and `+` to an additive monoid with one. @@ -132,8 +132,8 @@ protected abbrev addMonoidWithOne {M₁} [Zero M₁] [One M₁] [Add M₁] [SMul (natCast : ∀ n : ℕ, f n = n) : AddMonoidWithOne M₁ := { hf.addMonoid f zero add (swap nsmul) with natCast := Nat.cast, - natCast_zero := hf (by erw [natCast, Nat.cast_zero, zero]), - natCast_succ := fun n => hf (by erw [natCast, Nat.cast_succ, add, one, natCast]), one := 1 } + natCast_zero := hf (by rw [natCast, Nat.cast_zero, zero]), + natCast_succ := fun n => hf (by rw [natCast, Nat.cast_succ, add, one, natCast]), one := 1 } /-- A type endowed with `1` and `*` is a left cancel monoid, if it admits an injective map that preserves `1` and `*` to a left cancel monoid. See note [reducible non-instances]. -/ @@ -215,7 +215,7 @@ injective map that preserves `0` and unary `-` to an `NegZeroClass`."] protected abbrev invOneClass [InvOneClass M₂] (f : M₁ → M₂) (hf : Injective f) (one : f 1 = 1) (inv : ∀ x, f (x⁻¹) = (f x)⁻¹) : InvOneClass M₁ := { ‹One M₁›, ‹Inv M₁› with - inv_one := hf <| by erw [inv, one, inv_one] } + inv_one := hf <| by rw [inv, one, inv_one] } variable [Div M₁] [Pow M₁ ℤ] @@ -232,10 +232,10 @@ protected abbrev divInvMonoid [DivInvMonoid M₂] (f : M₁ → M₂) (hf : Inje (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : DivInvMonoid M₁ := { hf.monoid f one mul npow, ‹Inv M₁›, ‹Div M₁› with zpow := fun n x => x ^ n, - zpow_zero' := fun x => hf <| by erw [zpow, zpow_zero, one], - zpow_succ' := fun n x => hf <| by erw [zpow, mul, zpow_natCast, pow_succ, zpow, zpow_natCast], - zpow_neg' := fun n x => hf <| by erw [zpow, zpow_negSucc, inv, zpow, zpow_natCast], - div_eq_mul_inv := fun x y => hf <| by erw [div, mul, inv, div_eq_mul_inv] } + zpow_zero' := fun x => hf <| by rw [zpow, zpow_zero, one], + zpow_succ' := fun n x => hf <| by rw [zpow, mul, zpow_natCast, pow_succ, zpow, zpow_natCast], + zpow_neg' := fun n x => hf <| by rw [zpow, zpow_negSucc, inv, zpow, zpow_natCast], + div_eq_mul_inv := fun x y => hf <| by rw [div, mul, inv, div_eq_mul_inv] } /-- A type endowed with `1`, `*`, `⁻¹`, and `/` is a `DivInvOneMonoid` if it admits an injective map that preserves `1`, `*`, `⁻¹`, and `/` to a `DivInvOneMonoid`. See note @@ -263,9 +263,9 @@ protected abbrev divisionMonoid [DivisionMonoid M₂] (f : M₁ → M₂) (hf : (div : ∀ x y, f (x / y) = f x / f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : DivisionMonoid M₁ := { hf.divInvMonoid f one mul inv div npow zpow, hf.involutiveInv f inv with - mul_inv_rev := fun x y => hf <| by erw [inv, mul, mul_inv_rev, mul, inv, inv], + mul_inv_rev := fun x y => hf <| by rw [inv, mul, mul_inv_rev, mul, inv, inv], inv_eq_of_mul := fun x y h => hf <| by - erw [inv, inv_eq_of_mul_eq_one_right (by erw [← mul, h, one])] } + rw [inv, inv_eq_of_mul_eq_one_right (by rw [← mul, h, one])] } /-- A type endowed with `1`, `*`, `⁻¹`, and `/` is a `DivisionCommMonoid` if it admits an injective map that preserves `1`, `*`, `⁻¹`, and `/` to a `DivisionCommMonoid`. @@ -291,7 +291,7 @@ protected abbrev group [Group M₂] (f : M₁ → M₂) (hf : Injective f) (one (div : ∀ x y, f (x / y) = f x / f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : Group M₁ := { hf.divInvMonoid f one mul inv div npow zpow with - inv_mul_cancel := fun x => hf <| by erw [mul, inv, inv_mul_cancel, one] } + inv_mul_cancel := fun x => hf <| by rw [mul, inv, inv_mul_cancel, one] } /-- A type endowed with `0`, `1` and `+` is an additive group with one, if it admits an injective map that preserves `0`, `1` and `+` to an additive group with one. See note @@ -306,7 +306,7 @@ protected abbrev addGroupWithOne {M₁} [Zero M₁] [One M₁] [Add M₁] [SMul hf.addMonoidWithOne f zero one add nsmul natCast with intCast := Int.cast, intCast_ofNat := fun n => hf (by rw [natCast, ← Int.cast, intCast, Int.cast_natCast]), - intCast_negSucc := fun n => hf (by erw [intCast, neg, natCast, Int.cast_negSucc] ) } + intCast_negSucc := fun n => hf (by rw [intCast, neg, natCast, Int.cast_negSucc] ) } /-- A type endowed with `1`, `*` and `⁻¹` is a commutative group, if it admits an injective map that preserves `1`, `*` and `⁻¹` to a commutative group. See note [reducible non-instances]. -/ @@ -358,7 +358,7 @@ protected abbrev semigroup [Semigroup M₁] (f : M₁ → M₂) (hf : Surjective a surjective map that preserves `+` from an additive commutative semigroup."] protected abbrev commMagma [CommMagma M₁] (f : M₁ → M₂) (hf : Surjective f) (mul : ∀ x y, f (x * y) = f x * f y) : CommMagma M₂ where - mul_comm := hf.forall₂.2 fun x y => by erw [← mul, ← mul, mul_comm] + mul_comm := hf.forall₂.2 fun x y => by rw [← mul, ← mul, mul_comm] /-- A type endowed with `*` is a commutative semigroup, if it admits a surjective map that preserves `*` from a commutative semigroup. See note [reducible non-instances]. -/ @@ -380,8 +380,8 @@ surjective map that preserves `0` and `+` to an `AddZeroClass`."] protected abbrev mulOneClass [MulOneClass M₁] (f : M₁ → M₂) (hf : Surjective f) (one : f 1 = 1) (mul : ∀ x y, f (x * y) = f x * f y) : MulOneClass M₂ := { ‹One M₂›, ‹Mul M₂› with - one_mul := hf.forall.2 fun x => by erw [← one, ← mul, one_mul], - mul_one := hf.forall.2 fun x => by erw [← one, ← mul, mul_one] } + one_mul := hf.forall.2 fun x => by rw [← one, ← mul, one_mul], + mul_one := hf.forall.2 fun x => by rw [← one, ← mul, mul_one] } variable [Pow M₂ ℕ] @@ -395,10 +395,10 @@ protected abbrev monoid [Monoid M₁] (f : M₁ → M₂) (hf : Surjective f) (o (mul : ∀ x y, f (x * y) = f x * f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) : Monoid M₂ := { hf.semigroup f mul, hf.mulOneClass f one mul with npow := fun n x => x ^ n, - npow_zero := hf.forall.2 fun x => by dsimp only; erw [← npow, pow_zero, ← one], + npow_zero := hf.forall.2 fun x => by dsimp only; rw [← npow, pow_zero, ← one], npow_succ := fun n => hf.forall.2 fun x => by dsimp only - erw [← npow, pow_succ, ← npow, ← mul] } + rw [← npow, pow_succ, ← npow, ← mul] } /-- A type endowed with `0`, `1` and `+` is an additive monoid with one, if it admits a surjective map that preserves `0`, `1` and `*` from an additive monoid with one. See note @@ -441,7 +441,7 @@ preserves `-` to a type which has an involutive negation."] protected abbrev involutiveInv {M₂ : Type*} [Inv M₂] [InvolutiveInv M₁] (f : M₁ → M₂) (hf : Surjective f) (inv : ∀ x, f x⁻¹ = (f x)⁻¹) : InvolutiveInv M₂ where inv := Inv.inv - inv_inv := hf.forall.2 fun x => by erw [← inv, ← inv, inv_inv] + inv_inv := hf.forall.2 fun x => by rw [← inv, ← inv, inv_inv] variable [Inv M₂] [Div M₂] [Pow M₂ ℤ] @@ -457,14 +457,14 @@ protected abbrev divInvMonoid [DivInvMonoid M₁] (f : M₁ → M₂) (hf : Surj (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : DivInvMonoid M₂ := { hf.monoid f one mul npow, ‹Div M₂›, ‹Inv M₂› with zpow := fun n x => x ^ n, - zpow_zero' := hf.forall.2 fun x => by dsimp only; erw [← zpow, zpow_zero, ← one], + zpow_zero' := hf.forall.2 fun x => by dsimp only; rw [← zpow, zpow_zero, ← one], zpow_succ' := fun n => hf.forall.2 fun x => by dsimp only - erw [← zpow, ← zpow, zpow_natCast, zpow_natCast, pow_succ, ← mul], + rw [← zpow, ← zpow, zpow_natCast, zpow_natCast, pow_succ, ← mul], zpow_neg' := fun n => hf.forall.2 fun x => by dsimp only - erw [← zpow, ← zpow, zpow_negSucc, zpow_natCast, inv], - div_eq_mul_inv := hf.forall₂.2 fun x y => by erw [← inv, ← mul, ← div, div_eq_mul_inv] } + rw [← zpow, ← zpow, zpow_negSucc, zpow_natCast, inv], + div_eq_mul_inv := hf.forall₂.2 fun x y => by rw [← inv, ← mul, ← div, div_eq_mul_inv] } /-- A type endowed with `1`, `*` and `⁻¹` is a group, if it admits a surjective map that preserves `1`, `*` and `⁻¹` to a group. See note [reducible non-instances]. -/ @@ -476,7 +476,7 @@ protected abbrev group [Group M₁] (f : M₁ → M₂) (hf : Surjective f) (one (div : ∀ x y, f (x / y) = f x / f y) (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : Group M₂ := { hf.divInvMonoid f one mul inv div npow zpow with - inv_mul_cancel := hf.forall.2 fun x => by erw [← inv, ← mul, inv_mul_cancel, one] } + inv_mul_cancel := hf.forall.2 fun x => by rw [← inv, ← mul, inv_mul_cancel, one] } /-- A type endowed with `0`, `1`, `+` is an additive group with one, if it admits a surjective map that preserves `0`, `1`, and `+` to an additive group with one. diff --git a/Mathlib/Algebra/Group/Int.lean b/Mathlib/Algebra/Group/Int.lean index 720440a2282fb..e30cfc2cfe4b0 100644 --- a/Mathlib/Algebra/Group/Int.lean +++ b/Mathlib/Algebra/Group/Int.lean @@ -47,7 +47,7 @@ instance instAddCommGroup : AddCommGroup ℤ where zsmul := (·*·) zsmul_zero' := Int.zero_mul zsmul_succ' m n := by - simp only [ofNat_eq_coe, ofNat_succ, Int.add_mul, Int.add_comm, Int.one_mul] + simp only [ofNat_succ, Int.add_mul, Int.add_comm, Int.one_mul] zsmul_neg' m n := by simp only [negSucc_coe, ofNat_succ, Int.neg_mul] sub_eq_add_neg _ _ := Int.sub_eq_add_neg diff --git a/Mathlib/Algebra/Group/Opposite.lean b/Mathlib/Algebra/Group/Opposite.lean index d7ea15a86adfe..a66f4838ff8fd 100644 --- a/Mathlib/Algebra/Group/Opposite.lean +++ b/Mathlib/Algebra/Group/Opposite.lean @@ -161,7 +161,6 @@ instance instDivInvMonoid [DivInvMonoid α] : DivInvMonoid αᵐᵒᵖ where zpow n a := op <| a.unop ^ n zpow_zero' _ := unop_injective <| zpow_zero _ zpow_succ' _ _ := unop_injective <| by - simp only [Int.ofNat_eq_coe] rw [unop_op, zpow_natCast, pow_succ', unop_mul, unop_op, zpow_natCast] zpow_neg' _ _ := unop_injective <| DivInvMonoid.zpow_neg' _ _ diff --git a/Mathlib/Algebra/Group/Pi/Basic.lean b/Mathlib/Algebra/Group/Pi/Basic.lean index 480759b083256..7a88ae8220a12 100644 --- a/Mathlib/Algebra/Group/Pi/Basic.lean +++ b/Mathlib/Algebra/Group/Pi/Basic.lean @@ -400,18 +400,6 @@ theorem extend_div [Div γ] (f : α → β) (g₁ g₂ : α → γ) (e₁ e₂ : end Extend -theorem surjective_pi_map {F : ∀ i, f i → g i} (hF : ∀ i, Surjective (F i)) : - Surjective fun x : ∀ i, f i => fun i => F i (x i) := fun y => - ⟨fun i => (hF i (y i)).choose, funext fun i => (hF i (y i)).choose_spec⟩ - -theorem injective_pi_map {F : ∀ i, f i → g i} (hF : ∀ i, Injective (F i)) : - Injective fun x : ∀ i, f i => fun i => F i (x i) := - fun _ _ h => funext fun i => hF i <| (congr_fun h i : _) - -theorem bijective_pi_map {F : ∀ i, f i → g i} (hF : ∀ i, Bijective (F i)) : - Bijective fun x : ∀ i, f i => fun i => F i (x i) := - ⟨injective_pi_map fun i => (hF i).injective, surjective_pi_map fun i => (hF i).surjective⟩ - lemma comp_eq_const_iff (b : β) (f : α → β) {g : β → γ} (hg : Injective g) : g ∘ f = Function.const _ (g b) ↔ f = Function.const _ b := hg.comp_left.eq_iff' rfl diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean index b36ab5a81b89b..5e5ebeefca3c2 100644 --- a/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean +++ b/Mathlib/Algebra/Group/Pointwise/Finset/Basic.lean @@ -221,7 +221,7 @@ attribute [aesop safe apply (rule_sets := [finsetNonempty])] Nonempty.inv Nonemp @[to_additive (attr := simp)] theorem inv_eq_empty : s⁻¹ = ∅ ↔ s = ∅ := image_eq_empty -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem inv_subset_inv (h : s ⊆ t) : s⁻¹ ⊆ t⁻¹ := image_subset_image h @@ -272,6 +272,9 @@ theorem coe_inv (s : Finset α) : ↑s⁻¹ = (s : Set α)⁻¹ := coe_image.tra @[to_additive (attr := simp)] theorem card_inv (s : Finset α) : s⁻¹.card = s.card := card_image_of_injective _ inv_injective +@[to_additive (attr := simp)] +lemma dens_inv [Fintype α] (s : Finset α) : s⁻¹.dens = s.dens := by simp [dens] + @[to_additive (attr := simp)] theorem preimage_inv (s : Finset α) : s.preimage (·⁻¹) inv_injective.injOn = s⁻¹ := coe_injective <| by rw [coe_preimage, Set.inv_preimage, coe_inv] @@ -370,7 +373,7 @@ theorem singleton_mul (a : α) : {a} * s = s.image (a * ·) := theorem singleton_mul_singleton (a b : α) : ({a} : Finset α) * {b} = {a * b} := image₂_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem mul_subset_mul : s₁ ⊆ s₂ → t₁ ⊆ t₂ → s₁ * t₁ ⊆ s₂ * t₂ := image₂_subset @@ -417,7 +420,7 @@ theorem union_mul_inter_subset_union : (s₁ ∪ s₂) * (t₁ ∩ t₂) ⊆ s `s'`, `t'` such that `s' ⊆ s`, `t' ⊆ t` and `u ⊆ s' + t'`."] theorem subset_mul {s t : Set α} : ↑u ⊆ s * t → ∃ s' t' : Finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' * t' := - subset_image₂ + subset_set_image₂ @[to_additive] theorem image_mul [DecidableEq β] : (s * t).image (f : α → β) = s.image f * t.image f := @@ -556,7 +559,7 @@ theorem singleton_div (a : α) : {a} / s = s.image (a / ·) := theorem singleton_div_singleton (a b : α) : ({a} : Finset α) / {b} = {a / b} := image₂_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem div_subset_div : s₁ ⊆ s₂ → t₁ ⊆ t₂ → s₁ / t₁ ⊆ s₂ / t₂ := image₂_subset @@ -603,7 +606,7 @@ theorem union_div_inter_subset_union : (s₁ ∪ s₂) / (t₁ ∩ t₂) ⊆ s `s'`, `t'` such that `s' ⊆ s`, `t' ⊆ t` and `u ⊆ s' - t'`."] theorem subset_div {s t : Set α} : ↑u ⊆ s / t → ∃ s' t' : Finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' / t' := - subset_image₂ + subset_set_image₂ @[to_additive (attr := simp (default + 1))] lemma sup_div_le [SemilatticeSup β] [OrderBot β] {s t : Finset α} {f : α → β} {a : β} : @@ -898,6 +901,12 @@ theorem isUnit_coe : IsUnit (s : Set α) ↔ IsUnit s := by @[to_additive (attr := simp)] lemma univ_div_univ [Fintype α] : (univ / univ : Finset α) = univ := by simp [div_eq_mul_inv] +@[to_additive] lemma subset_div_left (ht : 1 ∈ t) : s ⊆ s / t := by + rw [div_eq_mul_inv]; exact subset_mul_left _ <| by simpa + +@[to_additive] lemma inv_subset_div_right (hs : 1 ∈ s) : t⁻¹ ⊆ s / t := by + rw [div_eq_mul_inv]; exact subset_mul_right _ hs + end DivisionMonoid /-- `Finset α` is a commutative division monoid under pointwise operations if `α` is. -/ @@ -1144,7 +1153,7 @@ theorem smul_singleton (b : β) : s • ({b} : Finset β) = s.image (· • b) : theorem singleton_smul_singleton (a : α) (b : β) : ({a} : Finset α) • ({b} : Finset β) = {a • b} := image₂_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem smul_subset_smul : s₁ ⊆ s₂ → t₁ ⊆ t₂ → s₁ • t₁ ⊆ s₂ • t₂ := image₂_subset @@ -1191,7 +1200,7 @@ theorem union_smul_inter_subset_union [DecidableEq α] : (s₁ ∪ s₂) • (t finsets `s'`, `t'` such that `s' ⊆ s`, `t' ⊆ t` and `u ⊆ s' +ᵥ t'`."] theorem subset_smul {s : Set α} {t : Set β} : ↑u ⊆ s • t → ∃ (s' : Finset α) (t' : Finset β), ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' • t' := - subset_image₂ + subset_set_image₂ end SMul @@ -1266,7 +1275,7 @@ theorem singleton_vsub (a : β) : ({a} : Finset β) -ᵥ t = t.image (a -ᵥ ·) theorem singleton_vsub_singleton (a b : β) : ({a} : Finset β) -ᵥ {b} = {a -ᵥ b} := image₂_singleton -@[mono] +@[mono, gcongr] theorem vsub_subset_vsub : s₁ ⊆ s₂ → t₁ ⊆ t₂ → s₁ -ᵥ t₁ ⊆ s₂ -ᵥ t₂ := image₂_subset @@ -1301,7 +1310,7 @@ end finsets `s'`, `t'` such that `s' ⊆ s`, `t' ⊆ t` and `u ⊆ s' -ᵥ t'`. -/ theorem subset_vsub {s t : Set β} : ↑u ⊆ s -ᵥ t → ∃ s' t' : Finset β, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' -ᵥ t' := - subset_image₂ + subset_set_image₂ end VSub @@ -1365,7 +1374,7 @@ theorem Nonempty.smul_finset (hs : s.Nonempty) : (a • s).Nonempty := theorem singleton_smul (a : α) : ({a} : Finset α) • t = a • t := image₂_singleton_left -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem smul_finset_subset_smul_finset : s ⊆ t → a • s ⊆ a • t := image_subset_image @@ -1377,6 +1386,10 @@ theorem smul_finset_singleton (b : β) : a • ({b} : Finset β) = {a • b} := theorem smul_finset_union : a • (s₁ ∪ s₂) = a • s₁ ∪ a • s₂ := image_union _ _ +@[to_additive] +lemma smul_finset_insert (a : α) (b : β) (s : Finset β) : a • insert b s = insert (a • b) (a • s) := + image_insert .. + @[to_additive] theorem smul_finset_inter_subset : a • (s₁ ∩ s₂) ⊆ a • s₁ ∩ a • s₂ := image_inter_subset _ _ _ diff --git a/Mathlib/Algebra/Group/Pointwise/Set.lean b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean similarity index 90% rename from Mathlib/Algebra/Group/Pointwise/Set.lean rename to Mathlib/Algebra/Group/Pointwise/Set/Basic.lean index a1ac52d71f441..bb8aba1b06f3a 100644 --- a/Mathlib/Algebra/Group/Pointwise/Set.lean +++ b/Mathlib/Algebra/Group/Pointwise/Set/Basic.lean @@ -181,10 +181,18 @@ theorem union_inv : (s ∪ t)⁻¹ = s⁻¹ ∪ t⁻¹ := theorem iInter_inv (s : ι → Set α) : (⋂ i, s i)⁻¹ = ⋂ i, (s i)⁻¹ := preimage_iInter +@[to_additive (attr := simp)] +theorem sInter_inv (S : Set (Set α)) : (⋂₀ S)⁻¹ = ⋂ s ∈ S, s⁻¹ := + preimage_sInter + @[to_additive (attr := simp)] theorem iUnion_inv (s : ι → Set α) : (⋃ i, s i)⁻¹ = ⋃ i, (s i)⁻¹ := preimage_iUnion +@[to_additive (attr := simp)] +theorem sUnion_inv (S : Set (Set α)) : (⋃₀ S)⁻¹ = ⋃ s ∈ S, s⁻¹ := + preimage_sUnion + @[to_additive (attr := simp)] theorem compl_inv : sᶜ⁻¹ = s⁻¹ᶜ := preimage_compl @@ -236,7 +244,7 @@ theorem inv_insert (a : α) (s : Set α) : (insert a s)⁻¹ = insert a⁻¹ s @[to_additive] theorem inv_range {ι : Sort*} {f : ι → α} : (range f)⁻¹ = range fun i => (f i)⁻¹ := by rw [← image_inv] - exact (range_comp _ _).symm + exact (range_comp ..).symm open MulOpposite @@ -324,7 +332,7 @@ theorem singleton_mul : {a} * t = (a * ·) '' t := theorem singleton_mul_singleton : ({a} : Set α) * {b} = {a * b} := image2_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem mul_subset_mul : s₁ ⊆ t₁ → s₂ ⊆ t₂ → s₁ * s₂ ⊆ t₁ * t₂ := image2_subset @@ -374,47 +382,63 @@ theorem iUnion_mul_right_image : ⋃ a ∈ t, (· * a) '' s = s * t := @[to_additive] theorem iUnion_mul (s : ι → Set α) (t : Set α) : (⋃ i, s i) * t = ⋃ i, s i * t := - image2_iUnion_left _ _ _ + image2_iUnion_left .. @[to_additive] theorem mul_iUnion (s : Set α) (t : ι → Set α) : (s * ⋃ i, t i) = ⋃ i, s * t i := - image2_iUnion_right _ _ _ + image2_iUnion_right .. + +@[to_additive] +theorem sUnion_mul (S : Set (Set α)) (t : Set α) : ⋃₀ S * t = ⋃ s ∈ S, s * t := + image2_sUnion_left .. + +@[to_additive] +theorem mul_sUnion (s : Set α) (T : Set (Set α)) : s * ⋃₀ T = ⋃ t ∈ T, s * t := + image2_sUnion_right .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem iUnion₂_mul (s : ∀ i, κ i → Set α) (t : Set α) : (⋃ (i) (j), s i j) * t = ⋃ (i) (j), s i j * t := - image2_iUnion₂_left _ _ _ + image2_iUnion₂_left .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem mul_iUnion₂ (s : Set α) (t : ∀ i, κ i → Set α) : (s * ⋃ (i) (j), t i j) = ⋃ (i) (j), s * t i j := - image2_iUnion₂_right _ _ _ + image2_iUnion₂_right .. @[to_additive] theorem iInter_mul_subset (s : ι → Set α) (t : Set α) : (⋂ i, s i) * t ⊆ ⋂ i, s i * t := - Set.image2_iInter_subset_left _ _ _ + Set.image2_iInter_subset_left .. @[to_additive] theorem mul_iInter_subset (s : Set α) (t : ι → Set α) : (s * ⋂ i, t i) ⊆ ⋂ i, s * t i := - image2_iInter_subset_right _ _ _ + image2_iInter_subset_right .. + +@[to_additive] +lemma mul_sInter_subset (s : Set α) (T : Set (Set α)) : + s * ⋂₀ T ⊆ ⋂ t ∈ T, s * t := image2_sInter_right_subset s T (fun a b => a * b) + +@[to_additive] +lemma sInter_mul_subset (S : Set (Set α)) (t : Set α) : + ⋂₀ S * t ⊆ ⋂ s ∈ S, s * t := image2_sInter_left_subset S t (fun a b => a * b) /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem iInter₂_mul_subset (s : ∀ i, κ i → Set α) (t : Set α) : (⋂ (i) (j), s i j) * t ⊆ ⋂ (i) (j), s i j * t := - image2_iInter₂_subset_left _ _ _ + image2_iInter₂_subset_left .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem mul_iInter₂_subset (s : Set α) (t : ∀ i, κ i → Set α) : (s * ⋂ (i) (j), t i j) ⊆ ⋂ (i) (j), s * t i j := - image2_iInter₂_subset_right _ _ _ + image2_iInter₂_subset_right .. /-- The singleton operation as a `MulHom`. -/ @[to_additive "The singleton operation as an `AddHom`."] @@ -512,7 +536,7 @@ theorem singleton_div : {a} / t = (· / ·) a '' t := theorem singleton_div_singleton : ({a} : Set α) / {b} = {a / b} := image2_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] theorem div_subset_div : s₁ ⊆ t₁ → s₂ ⊆ t₂ → s₁ / s₂ ⊆ t₁ / t₂ := image2_subset @@ -562,47 +586,63 @@ theorem iUnion_div_right_image : ⋃ a ∈ t, (· / a) '' s = s / t := @[to_additive] theorem iUnion_div (s : ι → Set α) (t : Set α) : (⋃ i, s i) / t = ⋃ i, s i / t := - image2_iUnion_left _ _ _ + image2_iUnion_left .. @[to_additive] theorem div_iUnion (s : Set α) (t : ι → Set α) : (s / ⋃ i, t i) = ⋃ i, s / t i := - image2_iUnion_right _ _ _ + image2_iUnion_right .. + +@[to_additive] +theorem sUnion_div (S : Set (Set α)) (t : Set α) : ⋃₀ S / t = ⋃ s ∈ S, s / t := + image2_sUnion_left .. + +@[to_additive] +theorem div_sUnion (s : Set α) (T : Set (Set α)) : s / ⋃₀ T = ⋃ t ∈ T, s / t := + image2_sUnion_right .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem iUnion₂_div (s : ∀ i, κ i → Set α) (t : Set α) : (⋃ (i) (j), s i j) / t = ⋃ (i) (j), s i j / t := - image2_iUnion₂_left _ _ _ + image2_iUnion₂_left .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem div_iUnion₂ (s : Set α) (t : ∀ i, κ i → Set α) : (s / ⋃ (i) (j), t i j) = ⋃ (i) (j), s / t i j := - image2_iUnion₂_right _ _ _ + image2_iUnion₂_right .. @[to_additive] theorem iInter_div_subset (s : ι → Set α) (t : Set α) : (⋂ i, s i) / t ⊆ ⋂ i, s i / t := - image2_iInter_subset_left _ _ _ + image2_iInter_subset_left .. @[to_additive] theorem div_iInter_subset (s : Set α) (t : ι → Set α) : (s / ⋂ i, t i) ⊆ ⋂ i, s / t i := - image2_iInter_subset_right _ _ _ + image2_iInter_subset_right .. + +@[to_additive] +theorem sInter_div_subset (S : Set (Set α)) (t : Set α) : ⋂₀ S / t ⊆ ⋂ s ∈ S, s / t := + image2_sInter_subset_left .. + +@[to_additive] +theorem div_sInter_subset (s : Set α) (T : Set (Set α)) : s / ⋂₀ T ⊆ ⋂ t ∈ T, s / t := + image2_sInter_subset_right .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem iInter₂_div_subset (s : ∀ i, κ i → Set α) (t : Set α) : (⋂ (i) (j), s i j) / t ⊆ ⋂ (i) (j), s i j / t := - image2_iInter₂_subset_left _ _ _ + image2_iInter₂_subset_left .. /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ @[to_additive] theorem div_iInter₂_subset (s : Set α) (t : ∀ i, κ i → Set α) : (s / ⋂ (i) (j), t i j) ⊆ ⋂ (i) (j), s / t i j := - image2_iInter₂_subset_right _ _ _ + image2_iInter₂_subset_right .. end Div @@ -659,7 +699,7 @@ lemma singleton_smul : ({a} : Set α) • t = a • t := image2_singleton_left @[to_additive (attr := simp high)] lemma singleton_smul_singleton : ({a} : Set α) • ({b} : Set β) = {a • b} := image2_singleton -@[to_additive (attr := mono)] +@[to_additive (attr := mono, gcongr)] lemma smul_subset_smul : s₁ ⊆ s₂ → t₁ ⊆ t₂ → s₁ • t₁ ⊆ s₂ • t₂ := image2_subset @[to_additive] lemma smul_subset_smul_left : t₁ ⊆ t₂ → s • t₁ ⊆ s • t₂ := image2_subset_left @@ -691,35 +731,51 @@ lemma iUnion_smul_right_image : ⋃ a ∈ t, (· • a) '' s = s • t := iUnion @[to_additive] lemma iUnion_smul (s : ι → Set α) (t : Set β) : (⋃ i, s i) • t = ⋃ i, s i • t := - image2_iUnion_left _ _ _ + image2_iUnion_left .. @[to_additive] lemma smul_iUnion (s : Set α) (t : ι → Set β) : (s • ⋃ i, t i) = ⋃ i, s • t i := - image2_iUnion_right _ _ _ + image2_iUnion_right .. + +@[to_additive] +lemma sUnion_smul (S : Set (Set α)) (t : Set β) : ⋃₀ S • t = ⋃ s ∈ S, s • t := + image2_sUnion_left .. + +@[to_additive] +lemma smul_sUnion (s : Set α) (T : Set (Set β)) : s • ⋃₀ T = ⋃ t ∈ T, s • t := + image2_sUnion_right .. @[to_additive] lemma iUnion₂_smul (s : ∀ i, κ i → Set α) (t : Set β) : - (⋃ i, ⋃ j, s i j) • t = ⋃ i, ⋃ j, s i j • t := image2_iUnion₂_left _ _ _ + (⋃ i, ⋃ j, s i j) • t = ⋃ i, ⋃ j, s i j • t := image2_iUnion₂_left .. @[to_additive] lemma smul_iUnion₂ (s : Set α) (t : ∀ i, κ i → Set β) : - (s • ⋃ i, ⋃ j, t i j) = ⋃ i, ⋃ j, s • t i j := image2_iUnion₂_right _ _ _ + (s • ⋃ i, ⋃ j, t i j) = ⋃ i, ⋃ j, s • t i j := image2_iUnion₂_right .. @[to_additive] lemma iInter_smul_subset (s : ι → Set α) (t : Set β) : (⋂ i, s i) • t ⊆ ⋂ i, s i • t := - image2_iInter_subset_left _ _ _ + image2_iInter_subset_left .. @[to_additive] lemma smul_iInter_subset (s : Set α) (t : ι → Set β) : (s • ⋂ i, t i) ⊆ ⋂ i, s • t i := - image2_iInter_subset_right _ _ _ + image2_iInter_subset_right .. + +@[to_additive] +lemma sInter_smul_subset (S : Set (Set α)) (t : Set β) : ⋂₀ S • t ⊆ ⋂ s ∈ S, s • t := + image2_sInter_left_subset S t (fun a x => a • x) + +@[to_additive] +lemma smul_sInter_subset (s : Set α) (T : Set (Set β)) : s • ⋂₀ T ⊆ ⋂ t ∈ T, s • t := + image2_sInter_right_subset s T (fun a x => a • x) @[to_additive] lemma iInter₂_smul_subset (s : ∀ i, κ i → Set α) (t : Set β) : - (⋂ i, ⋂ j, s i j) • t ⊆ ⋂ i, ⋂ j, s i j • t := image2_iInter₂_subset_left _ _ _ + (⋂ i, ⋂ j, s i j) • t ⊆ ⋂ i, ⋂ j, s i j • t := image2_iInter₂_subset_left .. @[to_additive] lemma smul_iInter₂_subset (s : Set α) (t : ∀ i, κ i → Set β) : - (s • ⋂ i, ⋂ j, t i j) ⊆ ⋂ i, ⋂ j, s • t i j := image2_iInter₂_subset_right _ _ _ + (s • ⋂ i, ⋂ j, t i j) ⊆ ⋂ i, ⋂ j, s • t i j := image2_iInter₂_subset_right .. @[to_additive] lemma smul_set_subset_smul {s : Set α} : a ∈ s → a • t ⊆ s • t := image_subset_image2_right @@ -749,9 +805,7 @@ lemma smul_set_nonempty : (a • s).Nonempty ↔ s.Nonempty := image_nonempty @[to_additive (attr := simp)] lemma smul_set_singleton : a • ({b} : Set β) = {a • b} := image_singleton -@[to_additive] -lemma smul_set_mono : s ⊆ t → a • s ⊆ a • t := - image_subset _ +@[to_additive (attr := gcongr)] lemma smul_set_mono : s ⊆ t → a • s ⊆ a • t := image_subset _ @[to_additive] lemma smul_set_subset_iff : a • s ⊆ t ↔ ∀ ⦃b⦄, b ∈ s → a • b ∈ t := @@ -759,11 +813,15 @@ lemma smul_set_subset_iff : a • s ⊆ t ↔ ∀ ⦃b⦄, b ∈ s → a • b @[to_additive] lemma smul_set_union : a • (t₁ ∪ t₂) = a • t₁ ∪ a • t₂ := - image_union _ _ _ + image_union .. + +@[to_additive] +lemma smul_set_insert (a : α) (b : β) (s : Set β) : a • insert b s = insert (a • b) (a • s) := + image_insert_eq .. @[to_additive] lemma smul_set_inter_subset : a • (t₁ ∩ t₂) ⊆ a • t₁ ∩ a • t₂ := - image_inter_subset _ _ _ + image_inter_subset .. @[to_additive] lemma smul_set_iUnion (a : α) (s : ι → Set β) : a • ⋃ i, s i = ⋃ i, a • s i := @@ -771,15 +829,23 @@ lemma smul_set_iUnion (a : α) (s : ι → Set β) : a • ⋃ i, s i = ⋃ i, a @[to_additive] lemma smul_set_iUnion₂ (a : α) (s : ∀ i, κ i → Set β) : - a • ⋃ i, ⋃ j, s i j = ⋃ i, ⋃ j, a • s i j := image_iUnion₂ _ _ + a • ⋃ i, ⋃ j, s i j = ⋃ i, ⋃ j, a • s i j := image_iUnion₂ .. + +@[to_additive] +lemma smul_set_sUnion (a : α) (S : Set (Set β)) : a • ⋃₀ S = ⋃ s ∈ S, a • s := by + rw [sUnion_eq_biUnion, smul_set_iUnion₂] @[to_additive] lemma smul_set_iInter_subset (a : α) (t : ι → Set β) : a • ⋂ i, t i ⊆ ⋂ i, a • t i := - image_iInter_subset _ _ + image_iInter_subset .. + +@[to_additive] +lemma smul_set_sInter_subset (a : α) (S : Set (Set β)) : + a • ⋂₀ S ⊆ ⋂ s ∈ S, a • s := image_sInter_subset .. @[to_additive] lemma smul_set_iInter₂_subset (a : α) (t : ∀ i, κ i → Set β) : - a • ⋂ i, ⋂ j, t i j ⊆ ⋂ i, ⋂ j, a • t i j := image_iInter₂_subset _ _ + a • ⋂ i, ⋂ j, t i j ⊆ ⋂ i, ⋂ j, a • t i j := image_iInter₂_subset .. @[to_additive] lemma Nonempty.smul_set : s.Nonempty → (a • s).Nonempty := Nonempty.image _ @@ -795,7 +861,7 @@ lemma range_smul_range {ι κ : Type*} [SMul α β] (b : ι → α) (c : κ → @[to_additive] lemma smul_set_range [SMul α β] {ι : Sort*} (a : α) (f : ι → β) : a • range f = range fun i ↦ a • f i := - (range_comp _ _).symm + (range_comp ..).symm @[to_additive] lemma range_smul [SMul α β] {ι : Sort*} (a : α) (f : ι → β) : range (fun i ↦ a • f i) = a • range f := (smul_set_range ..).symm @@ -861,28 +927,40 @@ lemma iUnion_vsub_left_image : ⋃ a ∈ s, (a -ᵥ ·) '' t = s -ᵥ t := iUnio lemma iUnion_vsub_right_image : ⋃ a ∈ t, (· -ᵥ a) '' s = s -ᵥ t := iUnion_image_right _ lemma iUnion_vsub (s : ι → Set β) (t : Set β) : (⋃ i, s i) -ᵥ t = ⋃ i, s i -ᵥ t := - image2_iUnion_left _ _ _ + image2_iUnion_left .. lemma vsub_iUnion (s : Set β) (t : ι → Set β) : (s -ᵥ ⋃ i, t i) = ⋃ i, s -ᵥ t i := - image2_iUnion_right _ _ _ + image2_iUnion_right .. + +lemma sUnion_vsub (S : Set (Set β)) (t : Set β) : ⋃₀ S -ᵥ t = ⋃ s ∈ S, s -ᵥ t := + image2_sUnion_left .. + +lemma vsub_sUnion (s : Set β) (T : Set (Set β)) : s -ᵥ ⋃₀ T = ⋃ t ∈ T, s -ᵥ t := + image2_sUnion_right .. lemma iUnion₂_vsub (s : ∀ i, κ i → Set β) (t : Set β) : - (⋃ i, ⋃ j, s i j) -ᵥ t = ⋃ i, ⋃ j, s i j -ᵥ t := image2_iUnion₂_left _ _ _ + (⋃ i, ⋃ j, s i j) -ᵥ t = ⋃ i, ⋃ j, s i j -ᵥ t := image2_iUnion₂_left .. lemma vsub_iUnion₂ (s : Set β) (t : ∀ i, κ i → Set β) : - (s -ᵥ ⋃ i, ⋃ j, t i j) = ⋃ i, ⋃ j, s -ᵥ t i j := image2_iUnion₂_right _ _ _ + (s -ᵥ ⋃ i, ⋃ j, t i j) = ⋃ i, ⋃ j, s -ᵥ t i j := image2_iUnion₂_right .. lemma iInter_vsub_subset (s : ι → Set β) (t : Set β) : (⋂ i, s i) -ᵥ t ⊆ ⋂ i, s i -ᵥ t := - image2_iInter_subset_left _ _ _ + image2_iInter_subset_left .. lemma vsub_iInter_subset (s : Set β) (t : ι → Set β) : (s -ᵥ ⋂ i, t i) ⊆ ⋂ i, s -ᵥ t i := - image2_iInter_subset_right _ _ _ + image2_iInter_subset_right .. + +lemma sInter_vsub_subset (S : Set (Set β)) (t : Set β) : ⋂₀ S -ᵥ t ⊆ ⋂ s ∈ S, s -ᵥ t := + image2_sInter_subset_left .. + +lemma vsub_sInter_subset (s : Set β) (T : Set (Set β)) : s -ᵥ ⋂₀ T ⊆ ⋂ t ∈ T, s -ᵥ t := + image2_sInter_subset_right .. lemma iInter₂_vsub_subset (s : ∀ i, κ i → Set β) (t : Set β) : - (⋂ i, ⋂ j, s i j) -ᵥ t ⊆ ⋂ i, ⋂ j, s i j -ᵥ t := image2_iInter₂_subset_left _ _ _ + (⋂ i, ⋂ j, s i j) -ᵥ t ⊆ ⋂ i, ⋂ j, s i j -ᵥ t := image2_iInter₂_subset_left .. lemma vsub_iInter₂_subset (s : Set β) (t : ∀ i, κ i → Set β) : - s -ᵥ ⋂ i, ⋂ j, t i j ⊆ ⋂ i, ⋂ j, s -ᵥ t i j := image2_iInter₂_subset_right _ _ _ + s -ᵥ ⋂ i, ⋂ j, t i j ⊆ ⋂ i, ⋂ j, s -ᵥ t i j := image2_iInter₂_subset_right .. end VSub @@ -1107,6 +1185,12 @@ theorem isUnit_iff : IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a := by @[to_additive (attr := simp)] lemma univ_div_univ : (univ / univ : Set α) = univ := by simp [div_eq_mul_inv] +@[to_additive] lemma subset_div_left (ht : 1 ∈ t) : s ⊆ s / t := by + rw [div_eq_mul_inv]; exact subset_mul_left _ <| by simpa + +@[to_additive] lemma inv_subset_div_right (hs : 1 ∈ s) : t⁻¹ ⊆ s / t := by + rw [div_eq_mul_inv]; exact subset_mul_right _ hs + end DivisionMonoid /-- `Set α` is a commutative division monoid under pointwise operations if `α` is. -/ @@ -1116,6 +1200,8 @@ protected noncomputable def divisionCommMonoid [DivisionCommMonoid α] : DivisionCommMonoid (Set α) := { Set.divisionMonoid, Set.commSemigroup with } +scoped[Pointwise] attribute [instance] Set.divisionCommMonoid Set.subtractionCommMonoid + section Group variable [Group α] {s t : Set α} {a b : α} @@ -1187,12 +1273,12 @@ theorem preimage_mul_right_one' : (· * b⁻¹) ⁻¹' 1 = {b} := by simp @[to_additive (attr := simp)] theorem mul_univ (hs : s.Nonempty) : s * (univ : Set α) = univ := let ⟨a, ha⟩ := hs - eq_univ_of_forall fun b => ⟨a, ha, a⁻¹ * b, trivial, mul_inv_cancel_left _ _⟩ + eq_univ_of_forall fun b => ⟨a, ha, a⁻¹ * b, trivial, mul_inv_cancel_left ..⟩ @[to_additive (attr := simp)] theorem univ_mul (ht : t.Nonempty) : (univ : Set α) * t = univ := let ⟨a, ha⟩ := ht - eq_univ_of_forall fun b => ⟨b * a⁻¹, trivial, a, ha, inv_mul_cancel_right _ _⟩ + eq_univ_of_forall fun b => ⟨b * a⁻¹, trivial, a, ha, inv_mul_cancel_right ..⟩ end Group @@ -1209,12 +1295,12 @@ lemma mul_subset_range {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) rintro _ ⟨a, ha, b, hb, rfl⟩ obtain ⟨a, rfl⟩ := hs ha obtain ⟨b, rfl⟩ := ht hb - exact ⟨a * b, map_mul _ _ _⟩ + exact ⟨a * b, map_mul ..⟩ @[to_additive] theorem preimage_mul_preimage_subset {s t : Set β} : m ⁻¹' s * m ⁻¹' t ⊆ m ⁻¹' (s * t) := by rintro _ ⟨_, _, _, _, rfl⟩ - exact ⟨_, ‹_›, _, ‹_›, (map_mul m _ _).symm⟩ + exact ⟨_, ‹_›, _, ‹_›, (map_mul m ..).symm⟩ @[to_additive] lemma preimage_mul (hm : Injective m) {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) : @@ -1238,12 +1324,12 @@ lemma div_subset_range {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) rintro _ ⟨a, ha, b, hb, rfl⟩ obtain ⟨a, rfl⟩ := hs ha obtain ⟨b, rfl⟩ := ht hb - exact ⟨a / b, map_div _ _ _⟩ + exact ⟨a / b, map_div ..⟩ @[to_additive] theorem preimage_div_preimage_subset {s t : Set β} : m ⁻¹' s / m ⁻¹' t ⊆ m ⁻¹' (s / t) := by rintro _ ⟨_, _, _, _, rfl⟩ - exact ⟨_, ‹_›, _, ‹_›, (map_div m _ _).symm⟩ + exact ⟨_, ‹_›, _, ‹_›, (map_div m ..).symm⟩ @[to_additive] lemma preimage_div (hm : Injective m) {s t : Set β} (hs : s ⊆ range m) (ht : t ⊆ range m) : diff --git a/Mathlib/Algebra/Group/Pointwise/Finset/NatCard.lean b/Mathlib/Algebra/Group/Pointwise/Set/Card.lean similarity index 100% rename from Mathlib/Algebra/Group/Pointwise/Finset/NatCard.lean rename to Mathlib/Algebra/Group/Pointwise/Set/Card.lean diff --git a/Mathlib/Algebra/Group/Prod.lean b/Mathlib/Algebra/Group/Prod.lean index 5870914629f9a..d7cb9b0f80a16 100644 --- a/Mathlib/Algebra/Group/Prod.lean +++ b/Mathlib/Algebra/Group/Prod.lean @@ -34,7 +34,7 @@ assert_not_exists MonoidWithZero -- assert_not_exists AddMonoidWithOne assert_not_exists DenselyOrdered -variable {A : Type*} {B : Type*} {G : Type*} {H : Type*} {M : Type*} {N : Type*} {P : Type*} +variable {G : Type*} {H : Type*} {M : Type*} {N : Type*} {P : Type*} namespace Prod diff --git a/Mathlib/Algebra/Group/Semiconj/Defs.lean b/Mathlib/Algebra/Group/Semiconj/Defs.lean index 88ad2b00a8933..cfeabeb0d12db 100644 --- a/Mathlib/Algebra/Group/Semiconj/Defs.lean +++ b/Mathlib/Algebra/Group/Semiconj/Defs.lean @@ -115,7 +115,7 @@ end Monoid section Group -variable [Group G] {a x y : G} +variable [Group G] /-- `a` semiconjugates `x` to `a * x * a⁻¹`. -/ @[to_additive "`a` semiconjugates `x` to `a + x + -a`."] diff --git a/Mathlib/Algebra/Group/Semiconj/Units.lean b/Mathlib/Algebra/Group/Semiconj/Units.lean index b842e2c11bc3b..5a31a5e5130e9 100644 --- a/Mathlib/Algebra/Group/Semiconj/Units.lean +++ b/Mathlib/Algebra/Group/Semiconj/Units.lean @@ -32,7 +32,7 @@ assert_not_exists DenselyOrdered open scoped Int -variable {M G : Type*} +variable {M : Type*} namespace SemiconjBy diff --git a/Mathlib/Algebra/Group/Subgroup/Basic.lean b/Mathlib/Algebra/Group/Subgroup/Basic.lean index 0d13d5ae72a71..556df038ddca9 100644 --- a/Mathlib/Algebra/Group/Subgroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subgroup/Basic.lean @@ -69,7 +69,7 @@ Definitions in the file: * `MonoidHom.ker f` : the kernel of a group homomorphism `f` is the subgroup of elements `x : G` such that `f x = 1` -* `MonoidHom.eq_locus f g` : given group homomorphisms `f`, `g`, the elements of `G` such that +* `MonoidHom.eqLocus f g` : given group homomorphisms `f`, `g`, the elements of `G` such that `f x = g x` form a subgroup of `G` ## Implementation notes @@ -94,27 +94,27 @@ variable {A : Type*} [AddGroup A] section SubgroupClass /-- `InvMemClass S G` states `S` is a type of subsets `s ⊆ G` closed under inverses. -/ -class InvMemClass (S G : Type*) [Inv G] [SetLike S G] : Prop where +class InvMemClass (S : Type*) (G : outParam Type*) [Inv G] [SetLike S G] : Prop where /-- `s` is closed under inverses -/ inv_mem : ∀ {s : S} {x}, x ∈ s → x⁻¹ ∈ s export InvMemClass (inv_mem) /-- `NegMemClass S G` states `S` is a type of subsets `s ⊆ G` closed under negation. -/ -class NegMemClass (S G : Type*) [Neg G] [SetLike S G] : Prop where +class NegMemClass (S : Type*) (G : outParam Type*) [Neg G] [SetLike S G] : Prop where /-- `s` is closed under negation -/ neg_mem : ∀ {s : S} {x}, x ∈ s → -x ∈ s export NegMemClass (neg_mem) /-- `SubgroupClass S G` states `S` is a type of subsets `s ⊆ G` that are subgroups of `G`. -/ -class SubgroupClass (S G : Type*) [DivInvMonoid G] [SetLike S G] extends SubmonoidClass S G, - InvMemClass S G : Prop +class SubgroupClass (S : Type*) (G : outParam Type*) [DivInvMonoid G] [SetLike S G] + extends SubmonoidClass S G, InvMemClass S G : Prop /-- `AddSubgroupClass S G` states `S` is a type of subsets `s ⊆ G` that are additive subgroups of `G`. -/ -class AddSubgroupClass (S G : Type*) [SubNegMonoid G] [SetLike S G] extends AddSubmonoidClass S G, - NegMemClass S G : Prop +class AddSubgroupClass (S : Type*) (G : outParam Type*) [SubNegMonoid G] [SetLike S G] + extends AddSubmonoidClass S G, NegMemClass S G : Prop attribute [to_additive] InvMemClass SubgroupClass diff --git a/Mathlib/Algebra/Group/Subgroup/Finite.lean b/Mathlib/Algebra/Group/Subgroup/Finite.lean index b4dc8b267698d..6e5342a357f4e 100644 --- a/Mathlib/Algebra/Group/Subgroup/Finite.lean +++ b/Mathlib/Algebra/Group/Subgroup/Finite.lean @@ -165,9 +165,11 @@ theorem pi_mem_of_mulSingle_mem_aux [DecidableEq η] (I : Finset η) {H : Subgro x ∈ H := by induction I using Finset.induction_on generalizing x with | empty => - convert one_mem H - ext i - exact h1 i (Finset.not_mem_empty i) + have : x = 1 := by + ext i + exact h1 i (Finset.not_mem_empty i) + rw [this] + exact one_mem H | insert hnmem ih => rename_i i I have : x = Function.update x i 1 * Pi.mulSingle i (x i) := by diff --git a/Mathlib/Algebra/Group/Subgroup/Order.lean b/Mathlib/Algebra/Group/Subgroup/Order.lean index 0578e6adbde06..7e9cd2eefee49 100644 --- a/Mathlib/Algebra/Group/Subgroup/Order.lean +++ b/Mathlib/Algebra/Group/Subgroup/Order.lean @@ -21,7 +21,7 @@ theorem mabs_mem_iff {S G} [Group G] [LinearOrder G] {_ : SetLike S G} section ModularLattice -variable {C : Type*} [CommGroup C] {s t : Subgroup C} {x : C} +variable {C : Type*} [CommGroup C] @[to_additive] instance : IsModularLattice (Subgroup C) := diff --git a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean index 17dc2929357ae..99bb82ddad9cc 100644 --- a/Mathlib/Algebra/Group/Subgroup/Pointwise.lean +++ b/Mathlib/Algebra/Group/Subgroup/Pointwise.lean @@ -392,6 +392,13 @@ theorem Normal.conjAct {G : Type*} [Group G] {H : Subgroup G} (hH : H.Normal) (g theorem smul_normal (g : G) (H : Subgroup G) [h : Normal H] : MulAut.conj g • H = H := h.conjAct g +theorem normalCore_eq_iInf_conjAct (H : Subgroup G) : + H.normalCore = ⨅ (g : ConjAct G), g • H := by + ext g + simp only [Subgroup.normalCore, Subgroup.mem_iInf, Subgroup.mem_pointwise_smul_iff_inv_smul_mem] + refine ⟨fun h x ↦ h x⁻¹, fun h x ↦ ?_⟩ + simpa only [ConjAct.toConjAct_inv, inv_inv] using h x⁻¹ + end Group section GroupWithZero diff --git a/Mathlib/Algebra/Group/Submonoid/Basic.lean b/Mathlib/Algebra/Group/Submonoid/Basic.lean index ddb7f8577ed46..623c641fbcfa6 100644 --- a/Mathlib/Algebra/Group/Submonoid/Basic.lean +++ b/Mathlib/Algebra/Group/Submonoid/Basic.lean @@ -65,14 +65,14 @@ variable [MulOneClass M] {s : Set M} variable [AddZeroClass A] {t : Set A} /-- `OneMemClass S M` says `S` is a type of subsets `s ≤ M`, such that `1 ∈ s` for all `s`. -/ -class OneMemClass (S : Type*) (M : Type*) [One M] [SetLike S M] : Prop where +class OneMemClass (S : Type*) (M : outParam Type*) [One M] [SetLike S M] : Prop where /-- By definition, if we have `OneMemClass S M`, we have `1 ∈ s` for all `s : S`. -/ one_mem : ∀ s : S, (1 : M) ∈ s export OneMemClass (one_mem) /-- `ZeroMemClass S M` says `S` is a type of subsets `s ≤ M`, such that `0 ∈ s` for all `s`. -/ -class ZeroMemClass (S : Type*) (M : Type*) [Zero M] [SetLike S M] : Prop where +class ZeroMemClass (S : Type*) (M : outParam Type*) [Zero M] [SetLike S M] : Prop where /-- By definition, if we have `ZeroMemClass S M`, we have `0 ∈ s` for all `s : S`. -/ zero_mem : ∀ s : S, (0 : M) ∈ s @@ -96,7 +96,7 @@ add_decl_doc Submonoid.toSubsemigroup /-- `SubmonoidClass S M` says `S` is a type of subsets `s ≤ M` that contain `1` and are closed under `(*)` -/ -class SubmonoidClass (S : Type*) (M : Type*) [MulOneClass M] [SetLike S M] extends +class SubmonoidClass (S : Type*) (M : outParam Type*) [MulOneClass M] [SetLike S M] extends MulMemClass S M, OneMemClass S M : Prop section @@ -115,7 +115,7 @@ add_decl_doc AddSubmonoid.toAddSubsemigroup /-- `AddSubmonoidClass S M` says `S` is a type of subsets `s ≤ M` that contain `0` and are closed under `(+)` -/ -class AddSubmonoidClass (S : Type*) (M : Type*) [AddZeroClass M] [SetLike S M] extends +class AddSubmonoidClass (S : Type*) (M : outParam Type*) [AddZeroClass M] [SetLike S M] extends AddMemClass S M, ZeroMemClass S M : Prop attribute [to_additive] Submonoid SubmonoidClass diff --git a/Mathlib/Algebra/Group/Submonoid/Membership.lean b/Mathlib/Algebra/Group/Submonoid/Membership.lean index e1ec1fb022a46..3f5261db6d422 100644 --- a/Mathlib/Algebra/Group/Submonoid/Membership.lean +++ b/Mathlib/Algebra/Group/Submonoid/Membership.lean @@ -440,7 +440,7 @@ abbrev groupPowers {x : M} {n : ℕ} (hpos : 0 < n) (hx : x ^ n = 1) : Group (po ← pow_eq_pow_mod _ hx, pow_mul, pow_mul] zpow_succ' m x := Subtype.ext <| by obtain ⟨_, k, rfl⟩ := x - simp only [← pow_mul, Int.natMod, Int.ofNat_eq_coe, SubmonoidClass.coe_pow, coe_mul] + simp only [← pow_mul, Int.natMod, SubmonoidClass.coe_pow, coe_mul] norm_cast iterate 2 rw [Int.toNat_natCast, mul_comm, pow_mul, ← pow_eq_pow_mod _ hx] rw [← pow_mul _ m, mul_comm, pow_mul, ← pow_succ, ← pow_mul, mul_comm, pow_mul] diff --git a/Mathlib/Algebra/Group/Submonoid/Operations.lean b/Mathlib/Algebra/Group/Submonoid/Operations.lean index 1bf4b67f90258..f84160423a5b5 100644 --- a/Mathlib/Algebra/Group/Submonoid/Operations.lean +++ b/Mathlib/Algebra/Group/Submonoid/Operations.lean @@ -591,7 +591,7 @@ theorem closure_closure_coe_preimage {s : Set M} : closure (((↑) : closure s Subtype.recOn x fun x hx _ => by refine closure_induction' (p := fun y hy ↦ (⟨y, hy⟩ : closure s) ∈ closure (((↑) : closure s → M) ⁻¹' s)) - (fun g hg => subset_closure hg) ?_ (fun g₁ g₂ hg₁ hg₂ => ?_) hx + _ (fun g hg => subset_closure hg) ?_ (fun g₁ g₂ hg₁ hg₂ => ?_) hx · exact Submonoid.one_mem _ · exact Submonoid.mul_mem _ diff --git a/Mathlib/Algebra/Group/Subsemigroup/Basic.lean b/Mathlib/Algebra/Group/Subsemigroup/Basic.lean index 88cda9b9d5583..c5801a38f6bdb 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Basic.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Basic.lean @@ -57,14 +57,14 @@ variable [Mul M] {s : Set M} variable [Add A] {t : Set A} /-- `MulMemClass S M` says `S` is a type of sets `s : Set M` that are closed under `(*)` -/ -class MulMemClass (S : Type*) (M : Type*) [Mul M] [SetLike S M] : Prop where +class MulMemClass (S : Type*) (M : outParam Type*) [Mul M] [SetLike S M] : Prop where /-- A substructure satisfying `MulMemClass` is closed under multiplication. -/ mul_mem : ∀ {s : S} {a b : M}, a ∈ s → b ∈ s → a * b ∈ s export MulMemClass (mul_mem) /-- `AddMemClass S M` says `S` is a type of sets `s : Set M` that are closed under `(+)` -/ -class AddMemClass (S : Type*) (M : Type*) [Add M] [SetLike S M] : Prop where +class AddMemClass (S : Type*) (M : outParam Type*) [Add M] [SetLike S M] : Prop where /-- A substructure satisfying `AddMemClass` is closed under addition. -/ add_mem : ∀ {s : S} {a b : M}, a ∈ s → b ∈ s → a + b ∈ s diff --git a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean index 05de353785319..85f523619d7ca 100644 --- a/Mathlib/Algebra/Group/Subsemigroup/Operations.lean +++ b/Mathlib/Algebra/Group/Subsemigroup/Operations.lean @@ -501,7 +501,7 @@ theorem closure_closure_coe_preimage {s : Set M} : eq_top_iff.2 fun x => Subtype.recOn x fun _ hx' _ => closure_induction' (p := fun y hy ↦ (⟨y, hy⟩ : closure s) ∈ closure (((↑) : closure s → M) ⁻¹' s)) - (fun _ hg => subset_closure hg) (fun _ _ _ _ => Subsemigroup.mul_mem _) hx' + _ (fun _ hg => subset_closure hg) (fun _ _ _ _ => Subsemigroup.mul_mem _) hx' /-- Given `Subsemigroup`s `s`, `t` of semigroups `M`, `N` respectively, `s × t` as a subsemigroup of `M × N`. -/ diff --git a/Mathlib/Algebra/Group/UniqueProds/Basic.lean b/Mathlib/Algebra/Group/UniqueProds/Basic.lean index c243d2138661e..99d252eee8364 100644 --- a/Mathlib/Algebra/Group/UniqueProds/Basic.lean +++ b/Mathlib/Algebra/Group/UniqueProds/Basic.lean @@ -70,13 +70,16 @@ variable {G H : Type*} [Mul G] [Mul H] {A B : Finset G} {a0 b0 : G} theorem of_subsingleton [Subsingleton G] : UniqueMul A B a0 b0 := by simp [UniqueMul, eq_iff_true_of_subsingleton] -@[to_additive] +@[to_additive of_card_le_one] theorem of_card_le_one (hA : A.Nonempty) (hB : B.Nonempty) (hA1 : A.card ≤ 1) (hB1 : B.card ≤ 1) : ∃ a ∈ A, ∃ b ∈ B, UniqueMul A B a b := by rw [Finset.card_le_one_iff] at hA1 hB1 obtain ⟨a, ha⟩ := hA; obtain ⟨b, hb⟩ := hB exact ⟨a, ha, b, hb, fun _ _ ha' hb' _ ↦ ⟨hA1 ha' ha, hB1 hb' hb⟩⟩ +@[deprecated (since := "2024-09-23")] +alias _root_.UniqueAdd.of_card_nonpos := UniqueAdd.of_card_le_one + @[to_additive] theorem mt (h : UniqueMul A B a0 b0) : ∀ ⦃a b⦄, a ∈ A → b ∈ B → a ≠ a0 ∨ b ≠ b0 → a * b ≠ a0 * b0 := fun _ _ ha hb k ↦ by @@ -113,7 +116,7 @@ theorem iff_existsUnique (aA : a0 ∈ A) (bB : b0 ∈ B) : exact Prod.mk.inj_iff.mp (J (x, y) ⟨Finset.mk_mem_product hx hy, l⟩))⟩ open Finset in -@[to_additive] +@[to_additive iff_card_le_one] theorem iff_card_le_one [DecidableEq G] (ha0 : a0 ∈ A) (hb0 : b0 ∈ B) : UniqueMul A B a0 b0 ↔ ((A ×ˢ B).filter (fun p ↦ p.1 * p.2 = a0 * b0)).card ≤ 1 := by simp_rw [card_le_one_iff, mem_filter, mem_product] @@ -124,6 +127,9 @@ theorem iff_card_le_one [DecidableEq G] (ha0 : a0 ∈ A) (hb0 : b0 ∈ B) : · rw [h1.2, h2.2] · exact Prod.ext_iff.1 (@h (a, b) (a0, b0) ⟨⟨ha, hb⟩, he⟩ ⟨⟨ha0, hb0⟩, rfl⟩) +@[deprecated (since := "2024-09-23")] +alias _root_.UniqueAdd.iff_card_nonpos := UniqueAdd.iff_card_le_one + -- Porting note: mathport warning: expanding binder collection -- (ab «expr ∈ » [finset.product/multiset.product/set.prod/list.product](A, B)) -/ @[to_additive] diff --git a/Mathlib/Algebra/Group/Units.lean b/Mathlib/Algebra/Group/Units.lean index a42617a760e41..1c93daf4e3123 100644 --- a/Mathlib/Algebra/Group/Units.lean +++ b/Mathlib/Algebra/Group/Units.lean @@ -379,7 +379,7 @@ theorem Units.val_mkOfMulEqOne [CommMonoid α] {a b : α} (h : a * b = 1) : section Monoid -variable [Monoid α] {a b c : α} +variable [Monoid α] {a : α} /-- Partial division. It is defined when the second argument is invertible, and unlike the division operator @@ -651,9 +651,9 @@ lemma IsUnit.exists_left_inv {a : M} (h : IsUnit a) : ∃ b, b * a = 1 := by @[to_additive] lemma IsUnit.pow (n : ℕ) : IsUnit a → IsUnit (a ^ n) := by rintro ⟨u, rfl⟩; exact ⟨u ^ n, rfl⟩ -theorem units_eq_one [Unique Mˣ] (u : Mˣ) : u = 1 := by subsingleton +theorem units_eq_one [Subsingleton Mˣ] (u : Mˣ) : u = 1 := by subsingleton -@[to_additive] lemma isUnit_iff_eq_one [Unique Mˣ] {x : M} : IsUnit x ↔ x = 1 := +@[to_additive] lemma isUnit_iff_eq_one [Subsingleton 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 diff --git a/Mathlib/Algebra/Group/Units/Equiv.lean b/Mathlib/Algebra/Group/Units/Equiv.lean index a3ae5f7904381..12d6fb5b2285c 100644 --- a/Mathlib/Algebra/Group/Units/Equiv.lean +++ b/Mathlib/Algebra/Group/Units/Equiv.lean @@ -13,7 +13,7 @@ import Mathlib.Algebra.Group.Units.Hom assert_not_exists MonoidWithZero assert_not_exists DenselyOrdered -variable {F α β A B M N P Q G H : Type*} +variable {F α M N G : Type*} /-- A group is isomorphic to its group of units. -/ @[to_additive (attr := simps apply_val symm_apply) @@ -31,7 +31,7 @@ lemma toUnits_val_apply {G : Type*} [Group G] (x : Gˣ) : toUnits (x : G) = x := namespace Units -variable [Monoid M] [Monoid N] [Monoid P] +variable [Monoid M] [Monoid N] /-- A multiplicative equivalence of monoids defines a multiplicative equivalence of their groups of units. -/ @@ -192,11 +192,10 @@ def MulEquiv.inv (G : Type*) [DivisionCommMonoid G] : G ≃* G := theorem MulEquiv.inv_symm (G : Type*) [DivisionCommMonoid G] : (MulEquiv.inv G).symm = MulEquiv.inv G := rfl --- Porting note: no `add_equiv.neg_symm` in `mathlib3` -@[to_additive] -protected -theorem MulEquiv.map_isUnit_iff {M N} [Monoid M] [Monoid N] [EquivLike F M N] [MonoidHomClass F M N] - (f : F) {m : M} : IsUnit (f m) ↔ IsUnit m := - isUnit_map_of_leftInverse (MonoidHom.inverse (f : M →* N) (EquivLike.inv f) - (EquivLike.left_inv f) <| EquivLike.right_inv f) (EquivLike.left_inv f) +instance isLocalRingHom_equiv [Monoid M] [Monoid N] [EquivLike F M N] + [MulEquivClass F M N] (f : F) : IsLocalRingHom f where + map_nonunit a ha := by + convert ha.map (f : M ≃* N).symm + rw [MulEquiv.eq_symm_apply] + rfl -- note to reviewers: ugly `rfl` diff --git a/Mathlib/Algebra/Group/Units/Hom.lean b/Mathlib/Algebra/Group/Units/Hom.lean index 1a84f0441934c..09f626ae87904 100644 --- a/Mathlib/Algebra/Group/Units/Hom.lean +++ b/Mathlib/Algebra/Group/Units/Hom.lean @@ -17,6 +17,18 @@ 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 `βˣ`. +* `IsLocalRingHom`: A predicate on monoid maps, requiring that it maps nonunits + to nonunits. For local rings, this means that the image of the unique maximal ideal is again + contained in the unique maximal ideal. This is developed earlier, and in the generality of + monoids, as it allows its use in non-local-ring related contexts, but it does have the + strange consequence that it does not require local rings, or even rings. + +## 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. + +Add a `@[to_additive]` version of `IsLocalRingHom`. -/ assert_not_exists MonoidWithZero @@ -152,7 +164,7 @@ end MonoidHom namespace IsUnit -variable {F G α M N : Type*} [FunLike F M N] [FunLike G N M] +variable {F G M N : Type*} [FunLike F M N] [FunLike G N M] section Monoid @@ -167,6 +179,7 @@ theorem of_leftInverse [MonoidHomClass G N M] {f : F} {x : M} (g : G) (hfg : Function.LeftInverse g f) (h : IsUnit (f x)) : IsUnit x := by simpa only [hfg x] using h.map g +/-- Prefer `IsLocalRingHom.of_leftInverse`, but we can't get rid of this because of `ToAdditive`. -/ @[to_additive] theorem _root_.isUnit_map_of_leftInverse [MonoidHomClass F M N] [MonoidHomClass G N M] {f : F} {x : M} (g : G) (hfg : Function.LeftInverse g f) : @@ -194,3 +207,49 @@ theorem liftRight_inv_mul (f : M →* N) (h : ∀ x, IsUnit (f x)) (x) : end Monoid end IsUnit + +section IsLocalRingHom + +variable {G R S T F : Type*} + +variable [Monoid R] [Monoid S] [Monoid T] [FunLike F R S] + +/-- A local ring homomorphism is a map `f` between monoids such that `a` in the domain + is a unit if `f a` is a unit for any `a`. See `LocalRing.local_hom_TFAE` for other equivalent + definitions in the local ring case - from where this concept originates, but it is useful in + other contexts, so we allow this generalisation in mathlib. -/ +class IsLocalRingHom (f : F) : Prop where + /-- A local ring homomorphism `f : R ⟶ S` will send nonunits of `R` to nonunits of `S`. -/ + map_nonunit : ∀ a, IsUnit (f a) → IsUnit a + +@[simp] +theorem IsUnit.of_map (f : F) [IsLocalRingHom f] (a : R) (h : IsUnit (f a)) : IsUnit a := + IsLocalRingHom.map_nonunit a h + +-- TODO : remove alias, change the parenthesis of `f` and `a` +alias isUnit_of_map_unit := IsUnit.of_map + +variable [MonoidHomClass F R S] + +@[simp] +theorem isUnit_map_iff (f : F) [IsLocalRingHom f] (a : R) : IsUnit (f a) ↔ IsUnit a := + ⟨IsLocalRingHom.map_nonunit a, IsUnit.map f⟩ + +theorem isLocalRingHom_of_leftInverse [FunLike G S R] [MonoidHomClass G S R] + {f : F} (g : G) (hfg : Function.LeftInverse g f) : IsLocalRingHom f where + map_nonunit a ha := by rwa [isUnit_map_of_leftInverse g hfg] at ha + +instance MonoidHom.isLocalRingHom_comp (g : S →* T) (f : R →* S) [IsLocalRingHom g] + [IsLocalRingHom f] : IsLocalRingHom (g.comp f) where + map_nonunit a := IsLocalRingHom.map_nonunit a ∘ IsLocalRingHom.map_nonunit (f := g) (f a) + +-- see note [lower instance priority] +instance (priority := 100) isLocalRingHom_toMonoidHom (f : F) [IsLocalRingHom f] : + IsLocalRingHom (f : R →* S) := + ⟨IsLocalRingHom.map_nonunit (f := f)⟩ + +theorem MonoidHom.isLocalRingHom_of_comp (f : R →* S) (g : S →* T) [IsLocalRingHom (g.comp f)] : + IsLocalRingHom f := + ⟨fun _ ha => (isUnit_map_iff (g.comp f) _).mp (ha.map g)⟩ + +end IsLocalRingHom diff --git a/Mathlib/Algebra/Group/WithOne/Defs.lean b/Mathlib/Algebra/Group/WithOne/Defs.lean index cb45380e57fa6..39ed722267c5d 100644 --- a/Mathlib/Algebra/Group/WithOne/Defs.lean +++ b/Mathlib/Algebra/Group/WithOne/Defs.lean @@ -43,7 +43,7 @@ assert_not_exists DenselyOrdered universe u v w -variable {α : Type u} {β : Type v} {γ : Type w} +variable {α : Type u} /-- Add an extra element `1` to a type -/ @[to_additive "Add an extra element `0` to a type"] diff --git a/Mathlib/Algebra/Group/ZeroOne.lean b/Mathlib/Algebra/Group/ZeroOne.lean index 3e72968095621..8822f97d1d17e 100644 --- a/Mathlib/Algebra/Group/ZeroOne.lean +++ b/Mathlib/Algebra/Group/ZeroOne.lean @@ -6,17 +6,10 @@ Authors: Gabriel Ebner, Mario Carneiro import Mathlib.Tactic.ToAdditive /-! -## Classes for `Zero` and `One` --/ - -class Zero.{u} (α : Type u) where - zero : α +## Typeclass `One` -instance (priority := 300) Zero.toOfNat0 {α} [Zero α] : OfNat α (nat_lit 0) where - ofNat := ‹Zero α›.1 - -instance (priority := 200) Zero.ofOfNat0 {α} [OfNat α (nat_lit 0)] : Zero α where - zero := 0 +`Zero` has already been defined in Lean. +-/ universe u diff --git a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean index 28a7f1306d857..d30f29f25d6f4 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Defs.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Defs.lean @@ -49,7 +49,7 @@ assert_not_exists Ring open Function -variable {R R' M M' N G A B α β : Type*} +variable {M N A B α β : Type*} /-- `Monoid.toMulAction` is faithful on nontrivial cancellative monoids with zero. -/ instance CancelMonoidWithZero.faithfulSMul [CancelMonoidWithZero α] [Nontrivial α] : diff --git a/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean b/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean index e78af0c456d38..27bab44a1aaed 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Opposite.lean @@ -27,7 +27,7 @@ With `open scoped RightActions`, this provides: * `p <+ᵥ v` as an alias for `AddOpposite.op v +ᵥ p` -/ -variable {R M N α : Type*} +variable {M α : Type*} /-! ### Actions _on_ the opposite type diff --git a/Mathlib/Algebra/GroupWithZero/Action/Prod.lean b/Mathlib/Algebra/GroupWithZero/Action/Prod.lean index b3ca53b145019..b825703247594 100644 --- a/Mathlib/Algebra/GroupWithZero/Action/Prod.lean +++ b/Mathlib/Algebra/GroupWithZero/Action/Prod.lean @@ -26,7 +26,7 @@ namespace Prod section -variable [SMul M α] [SMul M β] [SMul N α] [SMul N β] (a : M) (x : α × β) +variable [SMul M α] [SMul M β] theorem smul_zero_mk {α : Type*} [Monoid M] [AddMonoid α] [DistribMulAction M α] (a : M) (c : β) : a • ((0 : α), c) = (0, a • c) := by rw [Prod.smul_mk, smul_zero] diff --git a/Mathlib/Algebra/GroupWithZero/Basic.lean b/Mathlib/Algebra/GroupWithZero/Basic.lean index 8b4b08535c105..b6f9678b599f4 100644 --- a/Mathlib/Algebra/GroupWithZero/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Basic.lean @@ -37,7 +37,7 @@ assert_not_exists DenselyOrdered open Function -variable {α M₀ G₀ M₀' G₀' F F' : Type*} +variable {M₀ G₀ : Type*} section @@ -136,7 +136,7 @@ theorem right_ne_zero_of_mul_eq_one (h : a * b = 1) : b ≠ 0 := end section MonoidWithZero -variable [MonoidWithZero M₀] {a : M₀} {m n : ℕ} +variable [MonoidWithZero M₀] {a : M₀} {n : ℕ} @[simp] lemma zero_pow : ∀ {n : ℕ}, n ≠ 0 → (0 : M₀) ^ n = 0 | n + 1, _ => by rw [pow_succ, mul_zero] @@ -234,7 +234,7 @@ end CancelMonoidWithZero section GroupWithZero -variable [GroupWithZero G₀] {a b c g h x : G₀} +variable [GroupWithZero G₀] {a b x : G₀} theorem GroupWithZero.mul_left_injective (h : x ≠ 0) : Function.Injective fun y => x * y := fun y y' w => by @@ -291,7 +291,7 @@ end GroupWithZero section GroupWithZero -variable [GroupWithZero G₀] {a b c : G₀} +variable [GroupWithZero G₀] {a : G₀} @[simp] theorem zero_div (a : G₀) : 0 / a = 0 := by rw [div_eq_mul_inv, zero_mul] @@ -421,7 +421,7 @@ end GroupWithZero section CommGroupWithZero -variable [CommGroupWithZero G₀] {a b c d : G₀} +variable [CommGroupWithZero G₀] theorem div_mul_eq_mul_div₀ (a b c : G₀) : a / c * b = a * b / c := by simp_rw [div_eq_mul_inv, mul_assoc, mul_comm c⁻¹] diff --git a/Mathlib/Algebra/GroupWithZero/Commute.lean b/Mathlib/Algebra/GroupWithZero/Commute.lean index 59423cb09016f..24a2a0afe674b 100644 --- a/Mathlib/Algebra/GroupWithZero/Commute.lean +++ b/Mathlib/Algebra/GroupWithZero/Commute.lean @@ -14,7 +14,7 @@ import Mathlib.Tactic.Nontriviality assert_not_exists DenselyOrdered -variable {α M₀ G₀ M₀' G₀' F F' : Type*} +variable {M₀ G₀ : Type*} variable [MonoidWithZero M₀] namespace Ring @@ -83,7 +83,7 @@ theorem div_left (hac : Commute a c) (hbc : Commute b c) : Commute (a / b) c := end Commute section GroupWithZero -variable {G₀ : Type*} [GroupWithZero G₀] {a : G₀} {m n : ℕ} +variable {G₀ : Type*} [GroupWithZero G₀] theorem pow_inv_comm₀ (a : G₀) (m n : ℕ) : a⁻¹ ^ m * a ^ n = a ^ n * a⁻¹ ^ m := (Commute.refl a).inv_left₀.pow_pow m n diff --git a/Mathlib/Algebra/GroupWithZero/Defs.lean b/Mathlib/Algebra/GroupWithZero/Defs.lean index b3d73d7ba0a35..14ace092e132d 100644 --- a/Mathlib/Algebra/GroupWithZero/Defs.lean +++ b/Mathlib/Algebra/GroupWithZero/Defs.lean @@ -26,7 +26,7 @@ universe u -- We have to fix the universe of `G₀` here, since the default argument to -- `GroupWithZero.div'` cannot contain a universe metavariable. -variable {G₀ : Type u} {M₀ M₀' G₀' : Type*} +variable {G₀ : Type u} {M₀ : Type*} /-- Typeclass for expressing that a type `M₀` with multiplication and a zero satisfies `0 * a = 0` and `a * 0 = 0` for all `a : M₀`. -/ @@ -159,17 +159,17 @@ class MulDivCancelClass (M₀ : Type*) [MonoidWithZero M₀] [Div M₀] : Prop w protected mul_div_cancel (a b : M₀) : b ≠ 0 → a * b / b = a section MulDivCancelClass -variable [MonoidWithZero M₀] [Div M₀] [MulDivCancelClass M₀] {a b : M₀} +variable [MonoidWithZero M₀] [Div M₀] [MulDivCancelClass M₀] -@[simp] lemma mul_div_cancel_right₀ (a : M₀) (hb : b ≠ 0) : a * b / b = a := +@[simp] lemma mul_div_cancel_right₀ (a : M₀) {b : M₀} (hb : b ≠ 0) : a * b / b = a := MulDivCancelClass.mul_div_cancel _ _ hb end MulDivCancelClass section MulDivCancelClass -variable [CommMonoidWithZero M₀] [Div M₀] [MulDivCancelClass M₀] {a b : M₀} +variable [CommMonoidWithZero M₀] [Div M₀] [MulDivCancelClass M₀] -@[simp] lemma mul_div_cancel_left₀ (b : M₀) (ha : a ≠ 0) : a * b / a = b := by +@[simp] lemma mul_div_cancel_left₀ (b : M₀) {a : M₀} (ha : a ≠ 0) : a * b / a = b := by rw [mul_comm, mul_div_cancel_right₀ _ ha] end MulDivCancelClass @@ -216,7 +216,7 @@ end section GroupWithZero -variable [GroupWithZero G₀] {a b c g h x : G₀} +variable [GroupWithZero G₀] {a b : G₀} @[simp] theorem mul_inv_cancel_right₀ (h : b ≠ 0) (a : G₀) : a * b * b⁻¹ = a := diff --git a/Mathlib/Algebra/GroupWithZero/Indicator.lean b/Mathlib/Algebra/GroupWithZero/Indicator.lean index 2b8dcaded4211..52d9d31a8d50e 100644 --- a/Mathlib/Algebra/GroupWithZero/Indicator.lean +++ b/Mathlib/Algebra/GroupWithZero/Indicator.lean @@ -16,7 +16,7 @@ variable {ι κ G₀ M₀ R : Type*} namespace Set section MulZeroClass -variable [MulZeroClass M₀] {s t : Set ι} {f g : ι → M₀} {i : ι} +variable [MulZeroClass M₀] {s t : Set ι} {i : ι} lemma indicator_mul (s : Set ι) (f g : ι → M₀) : indicator s (fun i ↦ f i * g i) = fun i ↦ indicator s f i * indicator s g i := by @@ -40,6 +40,12 @@ lemma indicator_mul_right (s : Set ι) (f g : ι → M₀) : · rfl · rw [mul_zero] +lemma indicator_mul_const (s : Set ι) (f : ι → M₀) (a : M₀) (i : ι) : + s.indicator (f · * a) i = s.indicator f i * a := by rw [indicator_mul_left] + +lemma indicator_const_mul (s : Set ι) (f : ι → M₀) (a : M₀) (i : ι) : + s.indicator (a * f ·) i = a * s.indicator f i := by rw [indicator_mul_right] + lemma inter_indicator_mul (f g : ι → M₀) (i : ι) : (s ∩ t).indicator (fun j ↦ f j * g j) i = s.indicator f i * t.indicator g i := by rw [← Set.indicator_indicator] diff --git a/Mathlib/Algebra/GroupWithZero/InjSurj.lean b/Mathlib/Algebra/GroupWithZero/InjSurj.lean index d7a7ff367118a..75dc801b0bbb6 100644 --- a/Mathlib/Algebra/GroupWithZero/InjSurj.lean +++ b/Mathlib/Algebra/GroupWithZero/InjSurj.lean @@ -19,7 +19,7 @@ variable {M₀ G₀ M₀' G₀' : Type*} section MulZeroClass -variable [MulZeroClass M₀] {a b : M₀} +variable [MulZeroClass M₀] /-- Pull back a `MulZeroClass` instance along an injective function. See note [reducible non-instances]. -/ @@ -149,7 +149,7 @@ end MonoidWithZero section CancelMonoidWithZero -variable [CancelMonoidWithZero M₀] {a b c : M₀} +variable [CancelMonoidWithZero M₀] /-- Pull back a `CancelMonoidWithZero` along an injective function. See note [reducible non-instances]. -/ @@ -159,15 +159,15 @@ protected abbrev Function.Injective.cancelMonoidWithZero [Zero M₀'] [Mul M₀' CancelMonoidWithZero M₀' := { hf.monoid f one mul npow, hf.mulZeroClass f zero mul with mul_left_cancel_of_ne_zero := fun hx H => - hf <| mul_left_cancel₀ ((hf.ne_iff' zero).2 hx) <| by erw [← mul, ← mul, H], + hf <| mul_left_cancel₀ ((hf.ne_iff' zero).2 hx) <| by rw [← mul, ← mul, H], mul_right_cancel_of_ne_zero := fun hx H => - hf <| mul_right_cancel₀ ((hf.ne_iff' zero).2 hx) <| by erw [← mul, ← mul, H] } + hf <| mul_right_cancel₀ ((hf.ne_iff' zero).2 hx) <| by rw [← mul, ← mul, H] } end CancelMonoidWithZero section CancelCommMonoidWithZero -variable [CancelCommMonoidWithZero M₀] {a b c : M₀} +variable [CancelCommMonoidWithZero M₀] /-- Pull back a `CancelCommMonoidWithZero` along an injective function. See note [reducible non-instances]. -/ @@ -181,7 +181,7 @@ end CancelCommMonoidWithZero section GroupWithZero -variable [GroupWithZero G₀] {a b c g h x : G₀} +variable [GroupWithZero G₀] /-- Pull back a `GroupWithZero` along an injective function. See note [reducible non-instances]. -/ @@ -193,9 +193,9 @@ protected abbrev Function.Injective.groupWithZero [Zero G₀'] [Mul G₀'] [One { hf.monoidWithZero f zero one mul npow, hf.divInvMonoid f one mul inv div npow zpow, pullback_nonzero f zero one with - inv_zero := hf <| by erw [inv, zero, inv_zero], + inv_zero := hf <| by rw [inv, zero, inv_zero], mul_inv_cancel := fun x hx => hf <| by - erw [one, mul, inv, mul_inv_cancel₀ ((hf.ne_iff' zero).2 hx)] } + rw [one, mul, inv, mul_inv_cancel₀ ((hf.ne_iff' zero).2 hx)] } /-- Push forward a `GroupWithZero` along a surjective function. See note [reducible non-instances]. -/ @@ -206,16 +206,16 @@ protected abbrev Function.Surjective.groupWithZero [Zero G₀'] [Mul G₀'] [One (npow : ∀ (x) (n : ℕ), f (x ^ n) = f x ^ n) (zpow : ∀ (x) (n : ℤ), f (x ^ n) = f x ^ n) : GroupWithZero G₀' := { hf.monoidWithZero f zero one mul npow, hf.divInvMonoid f one mul inv div npow zpow with - inv_zero := by erw [← zero, ← inv, inv_zero], + inv_zero := by rw [← zero, ← inv, inv_zero], mul_inv_cancel := hf.forall.2 fun x hx => by - erw [← inv, ← mul, mul_inv_cancel₀ (mt (congr_arg f) fun h ↦ hx (h.trans zero)), one] + rw [← inv, ← mul, mul_inv_cancel₀ (mt (congr_arg f) fun h ↦ hx (h.trans zero)), one] exists_pair_ne := ⟨0, 1, h01⟩ } end GroupWithZero section CommGroupWithZero -variable [CommGroupWithZero G₀] {a b c d : G₀} +variable [CommGroupWithZero G₀] /-- Pull back a `CommGroupWithZero` along an injective function. See note [reducible non-instances]. -/ diff --git a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean index 3c09328f414ca..f28e2198589e2 100644 --- a/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean +++ b/Mathlib/Algebra/GroupWithZero/NonZeroDivisors.lean @@ -214,7 +214,7 @@ theorem map_mem_nonZeroDivisors [Nontrivial M] [NoZeroDivisors M'] [ZeroHomClass theorem le_nonZeroDivisors_of_noZeroDivisors [NoZeroDivisors M] {S : Submonoid M} (hS : (0 : M) ∉ S) : S ≤ M⁰ := fun _ hx _ hy ↦ - Or.recOn (eq_zero_or_eq_zero_of_mul_eq_zero hy) (fun h ↦ h) fun h ↦ + Or.recOn (eq_zero_or_eq_zero_of_mul_eq_zero hy) id fun h ↦ absurd (h ▸ hx : (0 : M) ∈ S) hS theorem powers_le_nonZeroDivisors_of_noZeroDivisors [NoZeroDivisors M] {a : M} (ha : a ≠ 0) : @@ -304,7 +304,7 @@ theorem mk_mem_nonZeroDivisors_associates : Associates.mk a ∈ (Associates M₀ /-- The non-zero divisors of associates of a monoid with zero `M₀` are isomorphic to the associates of the non-zero divisors of `M₀` under the map `⟨⟦a⟧, _⟩ ↦ ⟦⟨a, _⟩⟧`. -/ def associatesNonZeroDivisorsEquiv : (Associates M₀)⁰ ≃* Associates M₀⁰ where - toEquiv := .subtypeQuotientEquivQuotientSubtype (s₂ := Associated.setoid _) + toEquiv := .subtypeQuotientEquivQuotientSubtype _ (s₂ := Associated.setoid _) (· ∈ nonZeroDivisors _) (by simp [mem_nonZeroDivisors_iff, Quotient.forall, Associates.mk_mul_mk]) (by simp [Associated.setoid]) diff --git a/Mathlib/Algebra/GroupWithZero/Pi.lean b/Mathlib/Algebra/GroupWithZero/Pi.lean index 547f6a5013092..f11c9daf124b3 100644 --- a/Mathlib/Algebra/GroupWithZero/Pi.lean +++ b/Mathlib/Algebra/GroupWithZero/Pi.lean @@ -22,7 +22,7 @@ variable {ι : Type*} {α : ι → Type*} namespace Pi section MulZeroClass -variable [∀ i, MulZeroClass (α i)] [DecidableEq ι] {i j : ι} {f : ∀ i, α i} +variable [∀ i, MulZeroClass (α i)] [DecidableEq ι] {i : ι} {f : ∀ i, α i} instance mulZeroClass : MulZeroClass (∀ i, α i) where zero_mul := by intros; ext; exact zero_mul _ diff --git a/Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean similarity index 97% rename from Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean rename to Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean index 653b0ea020618..ec178273360b2 100644 --- a/Mathlib/Algebra/GroupWithZero/Pointwise/Set.lean +++ b/Mathlib/Algebra/GroupWithZero/Pointwise/Set/Basic.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Floris van Doorn -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.GroupWithZero.Basic /-! diff --git a/Mathlib/Algebra/GroupWithZero/Semiconj.lean b/Mathlib/Algebra/GroupWithZero/Semiconj.lean index f3798456188e4..0dfc56212073d 100644 --- a/Mathlib/Algebra/GroupWithZero/Semiconj.lean +++ b/Mathlib/Algebra/GroupWithZero/Semiconj.lean @@ -13,7 +13,7 @@ import Mathlib.Algebra.Group.Semiconj.Units assert_not_exists DenselyOrdered -variable {α M₀ G₀ M₀' G₀' F F' : Type*} +variable {G₀ : Type*} namespace SemiconjBy diff --git a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean index a32ad81fb22e8..4daea455977cf 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Basic.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Basic.lean @@ -23,7 +23,7 @@ We also define `Ring.inverse`, a globally defined function on any ring assert_not_exists Multiplicative assert_not_exists DenselyOrdered -variable {α M₀ G₀ M₀' G₀' F F' : Type*} +variable {α M₀ G₀ : Type*} variable [MonoidWithZero M₀] namespace Units @@ -87,6 +87,12 @@ noncomputable def inverse : M₀ → M₀ := fun x => if h : IsUnit x then ((h.u theorem inverse_unit (u : M₀ˣ) : inverse (u : M₀) = (u⁻¹ : M₀ˣ) := by rw [inverse, dif_pos u.isUnit, IsUnit.unit_of_val_units] +theorem IsUnit.ringInverse {x : M₀} (h : IsUnit x) : IsUnit (inverse x) := + match h with + | ⟨u, hu⟩ => hu ▸ ⟨u⁻¹, (inverse_unit u).symm⟩ + +theorem inverse_of_isUnit {x : M₀} (h : IsUnit x) : inverse x = ((h.unit⁻¹ : M₀ˣ) : M₀) := dif_pos h + /-- By definition, if `x` is not invertible then `inverse x = 0`. -/ @[simp] theorem inverse_non_unit (x : M₀) (h : ¬IsUnit x) : inverse x = 0 := @@ -152,7 +158,6 @@ theorem isUnit_ring_inverse {a : M₀} : IsUnit (Ring.inverse a) ↔ IsUnit a := namespace Units variable [GroupWithZero G₀] -variable {a b : G₀} /-- Embed a non-zero element of a `GroupWithZero` into the unit group. By combining this function with the operations on units, @@ -208,7 +213,7 @@ theorem _root_.GroupWithZero.eq_zero_or_unit (a : G₀) : a = 0 ∨ ∃ u : G₀ end Units section GroupWithZero -variable [GroupWithZero G₀] {a b c d : G₀} {m n : ℕ} +variable [GroupWithZero G₀] {a b c : G₀} {m n : ℕ} theorem IsUnit.mk0 (x : G₀) (hx : x ≠ 0) : IsUnit x := (Units.mk0 x hx).isUnit diff --git a/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean b/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean index c413ab0a165b8..407a0fb1b6c75 100644 --- a/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean +++ b/Mathlib/Algebra/GroupWithZero/Units/Lemmas.lean @@ -15,10 +15,34 @@ import Mathlib.Algebra.GroupWithZero.Hom assert_not_exists DenselyOrdered -variable {α M₀ G₀ M₀' G₀' F F' : Type*} +variable {M M₀ G₀ M₀' G₀' F F' : Type*} variable [MonoidWithZero M₀] +section Monoid + +variable [Monoid M] [GroupWithZero G₀] + +lemma isLocalRingHom_of_exists_map_ne_one [FunLike F G₀ M] [MonoidHomClass F G₀ M] {f : F} + (hf : ∃ x : G₀, f x ≠ 1) : IsLocalRingHom f where + map_nonunit a h := by + rcases eq_or_ne a 0 with (rfl | h) + · obtain ⟨t, ht⟩ := hf + refine (ht ?_).elim + have := map_mul f t 0 + rw [← one_mul (f (t * 0)), mul_zero] at this + exact (h.mul_right_cancel this).symm + · exact ⟨⟨a, a⁻¹, mul_inv_cancel₀ h, inv_mul_cancel₀ h⟩, rfl⟩ + +instance [GroupWithZero G₀] [FunLike F G₀ M₀] [MonoidWithZeroHomClass F G₀ M₀] [Nontrivial M₀] + (f : F) : IsLocalRingHom f := + isLocalRingHom_of_exists_map_ne_one ⟨0, by simp⟩ + +end Monoid + +section GroupWithZero + namespace Commute + variable [GroupWithZero G₀] {a b c d : G₀} /-- The `MonoidWithZero` version of `div_eq_div_iff_mul_eq_mul`. -/ @@ -94,7 +118,6 @@ def invMonoidWithZeroHom {G₀ : Type*} [CommGroupWithZero G₀] : G₀ →*₀ namespace Units variable [GroupWithZero G₀] -variable {a b : G₀} @[simp] theorem smul_mk0 {α : Type*} [SMul G₀ α] {g : G₀} (hg : g ≠ 0) (a : α) : mk0 g hg • a = g • a := @@ -108,3 +131,5 @@ end Units theorem map_zpow₀ {F G₀ G₀' : Type*} [GroupWithZero G₀] [GroupWithZero G₀'] [FunLike F G₀ G₀'] [MonoidWithZeroHomClass F G₀ G₀'] (f : F) (x : G₀) (n : ℤ) : f (x ^ n) = f x ^ n := map_zpow' f (map_inv₀ f) x n + +end GroupWithZero diff --git a/Mathlib/Algebra/Homology/BifunctorAssociator.lean b/Mathlib/Algebra/Homology/BifunctorAssociator.lean index 70f0ff7943445..77c349d2de113 100644 --- a/Mathlib/Algebra/Homology/BifunctorAssociator.lean +++ b/Mathlib/Algebra/Homology/BifunctorAssociator.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.GradedObject.Associator -import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor +import Mathlib.CategoryTheory.Linear.LinearFunctor import Mathlib.Algebra.Homology.Bifunctor /-! @@ -187,6 +187,212 @@ lemma ι_mapBifunctor₁₂Desc (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) end +variable (F₁₂ G) + +/-- The first differential on a summand +of `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def d₁ (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) : + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).obj (K₃.X i₃) ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j := + (ComplexShape.ε₁ c₁₂ c₃ c₄ (ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩, i₃) * + ComplexShape.ε₁ c₁ c₂ c₁₂ (i₁, i₂)) • + (G.map ((F₁₂.map (K₁.d i₁ (c₁.next i₁))).app (K₂.X i₂))).app (K₃.X i₃) ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ _ i₂ i₃ j + +lemma d₁_eq_zero (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) (h : ¬ c₁.Rel i₁ (c₁.next i₁)) : + d₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = 0 := by + dsimp [d₁] + rw [shape _ _ _ h, Functor.map_zero, zero_app, Functor.map_zero, zero_app, zero_comp, smul_zero] + +lemma d₁_eq {i₁ i₁' : ι₁} (h₁ : c₁.Rel i₁ i₁') (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) : + d₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = + (ComplexShape.ε₁ c₁₂ c₃ c₄ (ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩, i₃) * + ComplexShape.ε₁ c₁ c₂ c₁₂ (i₁, i₂) ) • + (G.map ((F₁₂.map (K₁.d i₁ i₁')).app (K₂.X i₂))).app (K₃.X i₃) ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁' i₂ i₃ j := by + obtain rfl := c₁.next_eq' h₁ + rfl + +/-- The second differential on a summand +of `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def d₂ (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) : + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).obj (K₃.X i₃) ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j := + (c₁₂.ε₁ c₃ c₄ (ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩, i₃) * c₁.ε₂ c₂ c₁₂ (i₁, i₂)) • + (G.map ((F₁₂.obj (K₁.X i₁)).map (K₂.d i₂ (c₂.next i₂)))).app (K₃.X i₃) ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ _ i₃ j + +lemma d₂_eq_zero (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) (h : ¬ c₂.Rel i₂ (c₂.next i₂)) : + d₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = 0 := by + dsimp [d₂] + rw [shape _ _ _ h, Functor.map_zero, Functor.map_zero, zero_app, zero_comp, smul_zero] + +lemma d₂_eq (i₁ : ι₁) {i₂ i₂' : ι₂} (h₂ : c₂.Rel i₂ i₂') (i₃ : ι₃) (j : ι₄) : + d₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = + (c₁₂.ε₁ c₃ c₄ (ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩, i₃) * c₁.ε₂ c₂ c₁₂ (i₁, i₂)) • + (G.map ((F₁₂.obj (K₁.X i₁)).map (K₂.d i₂ i₂'))).app (K₃.X i₃) ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ _ i₃ j := by + obtain rfl := c₂.next_eq' h₂ + rfl + +/-- The third differential on a summand +of `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def d₃ (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) : + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).obj (K₃.X i₃) ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j := + (ComplexShape.ε₂ c₁₂ c₃ c₄ (c₁.π c₂ c₁₂ (i₁, i₂), i₃)) • + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).map (K₃.d i₃ (c₃.next i₃)) ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ _ j + +lemma d₃_eq_zero (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j : ι₄) (h : ¬ c₃.Rel i₃ (c₃.next i₃)) : + d₃ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = 0 := by + dsimp [d₃] + rw [shape _ _ _ h, Functor.map_zero, zero_comp, smul_zero] + +lemma d₃_eq (i₁ : ι₁) (i₂ : ι₂) {i₃ i₃' : ι₃} (h₃ : c₃.Rel i₃ i₃') (j : ι₄) : + d₃ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j = + (ComplexShape.ε₂ c₁₂ c₃ c₄ (c₁.π c₂ c₁₂ (i₁, i₂), i₃)) • + (G.obj ((F₁₂.obj (K₁.X i₁)).obj (K₂.X i₂))).map (K₃.d i₃ i₃') ≫ + ιOrZero F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ _ j := by + obtain rfl := c₃.next_eq' h₃ + rfl + + +section + +variable [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] +variable (j j' : ι₄) + +/-- The first differential on `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def D₁ : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j' := + mapBifunctor₁₂Desc (fun i₁ i₂ i₃ _ ↦ d₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j') + +/-- The second differential on `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def D₂ : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j' := + mapBifunctor₁₂Desc (fun i₁ i₂ i₃ _ ↦ d₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j') + +/-- The third differential on `mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄`. -/ +noncomputable def D₃ : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j ⟶ + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).X j' := + mapBifunctor.D₂ _ _ _ _ _ _ + +end + +section + +variable (i₁ : ι₁) (i₂ : ι₂) (i₃ : ι₃) (j j' : ι₄) + (h : ComplexShape.r c₁ c₂ c₃ c₁₂ c₄ (i₁, i₂, i₃) = j) + +@[reassoc (attr := simp)] +lemma ι_D₁ [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] : + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ D₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' = + d₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j' := by + simp [D₁] + +@[reassoc (attr := simp)] +lemma ι_D₂ [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] : + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ D₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' = + d₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j' := by + simp [D₂] + +@[reassoc (attr := simp)] +lemma ι_D₃ : + ι F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j h ≫ D₃ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' = + d₃ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ i₁ i₂ i₃ j' := by + simp only [ι_eq _ _ _ _ _ _ _ _ _ _ _ _ rfl h, D₃, assoc, mapBifunctor.ι_D₂] + by_cases h₁ : c₃.Rel i₃ (c₃.next i₃) + · rw [d₃_eq _ _ _ _ _ _ _ _ _ h₁] + by_cases h₂ : ComplexShape.π c₁₂ c₃ c₄ (c₁.π c₂ c₁₂ (i₁, i₂), c₃.next i₃) = j' + · rw [mapBifunctor.d₂_eq _ _ _ _ _ h₁ _ h₂, + ιOrZero_eq _ _ _ _ _ _ _ _ _ _ _ h₂, + Linear.comp_units_smul, smul_left_cancel_iff, + ι_eq _ _ _ _ _ _ _ _ _ _ _ _ rfl h₂, + NatTrans.naturality_assoc] + · rw [mapBifunctor.d₂_eq_zero' _ _ _ _ _ h₁ _ h₂, comp_zero, + ιOrZero_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₂, comp_zero, smul_zero] + · rw [mapBifunctor.d₂_eq_zero _ _ _ _ _ _ _ h₁, comp_zero, + d₃_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₁] + +end + +lemma d_eq (j j' : ι₄) [HasGoodTrifunctor₁₂Obj F₁₂ G K₁ K₂ K₃ c₁₂ c₄] : + (mapBifunctor (mapBifunctor K₁ K₂ F₁₂ c₁₂) K₃ G c₄).d j j' = + D₁ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' + D₂ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' + + D₃ F₁₂ G K₁ K₂ K₃ c₁₂ c₄ j j' := by + rw [mapBifunctor.d_eq] + congr 1 + ext i₁ i₂ i₃ h + simp only [Preadditive.comp_add, ι_D₁, ι_D₂] + rw [ι_eq _ _ _ _ _ _ _ _ _ _ _ _ rfl h, assoc, mapBifunctor.ι_D₁] + set i₁₂ := ComplexShape.π c₁ c₂ c₁₂ ⟨i₁, i₂⟩ + by_cases h₁ : c₁₂.Rel i₁₂ (c₁₂.next i₁₂) + · by_cases h₂ : ComplexShape.π c₁₂ c₃ c₄ (c₁₂.next i₁₂, i₃) = j' + · rw [mapBifunctor.d₁_eq _ _ _ _ h₁ _ _ h₂] + simp only [mapBifunctor.d_eq, Functor.map_add, NatTrans.app_add, Preadditive.add_comp, + smul_add, Preadditive.comp_add, Linear.comp_units_smul] + congr 1 + · rw [← NatTrans.comp_app_assoc, ← Functor.map_comp, + mapBifunctor.ι_D₁] + by_cases h₃ : c₁.Rel i₁ (c₁.next i₁) + · have h₄ := (ComplexShape.next_π₁ c₂ c₁₂ h₃ i₂).symm + rw [mapBifunctor.d₁_eq _ _ _ _ h₃ _ _ h₄, + d₁_eq _ _ _ _ _ _ _ h₃, + ιOrZero_eq _ _ _ _ _ _ _ _ _ _ _ (by rw [← h₂, ← h₄]; rfl), + ι_eq _ _ _ _ _ _ _ _ _ _ (c₁₂.next i₁₂) _ h₄ h₂, + Functor.map_units_smul, Functor.map_comp, NatTrans.app_units_zsmul, + NatTrans.comp_app, Linear.units_smul_comp, assoc, smul_smul] + · rw [d₁_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₃, + mapBifunctor.d₁_eq_zero _ _ _ _ _ _ _ h₃, + Functor.map_zero, zero_app, zero_comp, smul_zero] + · rw [← NatTrans.comp_app_assoc, ← Functor.map_comp, + mapBifunctor.ι_D₂] + by_cases h₃ : c₂.Rel i₂ (c₂.next i₂) + · have h₄ := (ComplexShape.next_π₂ c₁ c₁₂ i₁ h₃).symm + rw [mapBifunctor.d₂_eq _ _ _ _ _ h₃ _ h₄, + d₂_eq _ _ _ _ _ _ _ _ h₃, + ιOrZero_eq _ _ _ _ _ _ _ _ _ _ _ (by rw [← h₂, ← h₄]; rfl), + ι_eq _ _ _ _ _ _ _ _ _ _ (c₁₂.next i₁₂) _ h₄ h₂, + Functor.map_units_smul, Functor.map_comp, NatTrans.app_units_zsmul, + NatTrans.comp_app, Linear.units_smul_comp, assoc, smul_smul] + · rw [d₂_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₃, + mapBifunctor.d₂_eq_zero _ _ _ _ _ _ _ h₃, + Functor.map_zero, zero_app, zero_comp, smul_zero] + · rw [mapBifunctor.d₁_eq_zero' _ _ _ _ h₁ _ _ h₂, comp_zero] + trans 0 + 0 + · simp + · congr 1 + · by_cases h₃ : c₁.Rel i₁ (c₁.next i₁) + · rw [d₁_eq _ _ _ _ _ _ _ h₃, ιOrZero_eq_zero, comp_zero, smul_zero] + dsimp [ComplexShape.r] + intro h₄ + apply h₂ + rw [← h₄, ComplexShape.next_π₁ c₂ c₁₂ h₃ i₂] + · rw [d₁_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₃] + · by_cases h₃ : c₂.Rel i₂ (c₂.next i₂) + · rw [d₂_eq _ _ _ _ _ _ _ _ h₃, ιOrZero_eq_zero, comp_zero, smul_zero] + dsimp [ComplexShape.r] + intro h₄ + apply h₂ + rw [← h₄, ComplexShape.next_π₂ c₁ c₁₂ i₁ h₃] + · rw [d₂_eq_zero _ _ _ _ _ _ _ _ _ _ _ h₃] + · rw [mapBifunctor.d₁_eq_zero _ _ _ _ _ _ _ h₁, comp_zero, + d₁_eq_zero, d₂_eq_zero, zero_add] + · intro h₂ + apply h₁ + have := ComplexShape.rel_π₂ c₁ c₁₂ i₁ h₂ + rw [c₁₂.next_eq' this] + exact this + · intro h₂ + apply h₁ + have := ComplexShape.rel_π₁ c₂ c₁₂ h₂ i₂ + rw [c₁₂.next_eq' this] + exact this + end mapBifunctor₁₂ end HomologicalComplex diff --git a/Mathlib/Algebra/Homology/ConcreteCategory.lean b/Mathlib/Algebra/Homology/ConcreteCategory.lean index 8d0b74ba8ec07..ec495e24a7d91 100644 --- a/Mathlib/Algebra/Homology/ConcreteCategory.lean +++ b/Mathlib/Algebra/Homology/ConcreteCategory.lean @@ -75,21 +75,20 @@ lemma δ_apply (x₃ : (forget₂ C Ab).obj (S.X₃.X i)) (forget₂ C Ab).map (S.X₁.homologyπ j) (S.X₁.cyclesMk x₁ k hk (by have := hS.mono_f apply (Preadditive.mono_iff_injective (S.f.f k)).1 inferInstance - erw [← forget₂_comp_apply, ← HomologicalComplex.Hom.comm, forget₂_comp_apply, hx₁, + rw [← forget₂_comp_apply, ← HomologicalComplex.Hom.comm, forget₂_comp_apply, hx₁, ← forget₂_comp_apply, HomologicalComplex.d_comp_d, Functor.map_zero, map_zero, AddMonoidHom.zero_apply])) := by refine hS.δ_apply' i j hij _ ((forget₂ C Ab).map (S.X₂.pOpcycles i) x₂) _ ?_ ?_ - · erw [← forget₂_comp_apply, ← forget₂_comp_apply, + · rw [← forget₂_comp_apply, ← forget₂_comp_apply, HomologicalComplex.p_opcyclesMap, Functor.map_comp, comp_apply, HomologicalComplex.homology_π_ι, forget₂_comp_apply, hx₂, HomologicalComplex.i_cyclesMk] · apply (Preadditive.mono_iff_injective (S.X₂.iCycles j)).1 inferInstance conv_lhs => - erw [← forget₂_comp_apply, HomologicalComplex.cyclesMap_i, forget₂_comp_apply, + rw [← forget₂_comp_apply, HomologicalComplex.cyclesMap_i, forget₂_comp_apply, HomologicalComplex.i_cyclesMk, hx₁] conv_rhs => - erw [← forget₂_comp_apply, ← forget₂_comp_apply, + rw [← forget₂_comp_apply, ← forget₂_comp_apply, HomologicalComplex.pOpcycles_opcyclesToCycles_assoc, HomologicalComplex.toCycles_i] - rfl end ShortExact diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean index 781e2de9cf31f..774df032bb48c 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/Basic.lean @@ -36,7 +36,6 @@ sheaves over `X` shall be in `Type u`. ## TODO * compute `Ext X Y 0` -* construct the covariant long exact sequences of `Ext`. * construct the contravariant long exact sequences of `Ext`. -/ diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean new file mode 100644 index 0000000000000..427dd7ae80159 --- /dev/null +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExactSequences.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2024 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.Exact +import Mathlib.Algebra.Homology.DerivedCategory.Ext.ExtClass +import Mathlib.Algebra.Homology.ShortComplex.Ab +import Mathlib.CategoryTheory.Triangulated.Yoneda + +/-! +# Long exact sequences of `Ext`-groups + +In this file, we obtain the covariant long exact sequence of `Ext`: +`Ext X S.X₁ n₀ → Ext X S.X₂ n₀ → Ext X S.X₃ n₀ → Ext X S.X₁ n₁ → Ext X S.X₂ n₁ → Ext X S.X₃ n₁` +when `S` is a short exact short complex in an abelian category `C`, `n₀ + 1 = n₁` and `X : C`. + +-/ + +universe w' w v u + +namespace CategoryTheory + +open Opposite DerivedCategory + +variable {C : Type u} [Category.{v} C] [Abelian C] [HasExt.{w} C] + +namespace Abelian + +namespace Ext + +section CovariantSequence + +lemma hom_comp_singleFunctor_map_shift [HasDerivedCategory.{w'} C] + {X Y Z : C} {n : ℕ} (x : Ext X Y n) (f : Y ⟶ Z) : + x.hom ≫ ((DerivedCategory.singleFunctor C 0).map f)⟦(n : ℤ)⟧' = + (x.comp (mk₀ f) (add_zero n)).hom := by + simp only [comp_hom, mk₀_hom, ShiftedHom.comp_mk₀] + +variable {X : C} {S : ShortComplex C} (hS : S.ShortExact) + +lemma preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply + [HasDerivedCategory.{w'} C] {X : C} {n₀ : ℕ} (x : Ext X S.X₃ n₀) + {n₁ : ℕ} (h : n₀ + 1 = n₁) : + (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequenceδ + hS.singleTriangle n₀ n₁ (by omega) x.hom = + (x.comp hS.extClass h).hom := by + rw [Pretriangulated.preadditiveCoyoneda_homologySequenceδ_apply, + comp_hom, hS.extClass_hom, ShiftedHom.comp] + rfl + +variable (X) + +include hS in +/-- Alternative formulation of `covariant_sequence_exact₂` -/ +lemma covariant_sequence_exact₂' (n : ℕ) : + (ShortComplex.mk (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n))) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_third_deg_zero, mk₀_comp_mk₀, ShortComplex.zero, mk₀_zero, + comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₂ _ + (hS.singleTriangle_distinguished) n + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + all_goals ext x; apply hom_comp_singleFunctor_map_shift (C := C) + +section + +variable (n₀ n₁ : ℕ) (h : n₀ + 1 = n₁) + +/-- Alternative formulation of `covariant_sequence_exact₃` -/ +lemma covariant_sequence_exact₃' : + (ShortComplex.mk (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_second_deg_zero, ShortComplex.ShortExact.comp_extClass, + comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₃ _ + (hS.singleTriangle_distinguished) n₀ n₁ (by omega) + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + · ext x; apply hom_comp_singleFunctor_map_shift (C := C) + · ext x + exact preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply hS x h + +/-- Alternative formulation of `covariant_sequence_exact₁` -/ +lemma covariant_sequence_exact₁' : + (ShortComplex.mk + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) + (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₁))) (by + ext x + dsimp [AddCommGrp.ofHom] + simp only [comp_assoc_of_third_deg_zero, ShortComplex.ShortExact.extClass_comp, comp_zero] + rfl)).Exact := by + letI := HasDerivedCategory.standard C + have := (preadditiveCoyoneda.obj (op ((singleFunctor C 0).obj X))).homologySequence_exact₁ _ + (hS.singleTriangle_distinguished) n₀ n₁ (by omega) + rw [ShortComplex.ab_exact_iff_function_exact] at this ⊢ + apply Function.Exact.of_ladder_addEquiv_of_exact' (e₁ := Ext.homAddEquiv) + (e₂ := Ext.homAddEquiv) (e₃ := Ext.homAddEquiv) (H := this) + · ext x + exact preadditiveCoyoneda_homologySequenceδ_singleTriangle_apply hS x h + · ext x; apply hom_comp_singleFunctor_map_shift (C := C) + +open ComposableArrows + +/-- Given a short exact short complex `S` in an abelian category `C` and an object `X : C`, +this is the long exact sequence +`Ext X S.X₁ n₀ → Ext X S.X₂ n₀ → Ext X S.X₃ n₀ → Ext X S.X₁ n₁ → Ext X S.X₂ n₁ → Ext X S.X₃ n₁` +when `n₀ + 1 = n₁` -/ +noncomputable def covariantSequence : ComposableArrows AddCommGrp.{w} 5 := + mk₅ (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₀))) + (AddCommGrp.ofHom (hS.extClass.postcomp X h)) + (AddCommGrp.ofHom ((mk₀ S.f).postcomp X (add_zero n₁))) + (AddCommGrp.ofHom ((mk₀ S.g).postcomp X (add_zero n₁))) + +lemma covariantSequence_exact : + (covariantSequence X hS n₀ n₁ h).Exact := + exact_of_δ₀ (covariant_sequence_exact₂' X hS n₀).exact_toComposableArrows + (exact_of_δ₀ (covariant_sequence_exact₃' X hS n₀ n₁ h).exact_toComposableArrows + (exact_of_δ₀ (covariant_sequence_exact₁' X hS n₀ n₁ h).exact_toComposableArrows + (covariant_sequence_exact₂' X hS n₁).exact_toComposableArrows)) + +end + +lemma covariant_sequence_exact₁ {n₁ : ℕ} (x₁ : Ext X S.X₁ n₁) + (hx₁ : x₁.comp (mk₀ S.f) (add_zero n₁) = 0) {n₀ : ℕ} (hn₀ : n₀ + 1 = n₁) : + ∃ (x₃ : Ext X S.X₃ n₀), x₃.comp hS.extClass hn₀ = x₁ := by + have := covariant_sequence_exact₁' X hS n₀ n₁ hn₀ + rw [ShortComplex.ab_exact_iff] at this + exact this x₁ hx₁ + +include hS in +lemma covariant_sequence_exact₂ {n : ℕ} (x₂ : Ext X S.X₂ n) + (hx₂ : x₂.comp (mk₀ S.g) (add_zero n) = 0) : + ∃ (x₁ : Ext X S.X₁ n), x₁.comp (mk₀ S.f) (add_zero n) = x₂ := by + have := covariant_sequence_exact₂' X hS n + rw [ShortComplex.ab_exact_iff] at this + exact this x₂ hx₂ + +lemma covariant_sequence_exact₃ {n₀ : ℕ} (x₃ : Ext X S.X₃ n₀) {n₁ : ℕ} (hn₁ : n₀ + 1 = n₁) + (hx₃ : x₃.comp hS.extClass hn₁ = 0) : + ∃ (x₂ : Ext X S.X₂ n₀), x₂.comp (mk₀ S.g) (add_zero n₀) = x₃ := by + have := covariant_sequence_exact₃' X hS n₀ n₁ hn₁ + rw [ShortComplex.ab_exact_iff] at this + exact this x₃ hx₃ + +end CovariantSequence + +end Ext + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean index 9a636124ff714..2869c7955e0c0 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext/ExtClass.lean @@ -29,6 +29,8 @@ namespace ShortComplex variable (S : ShortComplex C) +lemma ext_mk₀_f_comp_ext_mk₀_g : (Ext.mk₀ S.f).comp (Ext.mk₀ S.g) (zero_add 0) = 0 := by simp + namespace ShortExact variable {S} diff --git a/Mathlib/Algebra/Homology/HomologicalBicomplex.lean b/Mathlib/Algebra/Homology/HomologicalBicomplex.lean index b02aad6a648b8..dbd85f9d8e710 100644 --- a/Mathlib/Algebra/Homology/HomologicalBicomplex.lean +++ b/Mathlib/Algebra/Homology/HomologicalBicomplex.lean @@ -205,7 +205,7 @@ def XXIsoOfEq {x₁ y₁ : I₁} (h₁ : x₁ = y₁) {x₂ y₂ : I₂} (h₂ : @[simp] lemma XXIsoOfEq_rfl (i₁ : I₁) (i₂ : I₂) : - K.XXIsoOfEq (rfl : i₁ = i₁) (rfl : i₂ = i₂) = Iso.refl _ := rfl + K.XXIsoOfEq _ _ _ (rfl : i₁ = i₁) (rfl : i₂ = i₂) = Iso.refl _ := rfl end HomologicalComplex₂ diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean index 9341e60b09122..01810e1dc41e4 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Shift.lean @@ -244,7 +244,7 @@ instance commShiftMapCochainComplex : ext rw [CommShift.isoAdd_hom_app] dsimp - erw [id_comp, id_comp] + rw [id_comp, id_comp] simp only [CochainComplex.shiftFunctorAdd_hom_app_f, CochainComplex.shiftFunctorAdd_inv_app_f, HomologicalComplex.XIsoOfEq, eqToIso, eqToHom_map, eqToHom_trans, eqToHom_refl] diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean b/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean index b49421f3f25b8..85cb5a4752ba7 100644 --- a/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean +++ b/Mathlib/Algebra/Homology/HomotopyCategory/Triangulated.lean @@ -61,7 +61,7 @@ noncomputable def hom : (descCochain _ 0 (Cochain.ofHom (inr (f ≫ g))) (neg_add_cancel 1)) (by ext p _ rfl simp [mappingConeCompTriangle, map, ext_from_iff _ _ _ rfl, - inl_v_d_assoc _ (p+1) p (p+2) (by linarith) (by linarith)]) + inl_v_d_assoc _ (p+1) p (p+2) (by omega) (by omega)]) /-- Given two composable morphisms `f` and `g` in the category of cochain complexes, this is the canonical morphism (which is an homotopy equivalence) from the mapping cone of @@ -72,7 +72,7 @@ noncomputable def inv : mappingCone (mappingConeCompTriangle f g).mor₁ ⟶ map ext p rw [ext_from_iff _ (p + 1) _ rfl, ext_to_iff _ _ (p + 1) rfl] simp [map, δ_zero_cochain_comp, - Cochain.comp_v _ _ (add_neg_cancel 1) p (p+1) p (by linarith) (by linarith)]) + Cochain.comp_v _ _ (add_neg_cancel 1) p (p+1) p (by omega) (by omega)]) @[reassoc (attr := simp)] lemma hom_inv_id : hom f g ≫ inv f g = 𝟙 _ := by @@ -86,44 +86,25 @@ this is the `homotopyInvHomId` field of the homotopy equivalence the morphism `mappingCone f ⟶ mappingCone (f ≫ g)`. -/ noncomputable def homotopyInvHomId : Homotopy (inv f g ≫ hom f g) (𝟙 _) := (Cochain.equivHomotopy _ _).symm ⟨-((snd _).comp ((fst (f ≫ g)).1.comp - ((inl f).comp (inl _) (by linarith)) (show 1 + (-2) = -1 by linarith)) (zero_add (-1))), by + ((inl f).comp (inl _) (by omega)) (show 1 + (-2) = -1 by omega)) (zero_add (-1))), by rw [δ_neg, δ_zero_cochain_comp _ _ _ (neg_add_cancel 1), Int.negOnePow_neg, Int.negOnePow_one, Units.neg_smul, one_smul, - δ_comp _ _ (show 1 + (-2) = -1 by linarith) 2 (-1) 0 (by linarith) - (by linarith) (by linarith), - δ_comp _ _ (show (-1) + (-1) = -2 by linarith) 0 0 (-1) (by linarith) - (by linarith) (by linarith), Int.negOnePow_neg, Int.negOnePow_neg, - Int.negOnePow_even 2 ⟨1, by linarith⟩, Int.negOnePow_one, Units.neg_smul, + δ_comp _ _ (show 1 + (-2) = -1 by omega) 2 (-1) 0 (by omega) + (by omega) (by omega), + δ_comp _ _ (show (-1) + (-1) = -2 by omega) 0 0 (-1) (by omega) + (by omega) (by omega), Int.negOnePow_neg, Int.negOnePow_neg, + Int.negOnePow_even 2 ⟨1, by omega⟩, Int.negOnePow_one, Units.neg_smul, one_smul, one_smul, δ_inl, δ_inl, δ_snd, Cocycle.δ_eq_zero, Cochain.zero_comp, add_zero, Cochain.neg_comp, neg_neg] ext n rw [ext_from_iff _ (n + 1) n rfl, ext_from_iff _ (n + 1) n rfl, - ext_from_iff _ (n + 2) (n + 1) (by linarith)] - simp? [hom, inv, ext_to_iff _ n (n + 1) rfl, map, Cochain.comp_v _ _ - (add_neg_cancel 1) n (n + 1) n (by linarith) (by linarith), - Cochain.comp_v _ _ (show 1 + -2 = -1 by linarith) (n + 1) (n + 2) n - (by linarith) (by linarith), - Cochain.comp_v _ _ (show (-1) + -1 = -2 by linarith) (n + 2) (n + 1) n - (by linarith) (by linarith)] says - simp only [mappingConeCompTriangle_obj₁, mappingConeCompTriangle_obj₂, - mappingConeCompTriangle_mor₁, map, Int.reduceNeg, inv, hom, Cochain.ofHom_comp, - ofHom_desc, ofHom_lift, descCocycle_coe, AddSubmonoid.coe_zero, - Cochain.comp_zero_cochain_v, inl_v_descCochain_v_assoc, Cochain.zero_cochain_comp_v, - assoc, inl_v_snd_v_assoc, zero_comp, Cochain.id_comp, - Cochain.comp_assoc_of_first_is_zero_cochain, Cochain.comp_add, Cochain.comp_neg, - Cochain.comp_assoc_of_second_is_zero_cochain, neg_add_rev, neg_neg, Cochain.add_v, - Cochain.neg_v, - Cochain.comp_v _ _ (add_neg_cancel 1) n (n + 1) n (by linarith) (by linarith), - Cochain.comp_v _ _ (show 1 + -2 = -1 by linarith) (n + 1) (n + 2) n (by linarith) - (by linarith), - Cochain.comp_v _ _ (show (-1) + -1 = -2 by linarith) (n + 2) (n + 1) n (by linarith) - (by linarith), - Cochain.ofHom_v, HomologicalComplex.id_f, Preadditive.comp_add, Preadditive.comp_neg, - inl_v_fst_v_assoc, neg_zero, add_zero, comp_id, neg_add_cancel, inr_f_snd_v_assoc, - inr_f_descCochain_v_assoc, inr_f_fst_v_assoc, comp_zero, zero_add, - ext_to_iff _ n (n + 1) rfl, liftCochain_v_fst_v, inl_v_descCochain_v, inl_v_fst_v, - liftCochain_v_snd_v, Cochain.zero_v, inl_v_snd_v, and_self, neg_add_cancel_right, - inr_f_descCochain_v, inr_f_fst_v, inr_f_snd_v]⟩ + ext_from_iff _ (n + 2) (n + 1) (by omega)] + simp [hom, inv, ext_to_iff _ n (n + 1) rfl, map, Cochain.comp_v _ _ + (add_neg_cancel 1) n (n + 1) n (by omega) (by omega), + Cochain.comp_v _ _ (show 1 + -2 = -1 by omega) (n + 1) (n + 2) n + (by omega) (by omega), + Cochain.comp_v _ _ (show (-1) + -1 = -2 by omega) (n + 2) (n + 1) n + (by omega) (by omega)]⟩ end MappingConeCompHomotopyEquiv diff --git a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean index 8b76e44a2ca8c..474f801a48272 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/Ab.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/Ab.lean @@ -109,6 +109,18 @@ lemma ab_exact_iff : obtain ⟨x₁, rfl⟩ := h x₂ hx₂ exact ⟨x₁, rfl⟩ +lemma ab_exact_iff_function_exact : + S.Exact ↔ Function.Exact S.f S.g := by + rw [S.ab_exact_iff] + apply forall_congr' + intro x₂ + constructor + · intro h + refine ⟨h, ?_⟩ + rintro ⟨x₁, rfl⟩ + simp only [ab_zero_apply] + · tauto + lemma ab_exact_iff_ker_le_range : S.Exact ↔ S.g.ker ≤ S.f.range := S.ab_exact_iff lemma ab_exact_iff_range_eq_ker : S.Exact ↔ S.f.range = S.g.ker := by diff --git a/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean b/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean index 7523eadd214dd..59034f288455b 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ModuleCat.lean @@ -33,7 +33,7 @@ linear maps `f` and `g` and the vanishing of their composition. -/ def moduleCatMk {X₁ X₂ X₃ : Type v} [AddCommGroup X₁] [AddCommGroup X₂] [AddCommGroup X₃] [Module R X₁] [Module R X₂] [Module R X₃] (f : X₁ →ₗ[R] X₂) (g : X₂ →ₗ[R] X₃) (hfg : g.comp f = 0) : ShortComplex (ModuleCat.{v} R) := - ShortComplex.mk (ModuleCat.ofHom f) (ModuleCat.ofHom g) hfg + ShortComplex.mk (ModuleCat.asHom f) (ModuleCat.asHom g) hfg variable (S : ShortComplex (ModuleCat.{v} R)) @@ -138,7 +138,7 @@ def moduleCatLeftHomologyData : S.LeftHomologyData where erw [Submodule.Quotient.mk_eq_zero] rw [LinearMap.mem_range] apply exists_apply_eq_apply - hπ := ModuleCat.cokernelIsColimit (ModuleCat.ofHom S.moduleCatToCycles) + hπ := ModuleCat.cokernelIsColimit (ModuleCat.asHom S.moduleCatToCycles) @[simp] lemma moduleCatLeftHomologyData_f' : diff --git a/Mathlib/Algebra/Homology/ShortComplex/SnakeLemma.lean b/Mathlib/Algebra/Homology/ShortComplex/SnakeLemma.lean index 77769d32f3b80..8fe3dbac06932 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/SnakeLemma.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/SnakeLemma.lean @@ -381,7 +381,7 @@ variable (S₁ S₂ S₃ : SnakeInput C) /-- A morphism of snake inputs involve four morphisms of short complexes which make the obvious diagram commute. -/ @[ext] -structure Hom := +structure Hom where /-- a morphism between the zeroth lines -/ f₀ : S₁.L₀ ⟶ S₂.L₀ /-- a morphism between the first lines -/ diff --git a/Mathlib/Algebra/Homology/Single.lean b/Mathlib/Algebra/Homology/Single.lean index 6adb409ebcd24..f29c9eed69daf 100644 --- a/Mathlib/Algebra/Homology/Single.lean +++ b/Mathlib/Algebra/Homology/Single.lean @@ -201,7 +201,7 @@ lemma single₀_map_f_zero {A B : V} (f : A ⟶ B) : ((single₀ V).map f).f 0 = f := by rw [HomologicalComplex.single_map_f_self] dsimp [HomologicalComplex.singleObjXSelf, HomologicalComplex.singleObjXIsoOfEq] - erw [comp_id, id_comp] + rw [comp_id, id_comp] @[simp] @@ -269,7 +269,7 @@ lemma single₀_map_f_zero {A B : V} (f : A ⟶ B) : ((single₀ V).map f).f 0 = f := by rw [HomologicalComplex.single_map_f_self] dsimp [HomologicalComplex.singleObjXSelf, HomologicalComplex.singleObjXIsoOfEq] - erw [comp_id, id_comp] + rw [comp_id, id_comp] @[simp] lemma single₀ObjXSelf (X : V) : diff --git a/Mathlib/Algebra/Homology/TotalComplex.lean b/Mathlib/Algebra/Homology/TotalComplex.lean index 73fb3959181c0..645d747de064f 100644 --- a/Mathlib/Algebra/Homology/TotalComplex.lean +++ b/Mathlib/Algebra/Homology/TotalComplex.lean @@ -260,7 +260,7 @@ noncomputable def ιTotal (i₁ : I₁) (i₂ : I₂) (i₁₂ : I₁₂) @[reassoc (attr := simp)] lemma XXIsoOfEq_hom_ιTotal {x₁ y₁ : I₁} (h₁ : x₁ = y₁) {x₂ y₂ : I₂} (h₂ : x₂ = y₂) (i₁₂ : I₁₂) (h : ComplexShape.π c₁ c₂ c₁₂ (y₁, y₂) = i₁₂) : - (K.XXIsoOfEq h₁ h₂).hom ≫ K.ιTotal c₁₂ y₁ y₂ i₁₂ h = + (K.XXIsoOfEq _ _ _ h₁ h₂).hom ≫ K.ιTotal c₁₂ y₁ y₂ i₁₂ h = K.ιTotal c₁₂ x₁ x₂ i₁₂ (by rw [h₁, h₂, h]) := by subst h₁ h₂ simp @@ -268,7 +268,7 @@ lemma XXIsoOfEq_hom_ιTotal {x₁ y₁ : I₁} (h₁ : x₁ = y₁) {x₂ y₂ : @[reassoc (attr := simp)] lemma XXIsoOfEq_inv_ιTotal {x₁ y₁ : I₁} (h₁ : x₁ = y₁) {x₂ y₂ : I₂} (h₂ : x₂ = y₂) (i₁₂ : I₁₂) (h : ComplexShape.π c₁ c₂ c₁₂ (x₁, x₂) = i₁₂) : - (K.XXIsoOfEq h₁ h₂).inv ≫ K.ιTotal c₁₂ x₁ x₂ i₁₂ h = + (K.XXIsoOfEq _ _ _ h₁ h₂).inv ≫ K.ιTotal c₁₂ x₁ x₂ i₁₂ h = K.ιTotal c₁₂ y₁ y₂ i₁₂ (by rw [← h, h₁, h₂]) := by subst h₁ h₂ simp diff --git a/Mathlib/Algebra/Homology/TotalComplexShift.lean b/Mathlib/Algebra/Homology/TotalComplexShift.lean index 8d32945310df2..345677aa57934 100644 --- a/Mathlib/Algebra/Homology/TotalComplexShift.lean +++ b/Mathlib/Algebra/Homology/TotalComplexShift.lean @@ -129,7 +129,7 @@ noncomputable def totalShift₁XIso (n n' : ℤ) (h : n + x = n') : (((shiftFunctor₁ C x).obj K).total (up ℤ)).X n ≅ (K.total (up ℤ)).X n' where hom := totalDesc _ (fun p q hpq => K.ιTotal (up ℤ) (p + x) q n' (by dsimp at hpq ⊢; omega)) inv := totalDesc _ (fun p q hpq => - (K.XXIsoOfEq (Int.sub_add_cancel p x) rfl).inv ≫ + (K.XXIsoOfEq _ _ _ (Int.sub_add_cancel p x) rfl).inv ≫ ((shiftFunctor₁ C x).obj K).ιTotal (up ℤ) (p - x) q n (by dsimp at hpq ⊢; omega)) hom_inv_id := by @@ -235,7 +235,7 @@ noncomputable def totalShift₂XIso (n n' : ℤ) (h : n + y = n') : hom := totalDesc _ (fun p q hpq => (p * y).negOnePow • K.ιTotal (up ℤ) p (q + y) n' (by dsimp at hpq ⊢; omega)) inv := totalDesc _ (fun p q hpq => (p * y).negOnePow • - (K.XXIsoOfEq rfl (Int.sub_add_cancel q y)).inv ≫ + (K.XXIsoOfEq _ _ _ rfl (Int.sub_add_cancel q y)).inv ≫ ((shiftFunctor₂ C y).obj K).ιTotal (up ℤ) p (q - y) n (by dsimp at hpq ⊢; omega)) hom_inv_id := by ext p q h diff --git a/Mathlib/Algebra/Lie/Abelian.lean b/Mathlib/Algebra/Lie/Abelian.lean index 9d26a486b09c5..1c88f3135e544 100644 --- a/Mathlib/Algebra/Lie/Abelian.lean +++ b/Mathlib/Algebra/Lie/Abelian.lean @@ -201,20 +201,21 @@ def maxTrivLinearMapEquivLieModuleHom : maxTrivSubmodule R L (M →ₗ[R] N) ≃ @[simp] theorem coe_maxTrivLinearMapEquivLieModuleHom (f : maxTrivSubmodule R L (M →ₗ[R] N)) : - (maxTrivLinearMapEquivLieModuleHom f : M → N) = f := by ext; rfl + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) f : M → N) = f := by ext; rfl @[simp] theorem coe_maxTrivLinearMapEquivLieModuleHom_symm (f : M →ₗ⁅R,L⁆ N) : - (maxTrivLinearMapEquivLieModuleHom.symm f : M → N) = f := + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) |>.symm f : M → N) = f := rfl @[simp] theorem coe_linearMap_maxTrivLinearMapEquivLieModuleHom (f : maxTrivSubmodule R L (M →ₗ[R] N)) : - (maxTrivLinearMapEquivLieModuleHom f : M →ₗ[R] N) = (f : M →ₗ[R] N) := by ext; rfl + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) f : M →ₗ[R] N) = (f : M →ₗ[R] N) := by + ext; rfl @[simp] theorem coe_linearMap_maxTrivLinearMapEquivLieModuleHom_symm (f : M →ₗ⁅R,L⁆ N) : - (maxTrivLinearMapEquivLieModuleHom.symm f : M →ₗ[R] N) = (f : M →ₗ[R] N) := + (maxTrivLinearMapEquivLieModuleHom (M := M) (N := N) |>.symm f : M →ₗ[R] N) = (f : M →ₗ[R] N) := rfl end LieModule diff --git a/Mathlib/Algebra/Lie/Basic.lean b/Mathlib/Algebra/Lie/Basic.lean index 40207bffb861a..cb37eac2841ca 100644 --- a/Mathlib/Algebra/Lie/Basic.lean +++ b/Mathlib/Algebra/Lie/Basic.lean @@ -269,10 +269,10 @@ attribute [coe] LieHom.toLinearMap instance : Coe (L₁ →ₗ⁅R⁆ L₂) (L₁ →ₗ[R] L₂) := ⟨LieHom.toLinearMap⟩ -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] } +instance : FunLike (L₁ →ₗ⁅R⁆ L₂) L₁ L₂ where + coe f := f.toFun + coe_injective' x y h := by + cases x; cases y; simp at h; simp [h] initialize_simps_projections LieHom (toFun → apply) @@ -471,13 +471,12 @@ instance hasCoeToLieHom : Coe (L₁ ≃ₗ⁅R⁆ L₂) (L₁ →ₗ⁅R⁆ L₂ instance hasCoeToLinearEquiv : Coe (L₁ ≃ₗ⁅R⁆ L₂) (L₁ ≃ₗ[R] L₂) := ⟨toLinearEquiv⟩ -instance : EquivLike (L₁ ≃ₗ⁅R⁆ L₂) L₁ L₂ := - { coe := fun f => f.toFun, - inv := fun f => f.invFun, - left_inv := fun f => f.left_inv, - right_inv := fun f => f.right_inv, - coe_injective' := fun f g h₁ h₂ => - by cases f; cases g; simp at h₁ h₂; simp [*] } +instance : EquivLike (L₁ ≃ₗ⁅R⁆ L₂) L₁ L₂ where + coe f := f.toFun + inv f := f.invFun + left_inv f := f.left_inv + right_inv f := f.right_inv + coe_injective' f g h₁ h₂ := by cases f; cases g; simp at h₁ h₂; simp [*] theorem coe_to_lieHom (e : L₁ ≃ₗ⁅R⁆ L₂) : ⇑(e : L₁ →ₗ⁅R⁆ L₂) = e := rfl @@ -622,10 +621,9 @@ attribute [coe] LieModuleHom.toLinearMap instance : CoeOut (M →ₗ⁅R,L⁆ N) (M →ₗ[R] N) := ⟨LieModuleHom.toLinearMap⟩ -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] } +instance : FunLike (M →ₗ⁅R, L⁆ N) M N where + coe f := f.toFun + coe_injective' x y h := by cases x; cases y; simp at h; simp [h] initialize_simps_projections LieModuleHom (toFun → apply) @@ -855,13 +853,12 @@ instance hasCoeToLieModuleHom : Coe (M ≃ₗ⁅R,L⁆ N) (M →ₗ⁅R,L⁆ N) instance hasCoeToLinearEquiv : CoeOut (M ≃ₗ⁅R,L⁆ N) (M ≃ₗ[R] N) := ⟨toLinearEquiv⟩ -instance : EquivLike (M ≃ₗ⁅R,L⁆ N) M N := - { coe := fun f => f.toFun, - inv := fun f => f.invFun, - left_inv := fun f => f.left_inv, - right_inv := fun f => f.right_inv, - coe_injective' := fun f g h₁ h₂ => - by cases f; cases g; simp at h₁ h₂; simp [*] } +instance : EquivLike (M ≃ₗ⁅R,L⁆ N) M N where + coe f := f.toFun + inv f := f.invFun + left_inv f := f.left_inv + right_inv f := f.right_inv + coe_injective' f g h₁ h₂ := by cases f; cases g; simp at h₁ h₂; simp [*] @[simp] lemma coe_coe (e : M ≃ₗ⁅R,L⁆ N) : ⇑(e : M →ₗ⁅R,L⁆ N) = e := rfl diff --git a/Mathlib/Algebra/Lie/CartanExists.lean b/Mathlib/Algebra/Lie/CartanExists.lean index bbdbc280d8416..5ee149734e3b5 100644 --- a/Mathlib/Algebra/Lie/CartanExists.lean +++ b/Mathlib/Algebra/Lie/CartanExists.lean @@ -39,7 +39,7 @@ variable [Module.Finite K L] variable [Module.Finite R L] [Module.Free R L] variable [Module.Finite R M] [Module.Free R M] -open FiniteDimensional LieSubalgebra Module.Free Polynomial +open Module LieSubalgebra Module.Free Polynomial variable (K) @@ -117,7 +117,7 @@ section Field variable {K L : Type*} [Field K] [LieRing L] [LieAlgebra K L] [Module.Finite K L] -open FiniteDimensional LieSubalgebra LieSubmodule Polynomial Cardinal LieModule engel_isBot_of_isMin +open Module LieSubalgebra LieSubmodule Polynomial Cardinal LieModule engel_isBot_of_isMin #adaptation_note /-- otherwise there is a spurious warning on `contrapose!` below. -/ set_option linter.unusedVariables false in @@ -164,13 +164,6 @@ lemma engel_isBot_of_isMin (hLK : finrank K L ≤ #K) (U : LieSubalgebra K L) -- viewed as endomorphism of `E`. Note that `χ` is polynomial in its argument `r`. -- Similarly: `ψ r` is the characteristic polynomial of `⁅r • u + x, _⁆` -- viewed as endomorphism of `Q`. Note that `ψ` is polynomial in its argument `r`. - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI := E.instLieRingModuleSubtypeMemSubmodule - letI : LieModule K U E := LieSubmodule.instLieModule E let χ : Polynomial (K[X]) := lieCharpoly K E x' u let ψ : Polynomial (K[X]) := lieCharpoly K Q x' u -- It suffices to show that `χ` is the monomial `X ^ r`. @@ -217,7 +210,7 @@ lemma engel_isBot_of_isMin (hLK : finrank K L ≤ #K) (U : LieSubalgebra K L) obtain hz₀|hz₀ := eq_or_ne z 0 · -- If `z = 0`, then `⁅α • u + x, x⁆` vanishes and we use our assumption `x ≠ 0`. refine ⟨⟨x, self_mem_engel K x⟩, ?_, ?_⟩ - · simpa [coe_bracket_of_module, ne_eq, Submodule.mk_eq_zero] using hx₀ + · exact Subtype.coe_ne_coe.mp hx₀ · dsimp only [z] at hz₀ simp only [coe_bracket_of_module, hz₀, LieHom.map_zero, LinearMap.zero_apply] -- If `z ≠ 0`, then `⁅α • u + x, z⁆` vanishes per axiom of Lie algebras @@ -367,7 +360,7 @@ lemma exists_isCartanSubalgebra_engel_of_finrank_le_card (h : finrank K L ≤ #K suffices finrank K (engel K x) ≤ finrank K (engel K y) by suffices engel K y = engel K x from this.ge apply LieSubalgebra.to_submodule_injective - exact eq_of_le_of_finrank_le hyx this + exact Submodule.eq_of_le_of_finrank_le hyx this rw [(isRegular_iff_finrank_engel_eq_rank K x).mp hx] apply rank_le_finrank_engel diff --git a/Mathlib/Algebra/Lie/Derivation/Killing.lean b/Mathlib/Algebra/Lie/Derivation/Killing.lean index f7aca54a214c2..65e346eb954d5 100644 --- a/Mathlib/Algebra/Lie/Derivation/Killing.lean +++ b/Mathlib/Algebra/Lie/Derivation/Killing.lean @@ -86,16 +86,10 @@ instance instIsKilling_range_ad : LieAlgebra.IsKilling R 𝕀 := /-- The restriction of the Killing form of a finite-dimensional Killing Lie algebra to the range of the adjoint action is nondegenerate. -/ -lemma killingForm_restrict_range_ad_nondegenerate : ((killingForm R 𝔻).restrict 𝕀).Nondegenerate := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI := LieDerivation.IsKilling.instIsKilling_range_ad R L - letI := LieSubalgebra.lieAlgebra R (LieDerivation R L L) (LieDerivation.ad R L).range - letI := LieSubalgebra.lieRing R (LieDerivation R L L) (LieDerivation.ad R L).range - killingForm_restrict_range_ad R L ▸ LieAlgebra.IsKilling.killingForm_nondegenerate R _ +lemma killingForm_restrict_range_ad_nondegenerate : + ((killingForm R 𝔻).restrict 𝕀).Nondegenerate := by + convert LieAlgebra.IsKilling.killingForm_nondegenerate R 𝕀 + exact killingForm_restrict_range_ad R L /-- The range of the adjoint action on a finite-dimensional Killing Lie algebra is full. -/ @[simp] diff --git a/Mathlib/Algebra/Lie/DirectSum.lean b/Mathlib/Algebra/Lie/DirectSum.lean index f4d73a8802ef0..973c229bb0534 100644 --- a/Mathlib/Algebra/Lie/DirectSum.lean +++ b/Mathlib/Algebra/Lie/DirectSum.lean @@ -157,14 +157,14 @@ def lieAlgebraOf [DecidableEq ι] (j : ι) : L j →ₗ⁅R⁆ ⨁ i, L i := erw [AddHom.coe_mk, single_apply, single_apply] · simp? [h] says simp only [h, ↓reduceDIte, single_apply] · intros - erw [single_add] + rw [single_add] · -- This used to be the end of the proof before leanprover/lean4#2644 -- with `simp [of, singleAddHom]` simp only [of, singleAddHom, bracket_apply] erw [AddHom.coe_mk, single_apply, single_apply] · simp only [h, dite_false, single_apply, lie_self] · intros - erw [single_add] } + rw [single_add] } /-- The projection map onto one component, as a morphism of Lie algebras. -/ @[simps] @@ -229,20 +229,10 @@ variable {L : Type w} [LieRing L] [LieAlgebra R L] (I : ι → LieIdeal R L) [this Zulip thread](https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/ Typeclass.20resolution.20under.20binders/near/245151099). -/ instance lieRingOfIdeals : LieRing (⨁ i, I i) := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : (i : ι) → LieRing (I i) := fun _ => LieIdeal.lieRing .. DirectSum.lieRing fun i => ↥(I i) /-- See `DirectSum.lieRingOfIdeals` comment. -/ instance lieAlgebraOfIdeals : LieAlgebra R (⨁ i, I i) := - #adaptation_note /-- After lean4#5020, many instances for Lie algebras and manifolds are no - longer found. -/ - letI : (i : ι) → LieAlgebra R (I i) := fun _ => LieIdeal.lieAlgebra .. - letI : (i : ι) → LieRing (I i) := fun _ => LieIdeal.lieRing .. DirectSum.lieAlgebra fun i => ↥(I i) end Ideals diff --git a/Mathlib/Algebra/Lie/EngelSubalgebra.lean b/Mathlib/Algebra/Lie/EngelSubalgebra.lean index 3a6654de89875..6720922dae1f2 100644 --- a/Mathlib/Algebra/Lie/EngelSubalgebra.lean +++ b/Mathlib/Algebra/Lie/EngelSubalgebra.lean @@ -113,12 +113,6 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] rwa [← lie_skew, neg_mem_iff (G := L)] have aux₂ : ∀ n ∈ N, ⁅x, n⁆ ∈ N := fun n hn ↦ le_normalizer H (aux₁ _ hn) let dx : N →ₗ[R] N := (ad R L x).restrict aux₂ - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - have : IsArtinian R { x // x ∈ N } := isArtinian_submodule' _ obtain ⟨k, hk⟩ : ∃ a, ∀ b ≥ a, Codisjoint (LinearMap.ker (dx ^ b)) (LinearMap.range (dx ^ b)) := eventually_atTop.mp <| dx.eventually_codisjoint_ker_pow_range_pow specialize hk (k+1) (Nat.le_add_right k 1) @@ -143,7 +137,7 @@ lemma normalizer_eq_self_of_engel_le [IsArtinian R L] rintro _ ⟨y, rfl⟩ simp only [pow_succ', LinearMap.mul_apply, Submodule.mem_comap, mem_coe_submodule] apply aux₁ - simp only [Submodule.coeSubtype, SetLike.coe_mem] + simp only [Submodule.coe_subtype, SetLike.coe_mem] /-- A Lie subalgebra of a Noetherian Lie algebra is nilpotent if it is contained in the Engel subalgebra of all its elements. -/ diff --git a/Mathlib/Algebra/Lie/IdealOperations.lean b/Mathlib/Algebra/Lie/IdealOperations.lean index 99a95d581f6e3..bcd4cad1d3887 100644 --- a/Mathlib/Algebra/Lie/IdealOperations.lean +++ b/Mathlib/Algebra/Lie/IdealOperations.lean @@ -175,7 +175,7 @@ theorem lie_sup : ⁅I, N ⊔ N'⁆ = ⁅I, N⁆ ⊔ ⁅I, N'⁆ := by apply mono_lie_right <;> [exact le_sup_left; exact le_sup_right] suffices ⁅I, N ⊔ N'⁆ ≤ ⁅I, N⁆ ⊔ ⁅I, N'⁆ by exact le_antisymm this h rw [lieIdeal_oper_eq_span, lieSpan_le]; rintro m ⟨x, ⟨n, hn⟩, h⟩; erw [LieSubmodule.mem_sup] - erw [LieSubmodule.mem_sup] at hn; rcases hn with ⟨n₁, hn₁, n₂, hn₂, hn'⟩ + rw [LieSubmodule.mem_sup] at hn; rcases hn with ⟨n₁, hn₁, n₂, hn₂, hn'⟩ use ⁅(x : L), (⟨n₁, hn₁⟩ : N)⁆; constructor; · apply lie_coe_mem_lie use ⁅(x : L), (⟨n₂, hn₂⟩ : N')⁆; constructor; · apply lie_coe_mem_lie simp [← h, ← hn'] @@ -187,7 +187,7 @@ theorem sup_lie : ⁅I ⊔ J, N⁆ = ⁅I, N⁆ ⊔ ⁅J, N⁆ := by apply mono_lie_left <;> [exact le_sup_left; exact le_sup_right] suffices ⁅I ⊔ J, N⁆ ≤ ⁅I, N⁆ ⊔ ⁅J, N⁆ by exact le_antisymm this h rw [lieIdeal_oper_eq_span, lieSpan_le]; rintro m ⟨⟨x, hx⟩, n, h⟩; erw [LieSubmodule.mem_sup] - erw [LieSubmodule.mem_sup] at hx; rcases hx with ⟨x₁, hx₁, x₂, hx₂, hx'⟩ + rw [LieSubmodule.mem_sup] at hx; rcases hx with ⟨x₁, hx₁, x₂, hx₂, hx'⟩ use ⁅((⟨x₁, hx₁⟩ : I) : L), (n : N)⁆; constructor; · apply lie_coe_mem_lie use ⁅((⟨x₂, hx₂⟩ : J) : L), (n : N)⁆; constructor; · apply lie_coe_mem_lie simp [← h, ← hx'] @@ -213,12 +213,6 @@ theorem map_bracket_eq [LieModule R L M] : map f ⁅I, N⁆ = ⁅I, map f N⁆ : exact ⟨x, ⟨f n, (mem_map (f n)).mpr ⟨n, hn, rfl⟩⟩, hm⟩ · rintro ⟨x, ⟨m₂, hm₂ : m₂ ∈ map f N⟩, rfl⟩ obtain ⟨n, hn, rfl⟩ := (mem_map m₂).mp hm₂ - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Bracket I M := LieRingModule.toBracket exact ⟨⁅x, n⁆, ⟨x, ⟨n, hn⟩, rfl⟩, by simp⟩ theorem comap_bracket_eq [LieModule R L M] (hf₁ : f.ker = ⊥) (hf₂ : N₂ ≤ f.range) : @@ -281,7 +275,7 @@ theorem comap_bracket_eq {J₁ J₂ : LieIdeal R L'} (h : f.IsIdealMorphism) : congr; simp only [LieHom.coe_toLinearMap, Set.mem_setOf_eq]; ext y constructor · rintro ⟨⟨x₁, hx₁⟩, ⟨x₂, hx₂⟩, hy⟩; rw [← hy] - erw [LieSubmodule.mem_inf, f.mem_idealRange_iff h] at hx₁ hx₂ + rw [LieSubmodule.mem_inf, f.mem_idealRange_iff h] at hx₁ hx₂ obtain ⟨⟨z₁, hz₁⟩, hz₁'⟩ := hx₁; rw [← hz₁] at hz₁' obtain ⟨⟨z₂, hz₂⟩, hz₂'⟩ := hx₂; rw [← hz₂] at hz₂' refine ⟨⁅z₁, z₂⁆, ⟨⟨z₁, hz₁'⟩, ⟨z₂, hz₂'⟩, rfl⟩, ?_⟩ diff --git a/Mathlib/Algebra/Lie/InvariantForm.lean b/Mathlib/Algebra/Lie/InvariantForm.lean index dea6e6da8c49d..e95fdc8b0f1bf 100644 --- a/Mathlib/Algebra/Lie/InvariantForm.lean +++ b/Mathlib/Algebra/Lie/InvariantForm.lean @@ -124,14 +124,14 @@ variable (hΦ_inv : Φ.lieInvariant L) (hΦ_refl : Φ.IsRefl) variable (hL : ∀ I : LieIdeal K L, IsAtom I → ¬IsLieAbelian I) include hΦ_nondeg hΦ_refl hL -open FiniteDimensional Submodule in +open Module Submodule in lemma orthogonal_isCompl_coe_submodule (I : LieIdeal K L) (hI : IsAtom I) : IsCompl I.toSubmodule (orthogonal Φ hΦ_inv I).toSubmodule := by rw [orthogonal_toSubmodule, LinearMap.BilinForm.isCompl_orthogonal_iff_disjoint hΦ_refl, ← orthogonal_toSubmodule _ hΦ_inv, ← LieSubmodule.disjoint_iff_coe_toSubmodule] exact orthogonal_disjoint Φ hΦ_nondeg hΦ_inv hL I hI -open FiniteDimensional Submodule in +open Module Submodule in lemma orthogonal_isCompl (I : LieIdeal K L) (hI : IsAtom I) : IsCompl I (orthogonal Φ hΦ_inv I) := by rw [LieSubmodule.isCompl_iff_coe_toSubmodule] @@ -151,7 +151,7 @@ lemma restrict_orthogonal_nondegenerate (I : LieIdeal K L) (hI : IsAtom I) : LinearMap.BilinForm.orthogonal_orthogonal hΦ_nondeg hΦ_refl] exact (orthogonal_isCompl_coe_submodule Φ hΦ_nondeg hΦ_inv hΦ_refl hL I hI).symm -open FiniteDimensional Submodule in +open Module Submodule in lemma atomistic : ∀ I : LieIdeal K L, sSup {J : LieIdeal K L | IsAtom J ∧ J ≤ I} = I := by intro I apply le_antisymm diff --git a/Mathlib/Algebra/Lie/Killing.lean b/Mathlib/Algebra/Lie/Killing.lean index ba952dab65ff0..4efe977e0587c 100644 --- a/Mathlib/Algebra/Lie/Killing.lean +++ b/Mathlib/Algebra/Lie/Killing.lean @@ -46,7 +46,7 @@ namespace LieAlgebra NB: This is not standard terminology (the literature does not seem to name Lie algebras with this property). -/ -class IsKilling : Prop := +class IsKilling : Prop where /-- We say a Lie algebra is Killing if its Killing form is non-singular. -/ killingCompl_top_eq_bot : LieIdeal.killingCompl R L ⊤ = ⊥ diff --git a/Mathlib/Algebra/Lie/Nilpotent.lean b/Mathlib/Algebra/Lie/Nilpotent.lean index fd18eb25f5cf4..84d773813fa84 100644 --- a/Mathlib/Algebra/Lie/Nilpotent.lean +++ b/Mathlib/Algebra/Lie/Nilpotent.lean @@ -412,13 +412,6 @@ lemma disjoint_lowerCentralSeries_maxTrivSubmodule_iff [IsNilpotent R L M] : suffices ¬ Nontrivial (lowerCentralSeriesLast R L M) by exact this (nontrivial_lowerCentralSeriesLast R L M) rw [h.eq_bot, le_bot_iff] at this - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI unique : Unique (⊥ : LieSubmodule R L M) := Submodule.uniqueBot - letI subsing : Subsingleton (⊥ : LieSubmodule R L M) := Unique.instSubsingleton exact this ▸ not_nontrivial _ theorem nontrivial_max_triv_of_isNilpotent [Nontrivial M] [IsNilpotent R L M] : @@ -595,18 +588,7 @@ theorem LieModule.isNilpotent_of_top_iff : Equiv.lieModule_isNilpotent_iff LieSubalgebra.topEquiv (1 : M ≃ₗ[R] M) fun _ _ => rfl @[simp] lemma LieModule.isNilpotent_of_top_iff' : - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : LieRingModule L (⊤ : LieSubmodule R L M) := - LieSubmodule.instLieRingModuleSubtypeMemSubmodule .. IsNilpotent R L {x // x ∈ (⊤ : LieSubmodule R L M)} ↔ IsNilpotent R L M := - letI : LieRingModule L (⊤ : LieSubmodule R L M) := - LieSubmodule.instLieRingModuleSubtypeMemSubmodule .. - letI : LieModule R L {x // x ∈ (⊤ : LieSubmodule R L M)} := - LieSubmodule.instLieModule ⊤ Equiv.lieModule_isNilpotent_iff 1 (LinearEquiv.ofTop ⊤ rfl) fun _ _ ↦ rfl end Morphisms @@ -662,10 +644,10 @@ theorem coe_lowerCentralSeries_ideal_quot_eq {I : LieIdeal R L} (k : ℕ) : ext x constructor · rintro ⟨⟨y, -⟩, ⟨z, hz⟩, rfl : ⁅y, z⁆ = x⟩ - erw [← LieSubmodule.mem_coeSubmodule, ih, LieSubmodule.mem_coeSubmodule] at hz + rw [← LieSubmodule.mem_coeSubmodule, ih, LieSubmodule.mem_coeSubmodule] at hz exact ⟨⟨LieSubmodule.Quotient.mk y, LieSubmodule.mem_top _⟩, ⟨z, hz⟩, rfl⟩ · rintro ⟨⟨⟨y⟩, -⟩, ⟨z, hz⟩, rfl : ⁅y, z⁆ = x⟩ - erw [← LieSubmodule.mem_coeSubmodule, ← ih, LieSubmodule.mem_coeSubmodule] at hz + rw [← LieSubmodule.mem_coeSubmodule, ← ih, LieSubmodule.mem_coeSubmodule] at hz exact ⟨⟨y, LieSubmodule.mem_top _⟩, ⟨z, hz⟩, rfl⟩ /-- Note that the below inequality can be strict. For example the ideal of strictly-upper-triangular diff --git a/Mathlib/Algebra/Lie/OfAssociative.lean b/Mathlib/Algebra/Lie/OfAssociative.lean index 5b5c5283887a5..10d1f4dcca458 100644 --- a/Mathlib/Algebra/Lie/OfAssociative.lean +++ b/Mathlib/Algebra/Lie/OfAssociative.lean @@ -300,7 +300,10 @@ theorem toEnd_comp_subtype_mem (m : M) (hm : m ∈ (N : Submodule R M)) : @[simp] theorem toEnd_restrict_eq_toEnd (h := N.toEnd_comp_subtype_mem x) : (toEnd R L M x).restrict h = toEnd R L N x := by - ext; simp only [LinearMap.restrict_apply, toEnd_apply_apply, ← coe_bracket] + ext + simp only [LinearMap.restrict_coe_apply, toEnd_apply_apply, ← coe_bracket, + SetLike.coe_eq_coe] + rfl lemma mapsTo_pow_toEnd_sub_algebraMap {φ : R} {k : ℕ} {x : L} : MapsTo ((toEnd R L M x - algebraMap R (Module.End R M) φ) ^ k) N N := by diff --git a/Mathlib/Algebra/Lie/Quotient.lean b/Mathlib/Algebra/Lie/Quotient.lean index cefd7b350bb49..86913a4a41213 100644 --- a/Mathlib/Algebra/Lie/Quotient.lean +++ b/Mathlib/Algebra/Lie/Quotient.lean @@ -111,7 +111,7 @@ instance lieQuotientHasBracket : Bracket (L ⧸ I) (L ⧸ I) := apply Quotient.liftOn₂' x y fun x' y' => mk ⁅x', y'⁆ intro x₁ x₂ y₁ y₂ h₁ h₂ apply (Submodule.Quotient.eq I.toSubmodule).2 - rw [Submodule.quotientRel_r_def] at h₁ h₂ + rw [Submodule.quotientRel_def] at h₁ h₂ have h : ⁅x₁, x₂⁆ - ⁅y₁, y₂⁆ = ⁅x₁, x₂ - y₂⁆ + ⁅x₁ - y₁, y₂⁆ := by simp [-lie_skew, sub_eq_add_neg, add_assoc] rw [h] diff --git a/Mathlib/Algebra/Lie/Rank.lean b/Mathlib/Algebra/Lie/Rank.lean index 3fabb5568a84c..c9c5877344913 100644 --- a/Mathlib/Algebra/Lie/Rank.lean +++ b/Mathlib/Algebra/Lie/Rank.lean @@ -65,13 +65,13 @@ lemma rank_eq_natTrailingDegree [Nontrivial R] [DecidableEq ι] : rank R L M = (polyCharpoly φ b).natTrailingDegree := by apply nilRank_eq_polyCharpoly_natTrailingDegree -open FiniteDimensional +open Module include bₘ in lemma rank_le_card [Nontrivial R] : rank R L M ≤ Fintype.card ιₘ := nilRank_le_card _ bₘ -open FiniteDimensional +open Module lemma rank_le_finrank [Nontrivial R] : rank R L M ≤ finrank R M := nilRank_le_finrank _ @@ -103,7 +103,7 @@ section IsDomain variable (L) variable [IsDomain R] -open Cardinal FiniteDimensional MvPolynomial in +open Cardinal Module MvPolynomial in lemma exists_isRegular_of_finrank_le_card (h : finrank R M ≤ #R) : ∃ x : L, IsRegular R M x := LinearMap.exists_isNilRegular_of_finrank_le_card _ h @@ -138,7 +138,7 @@ lemma rank_eq_natTrailingDegree [Nontrivial R] [DecidableEq ι] : rank R L = (polyCharpoly (ad R L).toLinearMap b).natTrailingDegree := by apply nilRank_eq_polyCharpoly_natTrailingDegree -open FiniteDimensional +open Module include b in lemma rank_le_card [Nontrivial R] : rank R L ≤ Fintype.card ι := @@ -175,7 +175,7 @@ section IsDomain variable (L) variable [IsDomain R] -open Cardinal FiniteDimensional MvPolynomial in +open Cardinal Module MvPolynomial in lemma exists_isRegular_of_finrank_le_card (h : finrank R L ≤ #R) : ∃ x : L, IsRegular R x := LinearMap.exists_isNilRegular_of_finrank_le_card _ h @@ -191,7 +191,7 @@ namespace LieAlgebra variable (K : Type*) {L : Type*} [Field K] [LieRing L] [LieAlgebra K L] [Module.Finite K L] -open FiniteDimensional LieSubalgebra +open Module LieSubalgebra lemma finrank_engel (x : L) : finrank K (engel K x) = (ad K L x).charpoly.natTrailingDegree := diff --git a/Mathlib/Algebra/Lie/Semisimple/Basic.lean b/Mathlib/Algebra/Lie/Semisimple/Basic.lean index 7768d66b3c772..ada8114afb6da 100644 --- a/Mathlib/Algebra/Lie/Semisimple/Basic.lean +++ b/Mathlib/Algebra/Lie/Semisimple/Basic.lean @@ -140,11 +140,12 @@ lemma isSimple_of_isAtom (I : LieIdeal R L) (hI : IsAtom I) : IsSimple R I where Submodule.mem_toAddSubmonoid] apply add_mem -- Now `⁅a, y⁆ ∈ J` since `a ∈ I`, `y ∈ J`, and `J` is an ideal of `I`. - · simp only [Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Submodule.coeSubtype, - Subtype.exists, exists_and_right, exists_eq_right, ha, lie_mem_left, exists_true_left] + · simp only [Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Subtype.exists] + erw [Submodule.coe_subtype] + simp only [exists_and_right, exists_eq_right, ha, lie_mem_left, exists_true_left] exact lie_mem_right R I J ⟨a, ha⟩ y hy -- Finally `⁅b, y⁆ = 0`, by the independence of the atoms. - · suffices ⁅b, y.val⁆ = 0 by simp only [this, zero_mem] + · suffices ⁅b, y.val⁆ = 0 by erw [this]; simp only [zero_mem] rw [← LieSubmodule.mem_bot (R := R) (L := L), ← (IsSemisimple.setIndependent_isAtom hI).eq_bot] exact ⟨lie_mem_right R L I b y y.2, lie_mem_left _ _ _ _ _ hb⟩ } @@ -157,7 +158,11 @@ lemma isSimple_of_isAtom (I : LieIdeal R L) (hI : IsAtom I) : IsSimple R I where rw [eq_bot_iff] at this ⊢ intro x hx suffices x ∈ J → x = 0 from this hx - simpa [J'] using @this x.1 + have := @this x.1 + simp only [LieIdeal.incl_coe, LieIdeal.coe_to_lieSubalgebra_to_submodule, + LieSubmodule.mem_mk_iff', Submodule.mem_map, LieSubmodule.mem_coeSubmodule, Subtype.exists, + LieSubmodule.mem_bot, ZeroMemClass.coe_eq_zero, forall_exists_index, and_imp, J'] at this + exact fun _ ↦ this (↑x) x.property hx rfl -- We need to show that `J = ⊥`. -- Since `J` is an ideal of `L`, and `I` is an atom, -- it suffices to show that `J < I`. @@ -276,7 +281,6 @@ instance (priority := 100) instHasTrivialRadical : HasTrivialRadical R L := by intro x y ext simp only [LieIdeal.coe_bracket_of_module, LieSubmodule.coe_bracket, ZeroMemClass.coe_zero] - letI : Bracket I I := LieRingModule.toBracket have : (⁅(⟨x, hJ' x.2⟩ : I), ⟨y, hJ' y.2⟩⁆ : I) = 0 := trivial_lie_zero _ _ _ _ apply_fun Subtype.val at this exact this @@ -302,14 +306,6 @@ theorem subsingleton_of_hasTrivialRadical_lie_abelian [HasTrivialRadical R L] [h theorem abelian_radical_of_hasTrivialRadical [HasTrivialRadical R L] : IsLieAbelian (radical R L) := by - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Unique (⊥ : LieIdeal R L) := Submodule.uniqueBot - letI : Subsingleton (⊥ : LieIdeal R L) := Unique.instSubsingleton - letI : LieModule.IsTrivial L (⊥ : LieIdeal R L) := LieModule.instIsTrivialOfSubsingleton' .. rw [HasTrivialRadical.radical_eq_bot]; exact LieIdeal.isLieAbelian_of_trivial .. /-- The two properties shown to be equivalent here are possible definitions for a Lie algebra diff --git a/Mathlib/Algebra/Lie/SkewAdjoint.lean b/Mathlib/Algebra/Lie/SkewAdjoint.lean index bf72da94b1715..4ba8facc11fda 100644 --- a/Mathlib/Algebra/Lie/SkewAdjoint.lean +++ b/Mathlib/Algebra/Lie/SkewAdjoint.lean @@ -126,10 +126,9 @@ def skewAdjointMatricesLieSubalgebraEquiv (P : Matrix n n R) (h : Invertible P) exact this simp [Matrix.IsSkewAdjoint, J.isAdjointPair_equiv _ _ P (isUnit_of_invertible P)] --- TODO(mathlib4#6607): fix elaboration so annotation on `A` isn't needed theorem skewAdjointMatricesLieSubalgebraEquiv_apply (P : Matrix n n R) (h : Invertible P) (A : skewAdjointMatricesLieSubalgebra J) : - ↑(skewAdjointMatricesLieSubalgebraEquiv J P h A) = P⁻¹ * (A : Matrix n n R) * P := by + ↑(skewAdjointMatricesLieSubalgebraEquiv J P h A) = P⁻¹ * A * P := by simp [skewAdjointMatricesLieSubalgebraEquiv] /-- An equivalence of matrix algebras commuting with the transpose endomorphisms restricts to an diff --git a/Mathlib/Algebra/Lie/Solvable.lean b/Mathlib/Algebra/Lie/Solvable.lean index 8633e9ede390b..1ce5fd8fdcf58 100644 --- a/Mathlib/Algebra/Lie/Solvable.lean +++ b/Mathlib/Algebra/Lie/Solvable.lean @@ -266,8 +266,8 @@ def radical := /-- The radical of a Noetherian Lie algebra is solvable. -/ instance radicalIsSolvable [IsNoetherian R L] : IsSolvable R (radical R L) := by - have hwf := (LieSubmodule.wellFoundedGT_of_noetherian R L L).wf - rw [← CompleteLattice.isSupClosedCompact_iff_wellFounded] at hwf + have hwf := LieSubmodule.wellFoundedGT_of_noetherian R L L + rw [← CompleteLattice.isSupClosedCompact_iff_wellFoundedGT] at hwf refine hwf { I : LieIdeal R L | IsSolvable R I } ⟨⊥, ?_⟩ fun I hI J hJ => ?_ · exact LieAlgebra.isSolvableBot R L · rw [Set.mem_setOf_eq] at hI hJ ⊢ @@ -287,12 +287,9 @@ instance [IsSolvable R L] : IsSolvable R (⊤ : LieSubalgebra R L) := by @[simp] lemma radical_eq_top_of_isSolvable [IsSolvable R L] : radical R L = ⊤ := by - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - rw [eq_top_iff]; exact le_sSup <| LieAlgebra.instIsSolvableSubtypeMemLieSubalgebraTop R L + rw [eq_top_iff] + have h : IsSolvable R (⊤ : LieSubalgebra R L) := inferInstance + exact le_sSup h /-- Given a solvable Lie ideal `I` with derived series `I = D₀ ≥ D₁ ≥ ⋯ ≥ Dₖ = ⊥`, this is the natural number `k` (the number of inclusions). @@ -338,6 +335,9 @@ noncomputable def derivedAbelianOfIdeal (I : LieIdeal R L) : LieIdeal R L := | 0 => ⊥ | k + 1 => derivedSeriesOfIdeal R L k I +instance : Unique {x // x ∈ (⊥ : LieIdeal R L)} := + inferInstanceAs <| Unique {x // x ∈ (⊥ : Submodule R L)} + theorem abelian_derivedAbelianOfIdeal (I : LieIdeal R L) : IsLieAbelian (derivedAbelianOfIdeal I) := by dsimp only [derivedAbelianOfIdeal] diff --git a/Mathlib/Algebra/Lie/Subalgebra.lean b/Mathlib/Algebra/Lie/Subalgebra.lean index 37990704ca9da..be459970fb977 100644 --- a/Mathlib/Algebra/Lie/Subalgebra.lean +++ b/Mathlib/Algebra/Lie/Subalgebra.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.Algebra.Lie.Basic -import Mathlib.RingTheory.Noetherian +import Mathlib.RingTheory.Artinian /-! # Lie subalgebras @@ -107,6 +107,9 @@ instance [SMul R₁ R] [Module R₁ L] [IsScalarTower R₁ R L] (L' : LieSubalge instance (L' : LieSubalgebra R L) [IsNoetherian R L] : IsNoetherian R L' := isNoetherian_submodule' _ +instance (L' : LieSubalgebra R L) [IsArtinian R L] : IsArtinian R L' := + isArtinian_submodule' _ + end /-- A Lie subalgebra forms a new Lie algebra. -/ @@ -221,7 +224,7 @@ variable [Module R M] `L`, we may regard `M` as a Lie module of `L'` by restriction. -/ instance lieModule [LieModule R L M] : LieModule R L' M where smul_lie t x m := by - rw [coe_bracket_of_module]; erw [smul_lie]; simp only [coe_bracket_of_module] + rw [coe_bracket_of_module, Submodule.coe_smul_of_tower, smul_lie, coe_bracket_of_module] lie_smul t x m := by simp only [coe_bracket_of_module, lie_smul] /-- An `L`-equivariant map of Lie modules `M → N` is `L'`-equivariant for any Lie subalgebra @@ -292,7 +295,7 @@ theorem rangeRestrict_apply (x : L) : f.rangeRestrict x = ⟨f x, f.mem_range_se theorem surjective_rangeRestrict : Function.Surjective f.rangeRestrict := by rintro ⟨y, hy⟩ - erw [mem_range] at hy; obtain ⟨x, rfl⟩ := hy + rw [mem_range] at hy; obtain ⟨x, rfl⟩ := hy use x simp only [Subtype.mk_eq_mk, rangeRestrict_apply] diff --git a/Mathlib/Algebra/Lie/Submodule.lean b/Mathlib/Algebra/Lie/Submodule.lean index 2fcf4d22646c5..1ce9ee98b69dc 100644 --- a/Mathlib/Algebra/Lie/Submodule.lean +++ b/Mathlib/Algebra/Lie/Submodule.lean @@ -72,12 +72,12 @@ instance : Zero (LieSubmodule R L M) := instance : Inhabited (LieSubmodule R L M) := ⟨0⟩ -instance coeSubmodule : CoeOut (LieSubmodule R L M) (Submodule R M) := +instance (priority := high) coeSort : CoeSort (LieSubmodule R L M) (Type w) where + coe N := { x : M // x ∈ N } + +instance (priority := mid) coeSubmodule : CoeOut (LieSubmodule R L M) (Submodule R M) := ⟨toSubmodule⟩ -instance instCanLiftSubmoduleLieSubmodule : CanLift (Submodule R M) (LieSubmodule R L M) (·) - (fun N ↦ ∀ {x : L} {m : M}, m ∈ N → ⁅x, m⁆ ∈ N) where - prf N hN := ⟨⟨N, hN⟩, rfl⟩ @[norm_cast] theorem coe_toSubmodule : ((N : Submodule R M) : Set M) = N := @@ -109,7 +109,7 @@ theorem mem_coe {x : M} : x ∈ (N : Set M) ↔ x ∈ N := protected theorem zero_mem : (0 : M) ∈ N := zero_mem N --- Porting note (#10618): @[simp] can prove this +@[simp] theorem mk_eq_zero {x} (h : x ∈ N) : (⟨x, h⟩ : N) = 0 ↔ x = 0 := Subtype.ext_iff_val @@ -156,17 +156,6 @@ instance : LieRingModule L N where lie_add := by intro x m n; apply SetCoe.ext; apply lie_add leibniz_lie := by intro x y m; apply SetCoe.ext; apply leibniz_lie -instance module' {S : Type*} [Semiring S] [SMul S R] [Module S M] [IsScalarTower S R M] : - Module S N := - N.toSubmodule.module' - -instance : Module R N := - N.toSubmodule.module - -instance {S : Type*} [Semiring S] [SMul S R] [SMul Sᵐᵒᵖ R] [Module S M] [Module Sᵐᵒᵖ M] - [IsScalarTower S R M] [IsScalarTower Sᵐᵒᵖ R M] [IsCentralScalar S M] : IsCentralScalar S N := - N.toSubmodule.isCentralScalar - @[simp, norm_cast] theorem coe_zero : ((0 : N) : M) = (0 : M) := rfl @@ -189,10 +178,19 @@ theorem coe_smul (t : R) (m : N) : (↑(t • m) : M) = t • (m : M) := @[simp, norm_cast] theorem coe_bracket (x : L) (m : N) : - letI : Bracket L N := LieRingModule.toBracket (↑⁅x, m⁆ : M) = ⁅x, ↑m⁆ := rfl +-- Copying instances from `Submodule` for correct discrimination keys +instance [IsNoetherian R M] (N : LieSubmodule R L M) : IsNoetherian R N := + inferInstanceAs <| IsNoetherian R N.toSubmodule + +instance [IsArtinian R M] (N : LieSubmodule R L M) : IsArtinian R N := + inferInstanceAs <| IsArtinian R N.toSubmodule + +instance [NoZeroSMulDivisors R M] : NoZeroSMulDivisors R N := + inferInstanceAs <| NoZeroSMulDivisors R N.toSubmodule + variable [LieAlgebra R L] [LieModule R L M] instance instLieModule : LieModule R L N where @@ -249,7 +247,6 @@ instance LieIdeal.lieRingModule {R L : Type*} [CommRing R] [LieRing L] [LieAlgeb @[simp] theorem LieIdeal.coe_bracket_of_module {R L : Type*} [CommRing R] [LieRing L] [LieAlgebra R L] (I : LieIdeal R L) [LieRingModule L M] (x : I) (m : M) : - letI : Bracket I M := LieRingModule.toBracket ⁅x, m⁆ = ⁅(↑x : L), m⁆ := LieSubalgebra.coe_bracket_of_module (I : LieSubalgebra R L) x m @@ -325,6 +322,9 @@ theorem coeSubmodule_le_coeSubmodule : (N : Submodule R M) ≤ N' ↔ N ≤ N' : instance : Bot (LieSubmodule R L M) := ⟨0⟩ +instance instUniqueBot : Unique (⊥ : LieSubmodule R L M) := + inferInstanceAs <| Unique (⊥ : Submodule R M) + @[simp] theorem bot_coe : ((⊥ : LieSubmodule R L M) : Set M) = {0} := rfl @@ -547,10 +547,11 @@ theorem mem_sup (x : M) : x ∈ N ⊔ N' ↔ ∃ y ∈ N, ∃ z ∈ N', y + z = nonrec theorem eq_bot_iff : N = ⊥ ↔ ∀ m : M, m ∈ N → m = 0 := by rw [eq_bot_iff]; exact Iff.rfl -instance subsingleton_of_bot : Subsingleton (LieSubmodule R L ↑(⊥ : LieSubmodule R L M)) := by +instance subsingleton_of_bot : Subsingleton (LieSubmodule R L (⊥ : LieSubmodule R L M)) := by apply subsingleton_of_bot_eq_top - ext ⟨x, hx⟩; change x ∈ ⊥ at hx; rw [Submodule.mem_bot] at hx; subst hx - simp only [eq_self_iff_true, Submodule.mk_eq_zero, LieSubmodule.mem_bot, mem_top] + ext ⟨_, hx⟩ + simp only [mem_bot, mk_eq_zero, mem_top, iff_true] + exact hx instance : IsModularLattice (LieSubmodule R L M) where sup_inf_le_assoc_of_le _ _ := by @@ -830,9 +831,9 @@ theorem comap_incl_eq_top : N₂.comap N.incl = ⊤ ↔ N ≤ N₂ := by LieSubmodule.top_coeSubmodule, Submodule.comap_subtype_eq_top, coeSubmodule_le_coeSubmodule] theorem comap_incl_eq_bot : N₂.comap N.incl = ⊥ ↔ N ⊓ N₂ = ⊥ := by - simp only [← LieSubmodule.coe_toSubmodule_eq_iff, LieSubmodule.coeSubmodule_comap, - LieSubmodule.incl_coe, LieSubmodule.bot_coeSubmodule, ← Submodule.disjoint_iff_comap_eq_bot, - disjoint_iff, inf_coe_toSubmodule] + simp only [← coe_toSubmodule_eq_iff, coeSubmodule_comap, incl_coe, bot_coeSubmodule, + inf_coe_toSubmodule] + rw [← Submodule.disjoint_iff_comap_eq_bot, disjoint_iff] @[mono] theorem map_mono (h : N ≤ N₂) : N.map f ≤ N₂.map f := @@ -987,9 +988,9 @@ same as ideals of `L` contained in `I`. -/ instance subsingleton_of_bot : Subsingleton (LieIdeal R (⊥ : LieIdeal R L)) := by apply subsingleton_of_bot_eq_top ext ⟨x, hx⟩ - rw [LieSubmodule.bot_coeSubmodule, Submodule.mem_bot] at hx + rw [LieSubmodule.mem_bot] at hx subst hx - simp only [Submodule.mk_eq_zero, LieSubmodule.mem_bot, LieSubmodule.mem_top] + simp only [LieSubmodule.mk_eq_zero, LieSubmodule.mem_bot, LieSubmodule.mem_top] end LieIdeal @@ -1274,11 +1275,11 @@ def range : LieSubmodule R L N := (LieSubmodule.map f ⊤).copy (Set.range f) Set.image_univ.symm @[simp] -theorem coe_range : (f.range : Set N) = Set.range f := +theorem coe_range : f.range = Set.range f := rfl @[simp] -theorem coeSubmodule_range : (f.range : Submodule R N) = LinearMap.range (f : M →ₗ[R] N) := +theorem coeSubmodule_range : f.range = LinearMap.range (f : M →ₗ[R] N) := rfl @[simp] @@ -1297,7 +1298,7 @@ def codRestrict (P : LieSubmodule R L N) (f : M →ₗ⁅R,L⁆ N) (h : ∀ m, f M →ₗ⁅R,L⁆ P where toFun := f.toLinearMap.codRestrict P h __ := f.toLinearMap.codRestrict P h - map_lie' {x m} := by ext; simp; rfl + map_lie' {x m} := by ext; simp @[simp] lemma codRestrict_apply (P : LieSubmodule R L N) (f : M →ₗ⁅R,L⁆ N) (h : ∀ m, f m ∈ P) (m : M) : @@ -1314,13 +1315,17 @@ variable [AddCommGroup M] [Module R M] [LieRingModule L M] variable (N : LieSubmodule R L M) @[simp] -theorem ker_incl : N.incl.ker = ⊥ := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem ker_incl : N.incl.ker = ⊥ := (LieModuleHom.ker_eq_bot N.incl).mpr <| injective_incl N @[simp] -theorem range_incl : N.incl.range = N := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem range_incl : N.incl.range = N := by + simp only [← coe_toSubmodule_eq_iff, LieModuleHom.coeSubmodule_range, incl_coe] + rw [Submodule.range_subtype] @[simp] -theorem comap_incl_self : comap N.incl N = ⊤ := by simp [← LieSubmodule.coe_toSubmodule_eq_iff] +theorem comap_incl_self : comap N.incl N = ⊤ := by + simp only [← coe_toSubmodule_eq_iff, coeSubmodule_comap, incl_coe, top_coeSubmodule] + rw [Submodule.comap_subtype_self] theorem map_incl_top : (⊤ : LieSubmodule R L N).map N.incl = N := by simp diff --git a/Mathlib/Algebra/Lie/TensorProduct.lean b/Mathlib/Algebra/Lie/TensorProduct.lean index c44b1b7b2474c..0fe6b3f7fb9e8 100644 --- a/Mathlib/Algebra/Lie/TensorProduct.lean +++ b/Mathlib/Algebra/Lie/TensorProduct.lean @@ -201,8 +201,8 @@ theorem lieIdeal_oper_eq_tensor_map_range : TensorProduct.map_range_eq_span_tmul, Submodule.map_span] congr; ext m; constructor · rintro ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩; use x ⊗ₜ n; constructor - · use ⟨x, hx⟩, ⟨n, hn⟩; simp + · use ⟨x, hx⟩, ⟨n, hn⟩; rfl · simp - · rintro ⟨t, ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩, h⟩; rw [← h]; use ⟨x, hx⟩, ⟨n, hn⟩; simp + · rintro ⟨t, ⟨⟨x, hx⟩, ⟨n, hn⟩, rfl⟩, h⟩; rw [← h]; use ⟨x, hx⟩, ⟨n, hn⟩; rfl end LieSubmodule diff --git a/Mathlib/Algebra/Lie/TraceForm.lean b/Mathlib/Algebra/Lie/TraceForm.lean index 06be6aac63a94..bddebc215744c 100644 --- a/Mathlib/Algebra/Lie/TraceForm.lean +++ b/Mathlib/Algebra/Lie/TraceForm.lean @@ -38,7 +38,7 @@ variable (R K L M : Type*) [CommRing R] [LieRing L] [LieAlgebra R L] local notation "φ" => LieModule.toEnd R L M open LinearMap (trace) -open Set FiniteDimensional +open Set Module namespace LieModule @@ -226,9 +226,9 @@ lemma traceForm_eq_sum_genWeightSpaceOf convert finite_genWeightSpaceOf_ne_bot R L M z exact LieSubmodule.coeSubmodule_eq_bot_iff (genWeightSpaceOf M _ _) classical - have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top - (LieSubmodule.independent_iff_coe_toSubmodule.mp <| independent_genWeightSpaceOf R L M z) - (IsTriangularizable.iSup_eq_top z) + have h := LieSubmodule.independent_iff_coe_toSubmodule.mp <| independent_genWeightSpaceOf R L M z + have hds := DirectSum.isInternal_submodule_of_independent_of_iSup_eq_top h <| by + simp [← LieSubmodule.iSup_coe_toSubmodule] simp only [LinearMap.coeFn_sum, Finset.sum_apply, traceForm_apply_apply, LinearMap.trace_eq_sum_trace_restrict' hds hfin hxy] exact Finset.sum_congr (by simp) (fun χ _ ↦ rfl) @@ -276,9 +276,9 @@ lemma lowerCentralSeries_one_inf_center_le_ker_traceForm [Module.Free R M] [Modu intro y exact y.induction_on rfl (fun a u ↦ by simp [hzc u]) (fun u v hu hv ↦ by simp [hu, hv]) apply LinearMap.trace_comp_eq_zero_of_commute_of_trace_restrict_eq_zero - · exact IsTriangularizable.iSup_eq_top (1 ⊗ₜ[R] x) + · simpa only [Module.End.maxGenEigenspace_def] using IsTriangularizable.iSup_eq_top (1 ⊗ₜ[R] x) · exact fun μ ↦ trace_toEnd_eq_zero_of_mem_lcs A (A ⊗[R] L) - (genWeightSpaceOf (A ⊗[R] M) μ (1 ⊗ₜ x)) (le_refl 1) hz + (genWeightSpaceOf (A ⊗[R] M) μ ((1:A) ⊗ₜ[R] x)) (le_refl 1) hz · exact commute_toEnd_of_mem_center_right (A ⊗[R] M) hzc (1 ⊗ₜ x) /-- A nilpotent Lie algebra with a representation whose trace form is non-singular is Abelian. -/ @@ -302,7 +302,10 @@ variable [IsDomain R] [IsPrincipalIdealRing R] lemma trace_eq_trace_restrict_of_le_idealizer (hy' : ∀ m ∈ N, (φ x ∘ₗ φ y) m ∈ N := fun m _ ↦ N.lie_mem (N.mem_idealizer.mp (h hy) m)) : trace R M (φ x ∘ₗ φ y) = trace R N ((φ x ∘ₗ φ y).restrict hy') := by - suffices ∀ m, ⁅x, ⁅y, m⁆⁆ ∈ N by simp [(φ x ∘ₗ φ y).trace_restrict_eq_of_forall_mem _ this] + suffices ∀ m, ⁅x, ⁅y, m⁆⁆ ∈ N by + have : (trace R { x // x ∈ N }) ((φ x ∘ₗ φ y).restrict _) = (trace R M) (φ x ∘ₗ φ y) := + (φ x ∘ₗ φ y).trace_restrict_eq_of_forall_mem _ this + simp [this] exact fun m ↦ N.lie_mem (h hy m) include h in @@ -322,14 +325,8 @@ lemma traceForm_eq_zero_of_isTrivial [LieModule.IsTrivial I N] : let hy' : ∀ m ∈ N, (φ x ∘ₗ φ y) m ∈ N := fun m _ ↦ N.lie_mem (N.mem_idealizer.mp (h hy) m) suffices (φ x ∘ₗ φ y).restrict hy' = 0 by simp [this, N.trace_eq_trace_restrict_of_le_idealizer I h x hy] - ext n + ext (n : N) suffices ⁅y, (n : M)⁆ = 0 by simp [this] - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Bracket I N := LieRingModule.toBracket exact Submodule.coe_eq_zero.mpr (LieModule.IsTrivial.trivial (⟨y, hy⟩ : I) n) end LieSubmodule @@ -395,7 +392,7 @@ lemma killingForm_eq : end LieIdeal -open LieModule FiniteDimensional +open LieModule Module open Submodule (span subset_span) namespace LieModule @@ -416,6 +413,8 @@ lemma traceForm_eq_sum_finrank_nsmul_mul (x y : L) : ← traceForm_genWeightSpace_eq K L M _ x y] rfl +/-- See also `LieModule.traceForm_eq_sum_finrank_nsmul'` for an expression omitting the zero +weights. -/ lemma traceForm_eq_sum_finrank_nsmul : traceForm K L M = ∑ χ : Weight K L M, finrank K (genWeightSpace M χ) • (χ : L →ₗ[K] K).smulRight (χ : L →ₗ[K] K) := by @@ -423,6 +422,21 @@ lemma traceForm_eq_sum_finrank_nsmul : rw [traceForm_eq_sum_finrank_nsmul_mul, ← Finset.sum_attach] simp +/-- A variant of `LieModule.traceForm_eq_sum_finrank_nsmul` in which the sum is taken only over the +non-zero weights. -/ +lemma traceForm_eq_sum_finrank_nsmul' : + traceForm K L M = ∑ χ in {χ : Weight K L M | χ.IsNonZero}, finrank K (genWeightSpace M χ) • + (χ : L →ₗ[K] K).smulRight (χ : L →ₗ[K] K) := by + classical + suffices ∑ χ in {χ : Weight K L M | χ.IsZero}, finrank K (genWeightSpace M χ) • + (χ : L →ₗ[K] K).smulRight (χ : L →ₗ[K] K) = 0 by + rw [traceForm_eq_sum_finrank_nsmul, + ← Finset.sum_filter_add_sum_filter_not (p := fun χ : Weight K L M ↦ χ.IsNonZero)] + simp [this] + refine Finset.sum_eq_zero fun χ hχ ↦ ?_ + replace hχ : (χ : L →ₗ[K] K) = 0 := by simpa [← Weight.coe_toLinear_eq_zero_iff] using hχ + simp [hχ] + -- The reverse inclusion should also hold: TODO prove this! lemma range_traceForm_le_span_weight : LinearMap.range (traceForm K L M) ≤ span K (range (Weight.toLinear K L M)) := by diff --git a/Mathlib/Algebra/Lie/Weights/Basic.lean b/Mathlib/Algebra/Lie/Weights/Basic.lean index d267162165c92..e0f030da4cacc 100644 --- a/Mathlib/Algebra/Lie/Weights/Basic.lean +++ b/Mathlib/Algebra/Lie/Weights/Basic.lean @@ -219,13 +219,6 @@ instance [Subsingleton M] : IsEmpty (Weight R L M) := ⟨fun h ↦ h.2 (Subsingleton.elim _ _)⟩ instance [Nontrivial (genWeightSpace M (0 : L → R))] : Zero (Weight R L M) := - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - letI : Unique (⊥ : LieSubmodule R L M) := Submodule.uniqueBot - letI : Subsingleton (⊥ : LieSubmodule R L M) := Unique.instSubsingleton ⟨0, fun e ↦ not_nontrivial (⊥ : LieSubmodule R L M) (e ▸ ‹_›)⟩ @[simp] @@ -254,6 +247,8 @@ abbrev IsNonZero (χ : Weight R L M) := ¬ IsZero (χ : Weight R L M) lemma isNonZero_iff_ne_zero [Nontrivial (genWeightSpace M (0 : L → R))] {χ : Weight R L M} : χ.IsNonZero ↔ χ ≠ 0 := isZero_iff_eq_zero.not +noncomputable instance : DecidablePred (IsNonZero (R := R) (L := L) (M := M)) := Classical.decPred _ + variable (R L M) in /-- The set of weights is equivalent to a subtype. -/ def equivSetOf : Weight R L M ≃ {χ : L → R | genWeightSpace M χ ≠ ⊥} where @@ -330,7 +325,9 @@ lemma isNilpotent_toEnd_sub_algebraMap [IsNoetherian R M] (χ : L → R) (x : L) obtain ⟨k, hk⟩ := exists_genWeightSpace_le_ker_of_isNoetherian M χ x use k ext ⟨m, hm⟩ - simpa [this, LinearMap.pow_restrict _, LinearMap.restrict_apply] using hk hm + simp only [this, LinearMap.pow_restrict _, LinearMap.zero_apply, ZeroMemClass.coe_zero, + ZeroMemClass.coe_eq_zero] + exact ZeroMemClass.coe_eq_zero.mp (hk hm) /-- A (nilpotent) Lie algebra acts nilpotently on the zero weight space of a Noetherian Lie module. -/ @@ -590,12 +587,7 @@ private lemma isCompl_genWeightSpace_zero_posFittingComp_aux · suffices IsNilpotent R L M by simp [M₀, M₁, isCompl_top_bot] replace h : M₀ = ⊤ := by simpa [M₀, genWeightSpace] rw [← LieModule.isNilpotent_of_top_iff', ← h] - #adaptation_note - /-- - After lean4#5020, many instances for Lie algebras and manifolds are no longer found. - See https://leanprover.zulipchat.com/#narrow/stream/428973-nightly-testing/topic/.2316244.20adaptations.20for.20nightly-2024-08-28/near/466219124 - -/ - exact LieModule.instIsNilpotentSubtypeMemSubmoduleGenWeightSpaceOfNatForallOfIsNoetherian M + infer_instance · set M₀ₓ := genWeightSpaceOf M (0 : R) x set M₁ₓ := posFittingCompOf R M x set M₀ₓ₀ := genWeightSpace M₀ₓ (0 : L → R) @@ -715,13 +707,11 @@ lemma independent_genWeightSpaceOf [NoZeroSMulDivisors R M] (x : L) : lemma finite_genWeightSpaceOf_ne_bot [NoZeroSMulDivisors R M] [IsNoetherian R M] (x : L) : {χ : R | genWeightSpaceOf M χ x ≠ ⊥}.Finite := - CompleteLattice.WellFounded.finite_ne_bot_of_independent - IsWellFounded.wf (independent_genWeightSpaceOf R L M x) + CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent (independent_genWeightSpaceOf R L M x) lemma finite_genWeightSpace_ne_bot [NoZeroSMulDivisors R M] [IsNoetherian R M] : {χ : L → R | genWeightSpace M χ ≠ ⊥}.Finite := - CompleteLattice.WellFounded.finite_ne_bot_of_independent - IsWellFounded.wf (independent_genWeightSpace R L M) + CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent (independent_genWeightSpace R L M) instance Weight.instFinite [NoZeroSMulDivisors R M] [IsNoetherian R M] : Finite (Weight R L M) := by @@ -734,7 +724,7 @@ noncomputable instance Weight.instFintype [NoZeroSMulDivisors R M] [IsNoetherian /-- A Lie module `M` of a Lie algebra `L` is triangularizable if the endomorhpism of `M` defined by any `x : L` is triangularizable. -/ -class IsTriangularizable : Prop := +class IsTriangularizable : Prop where iSup_eq_top : ∀ x, ⨆ φ, ⨆ k, (toEnd R L M x).genEigenspace φ k = ⊤ instance (L' : LieSubalgebra R L) [IsTriangularizable R L M] : IsTriangularizable R L' M where @@ -755,7 +745,7 @@ lemma iSup_genWeightSpaceOf_eq_top [IsTriangularizable R L M] (x : L) : simp_rw [Module.End.maxGenEigenspace_def] exact IsTriangularizable.iSup_eq_top x -open LinearMap FiniteDimensional in +open LinearMap Module in @[simp] lemma trace_toEnd_genWeightSpace [IsDomain R] [IsPrincipalIdealRing R] [Module.Free R M] [Module.Finite R M] (χ : L → R) (x : L) : @@ -769,7 +759,7 @@ lemma trace_toEnd_genWeightSpace [IsDomain R] [IsPrincipalIdealRing R] section field -open FiniteDimensional +open Module variable (K) variable [Field K] [LieAlgebra K L] [Module K M] [LieModule K L M] [LieAlgebra.IsNilpotent K L] @@ -788,37 +778,12 @@ instance (N : LieSubmodule K L M) [IsTriangularizable K L M] : IsTriangularizabl See also `LieModule.iSup_genWeightSpace_eq_top'`. -/ lemma iSup_genWeightSpace_eq_top [IsTriangularizable K L M] : ⨆ χ : L → K, genWeightSpace M χ = ⊤ := by - generalize h_dim : finrank K M = n - induction n using Nat.strongRecOn generalizing M with | ind n ih => ?_ - obtain h' | ⟨y : L, hy : ¬ ∃ φ, genWeightSpaceOf M φ y = ⊤⟩ := - forall_or_exists_not (fun (x : L) ↦ ∃ (φ : K), genWeightSpaceOf M φ x = ⊤) - · choose χ hχ using h' - replace hχ : genWeightSpace M χ = ⊤ := by simpa only [genWeightSpace, hχ] using iInf_top - exact eq_top_iff.mpr <| hχ ▸ le_iSup (genWeightSpace M) χ - · replace hy : ∀ φ, finrank K (genWeightSpaceOf M φ y) < n := fun φ ↦ by - simp_rw [not_exists, ← lt_top_iff_ne_top] at hy; exact h_dim ▸ Submodule.finrank_lt (hy φ) - replace ih : ∀ φ, ⨆ χ : L → K, genWeightSpace (genWeightSpaceOf M φ y) χ = ⊤ := - fun φ ↦ ih _ (hy φ) (genWeightSpaceOf M φ y) rfl - replace ih : ∀ φ, ⨆ (χ : L → K) (_ : χ y = φ), - genWeightSpace (genWeightSpaceOf M φ y) χ = ⊤ := by - intro φ - suffices ∀ χ : L → K, χ y ≠ φ → genWeightSpace (genWeightSpaceOf M φ y) χ = ⊥ by - specialize ih φ; rw [iSup_split, biSup_congr this] at ih; simpa using ih - intro χ hχ - rw [eq_bot_iff, ← (genWeightSpaceOf M φ y).ker_incl, LieModuleHom.ker, - ← LieSubmodule.map_le_iff_le_comap, map_genWeightSpace_eq_of_injective - (genWeightSpaceOf M φ y).injective_incl, LieSubmodule.range_incl, ← disjoint_iff_inf_le] - exact (disjoint_genWeightSpaceOf K L M hχ).mono_left - (genWeightSpace_le_genWeightSpaceOf M y χ) - replace ih : ∀ φ, ⨆ (χ : L → K) (_ : χ y = φ), genWeightSpace M χ = genWeightSpaceOf M φ y := by - intro φ - have (χ : L → K) (hχ : χ y = φ) : genWeightSpace M χ = - (genWeightSpace (genWeightSpaceOf M φ y) χ).map (genWeightSpaceOf M φ y).incl := by - rw [← hχ, genWeightSpace_genWeightSpaceOf_map_incl] - simp_rw [biSup_congr this, ← LieSubmodule.map_iSup, ih, LieModuleHom.map_top, - LieSubmodule.range_incl] - simpa only [← ih, iSup_comm (ι := K), iSup_iSup_eq_right] using - iSup_genWeightSpaceOf_eq_top K L M y + simp only [← LieSubmodule.coe_toSubmodule_eq_iff, LieSubmodule.iSup_coe_toSubmodule, + LieSubmodule.iInf_coe_toSubmodule, LieSubmodule.top_coeSubmodule, genWeightSpace] + refine Module.End.iSup_iInf_maxGenEigenspace_eq_top_of_forall_mapsTo (toEnd K L M) + (fun x y φ z ↦ (genWeightSpaceOf M φ y).lie_mem) ?_ + simp_rw [Module.End.maxGenEigenspace_def] + apply IsTriangularizable.iSup_eq_top lemma iSup_genWeightSpace_eq_top' [IsTriangularizable K L M] : ⨆ χ : Weight K L M, genWeightSpace M χ = ⊤ := by diff --git a/Mathlib/Algebra/Lie/Weights/Cartan.lean b/Mathlib/Algebra/Lie/Weights/Cartan.lean index 152536e842483..0ef812f460f9e 100644 --- a/Mathlib/Algebra/Lie/Weights/Cartan.lean +++ b/Mathlib/Algebra/Lie/Weights/Cartan.lean @@ -88,7 +88,7 @@ def rootSpaceWeightSpaceProductAux {χ₁ χ₂ χ₃ : H → R} (hχ : χ₁ + { toFun := fun m => ⟨⁅(x : L), (m : M)⁆, hχ ▸ lie_mem_genWeightSpace_of_mem_genWeightSpace x.property m.property⟩ - map_add' := fun m n => by simp only [Submodule.coe_add, lie_add, AddMemClass.mk_add_mk] + map_add' := fun m n => by simp only [LieSubmodule.coe_add, lie_add, AddMemClass.mk_add_mk] map_smul' := fun t m => by dsimp only conv_lhs => @@ -97,7 +97,7 @@ def rootSpaceWeightSpaceProductAux {χ₁ χ₂ χ₃ : H → R} (hχ : χ₁ + rfl } map_add' x y := by ext m - simp only [Submodule.coe_add, add_lie, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.add_apply, + simp only [LieSubmodule.coe_add, add_lie, LinearMap.coe_mk, AddHom.coe_mk, LinearMap.add_apply, AddMemClass.mk_add_mk] map_smul' t x := by simp only [RingHom.id_apply] @@ -117,7 +117,6 @@ def rootSpaceWeightSpaceProduct (χ₁ χ₂ χ₃ : H → R) (hχ : χ₁ + χ ext m simp only [rootSpaceWeightSpaceProductAux] dsimp - repeat rw [LieSubmodule.coe_bracket] simp only [LieSubalgebra.coe_bracket_of_module, lie_lie] } @[simp] @@ -271,7 +270,9 @@ lemma mem_corootSpace {x : H} : have : x ∈ corootSpace α ↔ (x : L) ∈ LieSubmodule.map H.toLieSubmodule.incl (corootSpace α) := by rw [corootSpace] - simpa using exists_congr fun _ ↦ H.toLieSubmodule.injective_incl.eq_iff.symm + simp only [rootSpaceProduct_def, LieModuleHom.mem_range, LieSubmodule.mem_map, + LieSubmodule.incl_apply, SetLike.coe_eq_coe, exists_eq_right] + rfl simp_rw [this, corootSpace, ← LieModuleHom.map_top, ← LieSubmodule.mem_coeSubmodule, LieSubmodule.coeSubmodule_map, LieSubmodule.top_coeSubmodule, ← TensorProduct.span_tmul_eq_top, LinearMap.map_span, Set.image, Set.mem_setOf_eq, exists_exists_exists_and_eq] @@ -288,9 +289,9 @@ lemma mem_corootSpace' {x : H} : erw [← (H : Submodule R L).injective_subtype.mem_set_image (s := Submodule.span R s)] rw [mem_image] simp_rw [SetLike.mem_coe] - rw [← Submodule.mem_map, Submodule.coeSubtype, Submodule.map_span, mem_corootSpace, ← this] + rw [← Submodule.mem_map, Submodule.coe_subtype, Submodule.map_span, mem_corootSpace, ← this] ext u - simp only [Submodule.coeSubtype, mem_image, Subtype.exists, LieSubalgebra.mem_coe_submodule, + simp only [Submodule.coe_subtype, mem_image, Subtype.exists, LieSubalgebra.mem_coe_submodule, exists_and_right, exists_eq_right, mem_setOf_eq, s] refine ⟨fun ⟨_, y, hy, z, hz, hyz⟩ ↦ ⟨y, hy, z, hz, hyz⟩, fun ⟨y, hy, z, hz, hyz⟩ ↦ ⟨?_, y, hy, z, hz, hyz⟩⟩ diff --git a/Mathlib/Algebra/Lie/Weights/Chain.lean b/Mathlib/Algebra/Lie/Weights/Chain.lean index 4207a1056e76d..428b6ff73884c 100644 --- a/Mathlib/Algebra/Lie/Weights/Chain.lean +++ b/Mathlib/Algebra/Lie/Weights/Chain.lean @@ -41,7 +41,7 @@ We provide basic definitions and results to support `α`-chain techniques in thi -/ -open FiniteDimensional Function Set +open Module Function Set variable {R L : Type*} [CommRing R] [LieRing L] [LieAlgebra R L] (M : Type*) [AddCommGroup M] [Module R M] [LieRingModule L M] [LieModule R L M] @@ -212,11 +212,16 @@ lemma exists_forall_mem_corootSpace_smul_add_eq_zero have h₃ : genWeightSpaceChain M α χ p q = ⨆ i ∈ Finset.Ioo p q, N i := by simp_rw [genWeightSpaceChain_def', LieSubmodule.iSup_coe_toSubmodule] rw [← trace_toEnd_genWeightSpaceChain_eq_zero M α χ p q hp hq hx, - ← LieSubmodule.toEnd_restrict_eq_toEnd, - LinearMap.trace_eq_sum_trace_restrict_of_eq_biSup _ h₁ h₂ (genWeightSpaceChain M α χ p q) h₃] + ← LieSubmodule.toEnd_restrict_eq_toEnd] + -- The lines below illustrate the cost of treating `LieSubmodule` as both a + -- `Submodule` and a `LieSubmodule` simultaneously. + erw [LinearMap.trace_eq_sum_trace_restrict_of_eq_biSup _ h₁ h₂ (genWeightSpaceChain M α χ p q) h₃] + simp_rw [LieSubmodule.toEnd_restrict_eq_toEnd] dsimp [N] - simp_rw [LieSubmodule.toEnd_restrict_eq_toEnd, - trace_toEnd_genWeightSpace, Pi.add_apply, Pi.smul_apply, smul_add, ← smul_assoc, + convert_to _ = + ∑ k ∈ Finset.Ioo p q, (LinearMap.trace R { x // x ∈ (genWeightSpace M (k • α + χ)) }) + ((toEnd R { x // x ∈ H } { x // x ∈ genWeightSpace M (k • α + χ) }) x) + simp_rw [trace_toEnd_genWeightSpace, Pi.add_apply, Pi.smul_apply, smul_add, ← smul_assoc, Finset.sum_add_distrib, ← Finset.sum_smul, natCast_zsmul] end IsCartanSubalgebra diff --git a/Mathlib/Algebra/Lie/Weights/Killing.lean b/Mathlib/Algebra/Lie/Weights/Killing.lean index 30db9a4835dcf..80e8ca2ed6bf3 100644 --- a/Mathlib/Algebra/Lie/Weights/Killing.lean +++ b/Mathlib/Algebra/Lie/Weights/Killing.lean @@ -85,7 +85,7 @@ end IsKilling section Field -open FiniteDimensional LieModule Set +open Module LieModule Set open Submodule (span subset_span) variable [FiniteDimensional K L] (H : LieSubalgebra K L) [H.IsCartanSubalgebra] @@ -534,7 +534,9 @@ lemma _root_.IsSl2Triple.h_eq_coroot {α : Weight K H L} (hα : α.IsNonZero) lemma finrank_rootSpace_eq_one (α : Weight K H L) (hα : α.IsNonZero) : finrank K (rootSpace H α) = 1 := by suffices ¬ 1 < finrank K (rootSpace H α) by - have h₀ : finrank K (rootSpace H α) ≠ 0 := by simpa using α.genWeightSpace_ne_bot + have h₀ : finrank K (rootSpace H α) ≠ 0 := by + convert_to finrank K (rootSpace H α).toSubmodule ≠ 0 + simpa using α.genWeightSpace_ne_bot omega intro contra obtain ⟨h, e, f, ht, heα, hfα⟩ := exists_isSl2Triple_of_weight_isNonZero hα @@ -545,7 +547,7 @@ lemma finrank_rootSpace_eq_one (α : Weight K H L) (hα : α.IsNonZero) : have : killingForm K L y f = 0 := by simpa [F, traceForm_comm] using hy simpa [this] using lie_eq_killingForm_smul_of_mem_rootSpace_of_mem_rootSpace_neg hyα hfα have P : ht.symm.HasPrimitiveVectorWith y (-2 : K) := - { ne_zero := by simpa using hy₀ + { ne_zero := by simpa [LieSubmodule.mk_eq_zero] using hy₀ lie_h := by simp only [neg_smul, neg_lie, neg_inj, ht.h_eq_coroot hα heα hfα, ← H.coe_bracket_of_module, lie_eq_smul_of_mem_rootSpace hyα (coroot α), root_apply_coroot hα] @@ -554,6 +556,16 @@ lemma finrank_rootSpace_eq_one (α : Weight K H L) (hα : α.IsNonZero) : replace hn : -2 = (n : ℤ) := by norm_cast at hn omega +/-- The collection of roots as a `Finset`. -/ +noncomputable abbrev _root_.LieSubalgebra.root : Finset (Weight K H L) := {α | α.IsNonZero} + +lemma restrict_killingForm_eq_sum : + (killingForm K L).restrict H = ∑ α in H.root, (α : H →ₗ[K] K).smulRight (α : H →ₗ[K] K) := by + rw [restrict_killingForm, traceForm_eq_sum_finrank_nsmul' K H L] + refine Finset.sum_congr rfl fun χ hχ ↦ ?_ + replace hχ : χ.IsNonZero := by simpa [LieSubalgebra.root] using hχ + simp [finrank_rootSpace_eq_one _ hχ] + end CharZero end IsKilling diff --git a/Mathlib/Algebra/Lie/Weights/Linear.lean b/Mathlib/Algebra/Lie/Weights/Linear.lean index bc9f294cf35e7..741b68fdabb92 100644 --- a/Mathlib/Algebra/Lie/Weights/Linear.lean +++ b/Mathlib/Algebra/Lie/Weights/Linear.lean @@ -48,7 +48,7 @@ namespace LieModule /-- A typeclass encoding the fact that a given Lie module has linear weights, vanishing on the derived ideal. -/ -class LinearWeights [LieAlgebra.IsNilpotent R L] : Prop := +class LinearWeights [LieAlgebra.IsNilpotent R L] : Prop where map_add : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ x y, χ (x + y) = χ x + χ y map_smul : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ (t : R) x, χ (t • x) = t • χ x map_lie : ∀ χ : L → R, genWeightSpace M χ ≠ ⊥ → ∀ x y : L, χ ⁅x, y⁆ = 0 @@ -114,7 +114,7 @@ instance instLinearWeightsOfIsLieAbelian [IsLieAbelian L] [NoZeroSMulDivisors R section FiniteDimensional -open FiniteDimensional +open Module variable [IsDomain R] [IsPrincipalIdealRing R] [Module.Free R M] [Module.Finite R M] [LieAlgebra.IsNilpotent R L] @@ -239,9 +239,9 @@ lemma exists_forall_lie_eq_smul [LinearWeights R L M] [IsNoetherian R M] (χ : W (LieSubmodule.nontrivial_iff_ne_bot R L M).mpr χ.genWeightSpace_ne_bot obtain ⟨⟨⟨m, _⟩, hm₁⟩, hm₂⟩ := @exists_ne _ (nontrivial_max_triv_of_isNilpotent R L (shiftedGenWeightSpace R L M χ)) 0 - simp_rw [LieSubmodule.mem_coeSubmodule, mem_maxTrivSubmodule, Subtype.ext_iff, + simp_rw [mem_maxTrivSubmodule, Subtype.ext_iff, ZeroMemClass.coe_zero] at hm₁ - refine ⟨m, by simpa using hm₂, ?_⟩ + refine ⟨m, by simpa [LieSubmodule.mk_eq_zero] using hm₂, ?_⟩ intro x have := hm₁ x rwa [coe_lie_shiftedGenWeightSpace_apply, sub_eq_zero] at this diff --git a/Mathlib/Algebra/Lie/Weights/RootSystem.lean b/Mathlib/Algebra/Lie/Weights/RootSystem.lean index f306237f00379..d2a8a94210cd9 100644 --- a/Mathlib/Algebra/Lie/Weights/RootSystem.lean +++ b/Mathlib/Algebra/Lie/Weights/RootSystem.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.Algebra.Lie.Weights.Killing import Mathlib.LinearAlgebra.RootSystem.Basic +import Mathlib.LinearAlgebra.RootSystem.Finite.CanonicalBilinear import Mathlib.Algebra.Algebra.Rat /-! @@ -376,7 +377,7 @@ variable (H) /-- The root system of a finite-dimensional Lie algebra with non-degenerate Killing form over a field of characteristic zero, relative to a splitting Cartan subalgebra. -/ def rootSystem : - RootSystem {α : Weight K H L // α.IsNonZero} K (Dual K H) H := + RootSystem H.root K (Dual K H) H := RootSystem.mk' IsReflexive.toPerfectPairingDual { toFun := (↑) @@ -384,14 +385,20 @@ def rootSystem : intro α β h; ext x; simpa using LinearMap.congr_fun h x } { toFun := coroot ∘ (↑) inj' := by rintro ⟨α, hα⟩ ⟨β, hβ⟩ h; simpa using h } - (fun α ↦ by simpa using root_apply_coroot α.property) + (fun ⟨α, hα⟩ ↦ by simpa using root_apply_coroot <| by simpa using hα) (by rintro ⟨α, hα⟩ - ⟨⟨β, hβ⟩, rfl⟩ simp only [Function.Embedding.coeFn_mk, IsReflexive.toPerfectPairingDual_toLin, Function.comp_apply, Set.mem_range, Subtype.exists, exists_prop] - exact ⟨reflectRoot α β, reflectRoot_isNonZero α β hβ, rfl⟩) + exact ⟨reflectRoot α β, (by simpa using reflectRoot_isNonZero α β <| by simpa using hβ), rfl⟩) (by convert span_weight_isNonZero_eq_top K L H; ext; simp) +@[simp] +lemma corootForm_rootSystem_eq_killing : + (rootSystem H).CorootForm = (killingForm K L).restrict H := by + rw [restrict_killingForm_eq_sum, RootPairing.CorootForm, ← Finset.sum_coe_sort (s := H.root)] + rfl + @[simp] lemma rootSystem_toPerfectPairing_apply (f x) : (rootSystem H).toPerfectPairing f x = f x := rfl @[deprecated (since := "2024-09-09")] @@ -405,12 +412,12 @@ theorem isCrystallographic_rootSystem : (rootSystem H).IsCrystallographic := by exact ⟨chainBotCoeff β.1 α.1 - chainTopCoeff β.1 α.1, by simp [apply_coroot_eq_cast β.1 α.1]⟩ theorem isReduced_rootSystem : (rootSystem H).IsReduced := by - intro α β e + intro ⟨α, hα⟩ ⟨β, hβ⟩ e rw [LinearIndependent.pair_iff' ((rootSystem H).ne_zero _), not_forall] at e simp only [Nat.succ_eq_add_one, Nat.reduceAdd, rootSystem_root_apply, ne_eq, not_not] at e obtain ⟨u, hu⟩ := e obtain (h | h) := - eq_neg_or_eq_of_eq_smul α.1 β.1 β.2 u (by ext x; exact DFunLike.congr_fun hu.symm x) + eq_neg_or_eq_of_eq_smul α β (by simpa using hβ) u (by ext x; exact DFunLike.congr_fun hu.symm x) · right; ext x; simpa [neg_eq_iff_eq_neg] using DFunLike.congr_fun h.symm x · left; ext x; simpa using DFunLike.congr_fun h.symm x diff --git a/Mathlib/Algebra/ModEq.lean b/Mathlib/Algebra/ModEq.lean index 8c4bcc0fd4def..a275aad2c7254 100644 --- a/Mathlib/Algebra/ModEq.lean +++ b/Mathlib/Algebra/ModEq.lean @@ -5,6 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Data.Int.ModEq import Mathlib.Algebra.Field.Basic +import Mathlib.Algebra.Order.Ring.Int import Mathlib.GroupTheory.QuotientGroup.Basic /-! diff --git a/Mathlib/Algebra/Module/BigOperators.lean b/Mathlib/Algebra/Module/BigOperators.lean index 8b68d57357fd4..d15e7274ec57a 100644 --- a/Mathlib/Algebra/Module/BigOperators.lean +++ b/Mathlib/Algebra/Module/BigOperators.lean @@ -15,7 +15,7 @@ variable {ι κ α β R M : Type*} section AddCommMonoid -variable [Semiring R] [AddCommMonoid M] [Module R M] (r s : R) (x y : M) +variable [Semiring R] [AddCommMonoid M] [Module R M] theorem List.sum_smul {l : List R} {x : M} : l.sum • x = (l.map fun r ↦ r • x).sum := map_list_sum ((smulAddHom R M).flip x) l diff --git a/Mathlib/Algebra/Module/Defs.lean b/Mathlib/Algebra/Module/Defs.lean index a80f140f53d26..f810b34644f19 100644 --- a/Mathlib/Algebra/Module/Defs.lean +++ b/Mathlib/Algebra/Module/Defs.lean @@ -67,7 +67,8 @@ variable [Semiring R] [AddCommMonoid M] [Module R M] (r s : R) (x y : M) -- see Note [lower instance priority] /-- A module over a semiring automatically inherits a `MulActionWithZero` structure. -/ -instance (priority := 100) Module.toMulActionWithZero : MulActionWithZero R M := +instance (priority := 100) Module.toMulActionWithZero + {R M} {_ : Semiring R} {_ : AddCommMonoid M} [Module R M] : MulActionWithZero R M := { (inferInstance : MulAction R M) with smul_zero := smul_zero zero_smul := Module.zero_smul } diff --git a/Mathlib/Algebra/Module/Equiv/Basic.lean b/Mathlib/Algebra/Module/Equiv/Basic.lean index 3d210451cac46..502f5ddd8ebdf 100644 --- a/Mathlib/Algebra/Module/Equiv/Basic.lean +++ b/Mathlib/Algebra/Module/Equiv/Basic.lean @@ -122,7 +122,7 @@ protected theorem smul_def (f : M ≃ₗ[R] M) (a : M) : f • a = f a := /-- `LinearEquiv.applyDistribMulAction` is faithful. -/ instance apply_faithfulSMul : FaithfulSMul (M ≃ₗ[R] M) M := - ⟨@fun _ _ ↦ LinearEquiv.ext⟩ + ⟨LinearEquiv.ext⟩ instance apply_smulCommClass [SMul S R] [SMul S M] [IsScalarTower S R M] : SMulCommClass S (M ≃ₗ[R] M) M where diff --git a/Mathlib/Algebra/Module/Injective.lean b/Mathlib/Algebra/Module/Injective.lean index 9462f04c45e08..a2e077efec5f7 100644 --- a/Mathlib/Algebra/Module/Injective.lean +++ b/Mathlib/Algebra/Module/Injective.lean @@ -67,8 +67,8 @@ theorem Module.injective_module_of_injective_object [inj : CategoryTheory.Injective <| ModuleCat.of R Q] : Module.Injective R Q where out X Y _ _ _ _ f hf g := by - have : CategoryTheory.Mono (ModuleCat.ofHom f) := (ModuleCat.mono_iff_injective _).mpr hf - obtain ⟨l, rfl⟩ := inj.factors (ModuleCat.ofHom g) (ModuleCat.ofHom f) + have : CategoryTheory.Mono (ModuleCat.asHom f) := (ModuleCat.mono_iff_injective _).mpr hf + obtain ⟨l, rfl⟩ := inj.factors (ModuleCat.asHom g) (ModuleCat.asHom f) exact ⟨l, fun _ ↦ rfl⟩ theorem Module.injective_iff_injective_object : diff --git a/Mathlib/Algebra/Module/LinearMap/Basic.lean b/Mathlib/Algebra/Module/LinearMap/Basic.lean index f50429fa64814..1a68ecbd89506 100644 --- a/Mathlib/Algebra/Module/LinearMap/Basic.lean +++ b/Mathlib/Algebra/Module/LinearMap/Basic.lean @@ -21,41 +21,41 @@ open Function universe u u' v w x y z -variable {R R₁ R₂ R₃ k S S₃ T M M₁ M₂ M₃ N₁ N₂ N₃ ι : Type*} +variable {R R' S M M' : Type*} namespace LinearMap section SMul -variable [Semiring R] [Semiring R₂] -variable [AddCommMonoid M] [AddCommMonoid M₂] -variable [Module R M] [Module R₂ M₂] -variable {σ₁₂ : R →+* R₂} +variable [Semiring R] [Semiring R'] +variable [AddCommMonoid M] [AddCommMonoid M'] +variable [Module R M] [Module R' M'] +variable {σ₁₂ : R →+* R'} variable {S' T' : Type*} variable [Monoid S'] [DistribMulAction S' M] [SMulCommClass R S' M] variable [Monoid T'] [DistribMulAction T' M] [SMulCommClass R T' M] -instance : SMul S'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M₂) where +instance : SMul S'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M') where smul a f := - { toFun := a • (f : M → M₂) + { toFun := a • (f : M → M') map_add' := fun x y ↦ by simp only [DomMulAct.smul_apply, f.map_add, smul_add] map_smul' := fun c x ↦ by simp_rw [DomMulAct.smul_apply, ← smul_comm, f.map_smulₛₗ] } -theorem _root_.DomMulAct.smul_linearMap_apply (a : S'ᵈᵐᵃ) (f : M →ₛₗ[σ₁₂] M₂) (x : M) : +theorem _root_.DomMulAct.smul_linearMap_apply (a : S'ᵈᵐᵃ) (f : M →ₛₗ[σ₁₂] M') (x : M) : (a • f) x = f (DomMulAct.mk.symm a • x) := rfl @[simp] -theorem _root_.DomMulAct.mk_smul_linearMap_apply (a : S') (f : M →ₛₗ[σ₁₂] M₂) (x : M) : +theorem _root_.DomMulAct.mk_smul_linearMap_apply (a : S') (f : M →ₛₗ[σ₁₂] M') (x : M) : (DomMulAct.mk a • f) x = f (a • x) := rfl -theorem _root_.DomMulAct.coe_smul_linearMap (a : S'ᵈᵐᵃ) (f : M →ₛₗ[σ₁₂] M₂) : - (a • f : M →ₛₗ[σ₁₂] M₂) = a • (f : M → M₂) := +theorem _root_.DomMulAct.coe_smul_linearMap (a : S'ᵈᵐᵃ) (f : M →ₛₗ[σ₁₂] M') : + (a • f : M →ₛₗ[σ₁₂] M') = a • (f : M → M') := rfl -instance [SMulCommClass S' T' M] : SMulCommClass S'ᵈᵐᵃ T'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M₂) := +instance [SMulCommClass S' T' M] : SMulCommClass S'ᵈᵐᵃ T'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M') := ⟨fun s t f ↦ ext fun m ↦ by simp_rw [DomMulAct.smul_linearMap_apply, smul_comm]⟩ end SMul @@ -63,19 +63,15 @@ end SMul section Actions -variable [Semiring R] [Semiring R₂] [Semiring R₃] -variable [AddCommMonoid M] [AddCommMonoid M₂] [AddCommMonoid M₃] -variable [Module R M] [Module R₂ M₂] [Module R₃ M₃] -variable {σ₁₂ : R →+* R₂} {σ₂₃ : R₂ →+* R₃} {σ₁₃ : R →+* R₃} [RingHomCompTriple σ₁₂ σ₂₃ σ₁₃] +variable [Semiring R] [Semiring R'] +variable [AddCommMonoid M] [AddCommMonoid M'] +variable [Module R M] [Module R' M'] +variable {σ₁₂ : R →+* R'} section SMul -variable [Monoid S] [DistribMulAction S M₂] [SMulCommClass R₂ S M₂] -variable [Monoid S₃] [DistribMulAction S₃ M₃] [SMulCommClass R₃ S₃ M₃] -variable [Monoid T] [DistribMulAction T M₂] [SMulCommClass R₂ T M₂] - instance {S'} [Monoid S'] [DistribMulAction S' M] [SMulCommClass R S' M] : - DistribMulAction S'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M₂) where + DistribMulAction S'ᵈᵐᵃ (M →ₛₗ[σ₁₂] M') where one_smul _ := ext fun _ ↦ congr_arg _ (one_smul _ _) mul_smul _ _ _ := ext fun _ ↦ congr_arg _ (mul_smul _ _ _) smul_add _ _ _ := ext fun _ ↦ rfl @@ -85,12 +81,12 @@ end SMul section Module -variable [Semiring S] [Module S M] [Module S M₂] [SMulCommClass R₂ S M₂] +variable [Semiring S] [Module S M] [Module S M'] [SMulCommClass R' S M'] -instance [NoZeroSMulDivisors S M₂] : NoZeroSMulDivisors S (M →ₛₗ[σ₁₂] M₂) := +instance [NoZeroSMulDivisors S M'] : NoZeroSMulDivisors S (M →ₛₗ[σ₁₂] M') := coe_injective.noZeroSMulDivisors _ rfl coe_smul -instance [SMulCommClass R S M] : Module Sᵈᵐᵃ (M →ₛₗ[σ₁₂] M₂) where +instance [SMulCommClass R S M] : Module Sᵈᵐᵃ (M →ₛₗ[σ₁₂] M') where add_smul _ _ _ := ext fun _ ↦ by simp_rw [add_apply, DomMulAct.smul_linearMap_apply, ← map_add, ← add_smul]; rfl zero_smul _ := ext fun _ ↦ by erw [DomMulAct.smul_linearMap_apply, zero_smul, map_zero]; rfl diff --git a/Mathlib/Algebra/Module/LinearMap/Defs.lean b/Mathlib/Algebra/Module/LinearMap/Defs.lean index e442944e3cb7b..e2c0d89223846 100644 --- a/Mathlib/Algebra/Module/LinearMap/Defs.lean +++ b/Mathlib/Algebra/Module/LinearMap/Defs.lean @@ -933,9 +933,8 @@ end Actions section RestrictScalarsAsLinearMap -variable {R S M N : Type*} [Semiring R] [Semiring S] [AddCommGroup M] [AddCommGroup N] [Module R M] - [Module R N] [Module S M] [Module S N] - [LinearMap.CompatibleSMul M N R S] +variable {R S M N P : Type*} [Semiring R] [Semiring S] [AddCommMonoid M] [AddCommMonoid N] + [Module R M] [Module R N] [Module S M] [Module S N] [CompatibleSMul M N R S] variable (R S M N) in @[simp] @@ -948,7 +947,9 @@ theorem restrictScalars_add (f g : M →ₗ[S] N) : rfl @[simp] -theorem restrictScalars_neg (f : M →ₗ[S] N) : (-f).restrictScalars R = -f.restrictScalars R := +theorem restrictScalars_neg {M N : Type*} [AddCommGroup M] [AddCommGroup N] + [Module R M] [Module R N] [Module S M] [Module S N] [CompatibleSMul M N R S] + (f : M →ₗ[S] N) : (-f).restrictScalars R = -f.restrictScalars R := rfl variable {R₁ : Type*} [Semiring R₁] [Module R₁ N] [SMulCommClass S R₁ N] [SMulCommClass R R₁ N] @@ -958,6 +959,18 @@ theorem restrictScalars_smul (c : R₁) (f : M →ₗ[S] N) : (c • f).restrictScalars R = c • f.restrictScalars R := rfl +@[simp] +lemma restrictScalars_comp [AddCommMonoid P] [Module S P] [Module R P] + [CompatibleSMul N P R S] [CompatibleSMul M P R S] (f : N →ₗ[S] P) (g : M →ₗ[S] N) : + (f ∘ₗ g).restrictScalars R = f.restrictScalars R ∘ₗ g.restrictScalars R := by + rfl + +@[simp] +lemma restrictScalars_trans {T : Type*} [CommSemiring T] [Module T M] [Module T N] + [CompatibleSMul M N S T] [CompatibleSMul M N R T] (f : M →ₗ[T] N) : + (f.restrictScalars S).restrictScalars R = f.restrictScalars R := + rfl + variable (S M N R R₁) /-- `LinearMap.restrictScalars` as a `LinearMap`. -/ diff --git a/Mathlib/Algebra/Module/LinearMap/Polynomial.lean b/Mathlib/Algebra/Module/LinearMap/Polynomial.lean index 6f0b08d7782c3..823b874234f59 100644 --- a/Mathlib/Algebra/Module/LinearMap/Polynomial.lean +++ b/Mathlib/Algebra/Module/LinearMap/Polynomial.lean @@ -351,7 +351,7 @@ lemma polyCharpolyAux_basisIndep {ιM' : Type*} [Fintype ιM'] [DecidableEq ιM' end aux -open FiniteDimensional Matrix +open Module Matrix variable [Module.Free R M] [Module.Finite R M] (b : Basis ι R L) @@ -479,11 +479,11 @@ lemma polyCharpoly_coeff_nilRank_ne_zero : rw [nilRank_eq_polyCharpoly_natTrailingDegree _ b] apply polyCharpoly_coeff_nilRankAux_ne_zero -open FiniteDimensional Module.Free +open Module Module.Free lemma nilRank_le_card {ι : Type*} [Fintype ι] (b : Basis ι R M) : nilRank φ ≤ Fintype.card ι := by apply Polynomial.natTrailingDegree_le_of_ne_zero - rw [← FiniteDimensional.finrank_eq_card_basis b, ← polyCharpoly_natDegree φ (chooseBasis R L), + rw [← Module.finrank_eq_card_basis b, ← polyCharpoly_natDegree φ (chooseBasis R L), Polynomial.coeff_natDegree, (polyCharpoly_monic _ _).leadingCoeff] apply one_ne_zero @@ -538,7 +538,7 @@ section IsDomain variable [IsDomain R] -open Cardinal FiniteDimensional MvPolynomial Module.Free in +open Cardinal Module MvPolynomial Module.Free in lemma exists_isNilRegular_of_finrank_le_card (h : finrank R M ≤ #R) : ∃ x : L, IsNilRegular φ x := by let b := chooseBasis R L diff --git a/Mathlib/Algebra/Module/LocalizedModule.lean b/Mathlib/Algebra/Module/LocalizedModule.lean index 45ebbceedbb8a..f9a2368b9a818 100644 --- a/Mathlib/Algebra/Module/LocalizedModule.lean +++ b/Mathlib/Algebra/Module/LocalizedModule.lean @@ -402,6 +402,29 @@ noncomputable instance isModule' : Module R (LocalizedModule S M) := theorem smul'_mk (r : R) (s : S) (m : M) : r • mk m s = mk (r • m) s := by erw [mk_smul_mk r m 1 s, one_mul] +lemma smul_eq_iff_of_mem + (r : R) (hr : r ∈ S) (x y : LocalizedModule S M) : + r • x = y ↔ x = Localization.mk 1 ⟨r, hr⟩ • y := by + induction x using induction_on with + | h m s => + induction y using induction_on with + | h n t => + rw [smul'_mk, mk_smul_mk, one_smul, mk_eq, mk_eq] + simp only [Subtype.exists, Submonoid.mk_smul, exists_prop] + fconstructor + · rintro ⟨a, ha, eq1⟩ + refine ⟨a, ha, ?_⟩ + rw [mul_smul, ← eq1, Submonoid.mk_smul, smul_comm r t] + · rintro ⟨a, ha, eq1⟩ + refine ⟨a, ha, ?_⟩ + rw [← eq1, mul_comm, mul_smul, Submonoid.mk_smul] + rfl + +lemma eq_zero_of_smul_eq_zero + (r : R) (hr : r ∈ S) (x : LocalizedModule S M) (hx : r • x = 0) : x = 0 := by + rw [smul_eq_iff_of_mem (hr := hr)] at hx + rw [hx, smul_zero] + theorem smul'_mul {A : Type*} [Semiring A] [Algebra R A] (x : T) (p₁ p₂ : LocalizedModule S A) : x • p₁ * p₂ = x • (p₁ * p₂) := by induction p₁, p₂ using induction_on₂ with | _ a₁ s₁ a₂ s₂ => _ @@ -605,7 +628,7 @@ noncomputable def lift' (g : M →ₗ[R] M'') simp only [Submonoid.smul_def, ← g.map_smul, eq1] have : Function.Injective (h c).unit.inv := ((Module.End_isUnit_iff _).1 (by simp)).1 apply_fun (h c).unit.inv - erw [Units.inv_eq_val_inv, Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← + rw [Units.inv_eq_val_inv, Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← (h c).unit⁻¹.val.map_smul] symm rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, ← g.map_smul, ← g.map_smul, ← g.map_smul, ← @@ -625,13 +648,13 @@ theorem lift'_add (g : M →ₗ[R] M'') (h : ∀ x : S, IsUnit ((algebraMap R (M intro a a' b b' erw [LocalizedModule.lift'_mk, LocalizedModule.lift'_mk, LocalizedModule.lift'_mk] -- Porting note: We remove `generalize_proofs h1 h2 h3`. This only generalize `h1`. - erw [map_add, Module.End_algebraMap_isUnit_inv_apply_eq_iff, smul_add, ← map_smul, + rw [map_add, Module.End_algebraMap_isUnit_inv_apply_eq_iff, smul_add, ← map_smul, ← map_smul, ← map_smul] congr 1 <;> symm · erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, mul_smul, ← map_smul] rfl · dsimp - erw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, mul_comm, mul_smul, ← map_smul] + rw [Module.End_algebraMap_isUnit_inv_apply_eq_iff, mul_comm, mul_smul, ← map_smul] rfl) x y diff --git a/Mathlib/Algebra/Module/Submodule/Bilinear.lean b/Mathlib/Algebra/Module/Submodule/Bilinear.lean index bacd3bc47d6b5..d6c065576cbbf 100644 --- a/Mathlib/Algebra/Module/Submodule/Bilinear.lean +++ b/Mathlib/Algebra/Module/Submodule/Bilinear.lean @@ -56,13 +56,15 @@ theorem map₂_span_span (f : M →ₗ[R] N →ₗ[R] P) (s : Set M) (t : Set N) apply le_antisymm · rw [map₂_le] apply @span_induction' R M _ _ _ s - intro a ha - apply @span_induction' R N _ _ _ t - intro b hb - exact subset_span ⟨_, ‹_›, _, ‹_›, rfl⟩ - all_goals intros; simp only [*, add_mem, smul_mem, zero_mem, _root_.map_zero, map_add, - LinearMap.zero_apply, LinearMap.add_apply, LinearMap.smul_apply, - map_smul] + on_goal 1 => + intro a ha + apply @span_induction' R N _ _ _ t + · intro b hb + exact subset_span ⟨_, ‹_›, _, ‹_›, rfl⟩ + all_goals + intros + simp only [*, add_mem, smul_mem, zero_mem, _root_.map_zero, map_add, + LinearMap.zero_apply, LinearMap.add_apply, LinearMap.smul_apply, map_smul] · rw [span_le, image2_subset_iff] intro a ha b hb exact apply_mem_map₂ _ (subset_span ha) (subset_span hb) diff --git a/Mathlib/Algebra/Module/Submodule/Lattice.lean b/Mathlib/Algebra/Module/Submodule/Lattice.lean index 1b9c97d71bbe6..3e15b4721bc18 100644 --- a/Mathlib/Algebra/Module/Submodule/Lattice.lean +++ b/Mathlib/Algebra/Module/Submodule/Lattice.lean @@ -241,6 +241,10 @@ theorem mem_finset_inf {ι} {s : Finset ι} {p : ι → Submodule R M} {x : M} : x ∈ s.inf p ↔ ∀ i ∈ s, x ∈ p i := by simp only [← SetLike.mem_coe, finset_inf_coe, Set.mem_iInter] +lemma inf_iInf {ι : Type*} [Nonempty ι] {p : ι → Submodule R M} (q : Submodule R M) : + q ⊓ ⨅ i, p i = ⨅ i, q ⊓ p i := + SetLike.coe_injective <| by simpa only [inf_coe, iInf_coe] using Set.inter_iInter _ _ + theorem mem_sup_left {S T : Submodule R M} : ∀ {x : M}, x ∈ S → x ∈ S ⊔ T := by have : S ≤ S ⊔ T := le_sup_left rw [LE.le] at this @@ -287,7 +291,7 @@ theorem toAddSubmonoid_sSup (s : Set (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' + 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) diff --git a/Mathlib/Algebra/Module/Submodule/LinearMap.lean b/Mathlib/Algebra/Module/Submodule/LinearMap.lean index 4ff64ac81d3b1..36b04e8dc9c3d 100644 --- a/Mathlib/Algebra/Module/Submodule/LinearMap.lean +++ b/Mathlib/Algebra/Module/Submodule/LinearMap.lean @@ -75,9 +75,11 @@ theorem subtype_apply (x : p) : p.subtype x = x := rfl @[simp] -theorem coeSubtype : (Submodule.subtype p : p → M) = Subtype.val := +theorem coe_subtype : (Submodule.subtype p : p → M) = Subtype.val := rfl +@[deprecated (since := "2024-09-27")] alias coeSubtype := coe_subtype + theorem injective_subtype : Injective p.subtype := Subtype.coe_injective @@ -181,6 +183,13 @@ lemma restrict_comp (g ∘ₗ f).restrict hfg = (g.restrict hg) ∘ₗ (f.restrict hf) := rfl +-- TODO Consider defining `Algebra R (p.compatibleMaps p)`, `AlgHom` version of `LinearMap.restrict` +lemma restrict_smul_one + {R M : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] {p : Submodule R M} + (μ : R) (h : ∀ x ∈ p, (μ • (1 : Module.End R M)) x ∈ p := fun _ ↦ p.smul_mem μ) : + (μ • 1 : Module.End R M).restrict h = μ • (1 : Module.End R p) := + rfl + lemma restrict_commute {f g : M →ₗ[R] M} (h : Commute f g) {p : Submodule R M} (hf : MapsTo f p p) (hg : MapsTo g p p) : Commute (f.restrict hf) (g.restrict hg) := by diff --git a/Mathlib/Algebra/Module/Submodule/Map.lean b/Mathlib/Algebra/Module/Submodule/Map.lean index 6f6227fd83734..0e08a969e1c07 100644 --- a/Mathlib/Algebra/Module/Submodule/Map.lean +++ b/Mathlib/Algebra/Module/Submodule/Map.lean @@ -104,7 +104,7 @@ theorem map_mono {f : F} {p p' : Submodule R M} : p ≤ p' → map f p ≤ map f image_subset _ @[simp] -theorem map_zero : map (0 : M →ₛₗ[σ₁₂] M₂) p = ⊥ := +protected theorem map_zero : map (0 : M →ₛₗ[σ₁₂] M₂) p = ⊥ := have : ∃ x : M, x ∈ p := ⟨0, p.zero_mem⟩ ext <| by simp [this, eq_comm] @@ -120,6 +120,10 @@ theorem map_inf (f : F) {p q : Submodule R M} (hf : Injective f) : (p ⊓ q).map f = p.map f ⊓ q.map f := SetLike.coe_injective <| Set.image_inter hf +lemma map_iInf {ι : Type*} [Nonempty ι] {p : ι → Submodule R M} (f : F) (hf : Injective f) : + (⨅ i, p i).map f = ⨅ i, (p i).map f := + SetLike.coe_injective <| by simpa only [map_coe, iInf_coe] using hf.injOn.image_iInter_eq + theorem range_map_nonempty (N : Submodule R M) : (Set.range (fun ϕ => Submodule.map ϕ N : (M →ₛₗ[σ₁₂] M₂) → Submodule R₂ M₂)).Nonempty := ⟨_, Set.mem_range.mpr ⟨0, rfl⟩⟩ diff --git a/Mathlib/Algebra/Module/Submodule/Pointwise.lean b/Mathlib/Algebra/Module/Submodule/Pointwise.lean index 031be85372fc7..c8d8a18665f39 100644 --- a/Mathlib/Algebra/Module/Submodule/Pointwise.lean +++ b/Mathlib/Algebra/Module/Submodule/Pointwise.lean @@ -418,7 +418,7 @@ lemma set_smul_eq_map [SMulCommClass R R N] : exact ⟨Finsupp.single r ⟨n, hn⟩, Finsupp.single_mem_supported _ _ hr, by simp⟩ · intro x hx obtain ⟨c, hc, rfl⟩ := hx - simp only [LinearMap.coe_comp, coeSubtype, Finsupp.coe_lsum, Finsupp.sum, Function.comp_apply] + simp only [LinearMap.coe_comp, coe_subtype, Finsupp.coe_lsum, Finsupp.sum, Function.comp_apply] rw [AddSubmonoid.coe_finset_sum] refine Submodule.sum_mem (p := sR • N) (t := c.support) ?_ _ ⟨sR • N, ?_⟩ · rintro r hr diff --git a/Mathlib/Algebra/Module/Torsion.lean b/Mathlib/Algebra/Module/Torsion.lean index ecd92053f2c94..5be854af327cb 100644 --- a/Mathlib/Algebra/Module/Torsion.lean +++ b/Mathlib/Algebra/Module/Torsion.lean @@ -3,11 +3,11 @@ Copyright (c) 2022 Pierre-Alexandre Bazin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Pierre-Alexandre Bazin -/ -import Mathlib.LinearAlgebra.Isomorphisms +import Mathlib.Algebra.DirectSum.Module +import Mathlib.Algebra.Module.ZMod import Mathlib.GroupTheory.Torsion +import Mathlib.LinearAlgebra.Isomorphisms import Mathlib.RingTheory.Coprime.Ideal -import Mathlib.Data.ZMod.Module -import Mathlib.Algebra.DirectSum.Module /-! # Torsion submodules diff --git a/Mathlib/Algebra/Module/ZLattice/Basic.lean b/Mathlib/Algebra/Module/ZLattice/Basic.lean index 94a9e5badef5b..a436852b2ab88 100644 --- a/Mathlib/Algebra/Module/ZLattice/Basic.lean +++ b/Mathlib/Algebra/Module/ZLattice/Basic.lean @@ -384,7 +384,7 @@ end ZSpan section ZLattice -open Submodule FiniteDimensional ZSpan +open Submodule Module ZSpan -- TODO: generalize this class to other rings than `ℤ` /-- `L : Submodule ℤ E` where `E` is a vector space over a normed field `K` is a `ℤ`-lattice if @@ -562,7 +562,7 @@ variable {ι : Type*} [hs : IsZLattice K L] (b : Basis ι ℤ L) /-- Any `ℤ`-basis of `L` is also a `K`-basis of `E`. -/ def Basis.ofZLatticeBasis : Basis ι K E := by - have : Finite ℤ L := ZLattice.module_finite K L + have : Module.Finite ℤ L := ZLattice.module_finite K L have : Free ℤ L := ZLattice.module_free K L let e := Basis.indexEquiv (Free.chooseBasis ℤ L) b have : Fintype ι := Fintype.ofEquiv _ e @@ -583,7 +583,7 @@ theorem Basis.ofZLatticeBasis_repr_apply (x : L) (i : ι) : exact DFunLike.congr_fun (LinearMap.congr_fun this x) i refine Basis.ext b fun i ↦ ?_ simp_rw [LinearMap.coe_comp, Function.comp_apply, LinearMap.coe_restrictScalars, - LinearEquiv.coe_coe, coeSubtype, ← b.ofZLatticeBasis_apply K, repr_self, + LinearEquiv.coe_coe, coe_subtype, ← b.ofZLatticeBasis_apply K, repr_self, Finsupp.mapRange.linearMap_apply, Finsupp.mapRange_single, Algebra.linearMap_apply, map_one] theorem Basis.ofZLatticeBasis_span : diff --git a/Mathlib/Algebra/Module/ZLattice/Covolume.lean b/Mathlib/Algebra/Module/ZLattice/Covolume.lean index bec47d37fcc0b..04e559d80a384 100644 --- a/Mathlib/Algebra/Module/ZLattice/Covolume.lean +++ b/Mathlib/Algebra/Module/ZLattice/Covolume.lean @@ -29,7 +29,7 @@ noncomputable section namespace ZLattice -open Submodule MeasureTheory FiniteDimensional MeasureTheory Module +open Submodule MeasureTheory Module MeasureTheory Module section General diff --git a/Mathlib/Data/ZMod/Module.lean b/Mathlib/Algebra/Module/ZMod.lean similarity index 94% rename from Mathlib/Data/ZMod/Module.lean rename to Mathlib/Algebra/Module/ZMod.lean index 64cb1d86b6160..961af9fe2c048 100644 --- a/Mathlib/Data/ZMod/Module.lean +++ b/Mathlib/Algebra/Module/ZMod.lean @@ -5,7 +5,6 @@ Authors: Lawrence Wu -/ import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.Data.ZMod.Basic -import Mathlib.Order.OmegaCompletePartialOrder /-! # The `ZMod n`-module structure on Abelian groups whose elements have order dividing `n` @@ -92,9 +91,8 @@ theorem toZModSubmodule_symm : ⇑((toZModSubmodule n).symm : _ ≃o AddSubgroup M) = Submodule.toAddSubgroup := rfl -@[simp] -theorem coe_toZModSubmodule (S : AddSubgroup M) : (toZModSubmodule n S : Set M) = S := - rfl +@[simp] lemma coe_toZModSubmodule (S : AddSubgroup M) : (toZModSubmodule n S : Set M) = S := rfl +@[simp] lemma mem_toZModSubmodule {S : AddSubgroup M} : x ∈ toZModSubmodule n S ↔ x ∈ S := .rfl @[simp] theorem toZModSubmodule_toAddSubgroup (S : AddSubgroup M) : diff --git a/Mathlib/Algebra/MonoidAlgebra/Defs.lean b/Mathlib/Algebra/MonoidAlgebra/Defs.lean index f0273652c337c..a2574ffe76219 100644 --- a/Mathlib/Algebra/MonoidAlgebra/Defs.lean +++ b/Mathlib/Algebra/MonoidAlgebra/Defs.lean @@ -209,10 +209,10 @@ instance nonUnitalSemiring : NonUnitalSemiring (MonoidAlgebra k G) := mul_assoc := fun f g h => by -- Porting note: `reducible` cannot be `local` so proof gets long. simp only [mul_def] - rw [sum_sum_index]; congr; ext a₁ b₁ - rw [sum_sum_index, sum_sum_index]; congr; ext a₂ b₂ - rw [sum_sum_index, sum_single_index]; congr; ext a₃ b₃ - rw [sum_single_index, mul_assoc, mul_assoc] + rw [sum_sum_index] <;> congr; on_goal 1 => ext a₁ b₁ + rw [sum_sum_index, sum_sum_index] <;> congr; on_goal 1 => ext a₂ b₂ + rw [sum_sum_index, sum_single_index] <;> congr; on_goal 1 => ext a₃ b₃ + on_goal 1 => rw [sum_single_index, mul_assoc, mul_assoc] all_goals simp only [single_zero, single_add, forall_true_iff, add_mul, mul_add, zero_mul, mul_zero, sum_zero, sum_add] } @@ -974,10 +974,10 @@ instance nonUnitalSemiring : NonUnitalSemiring k[G] := mul_assoc := fun f g h => by -- Porting note: `reducible` cannot be `local` so proof gets long. simp only [mul_def] - rw [sum_sum_index]; congr; ext a₁ b₁ - rw [sum_sum_index, sum_sum_index]; congr; ext a₂ b₂ - rw [sum_sum_index, sum_single_index]; congr; ext a₃ b₃ - rw [sum_single_index, mul_assoc, add_assoc] + rw [sum_sum_index] <;> congr; on_goal 1 => ext a₁ b₁ + rw [sum_sum_index, sum_sum_index] <;> congr; on_goal 1 => ext a₂ b₂ + rw [sum_sum_index, sum_single_index] <;> congr; on_goal 1 => ext a₃ b₃ + on_goal 1 => rw [sum_single_index, mul_assoc, add_assoc] all_goals simp only [single_zero, single_add, forall_true_iff, add_mul, mul_add, zero_mul, mul_zero, sum_zero, sum_add] } diff --git a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean index 111fe27da2293..aa57dcae344e6 100644 --- a/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean +++ b/Mathlib/Algebra/MonoidAlgebra/ToDirectSum.lean @@ -136,17 +136,21 @@ theorem toDirectSum_mul [DecidableEq ι] [AddMonoid ι] [Semiring M] (f g : AddM AddMonoidHom.mul_apply, Finsupp.singleAddHom_apply] -- This was not needed before leanprover/lean4#2644 erw [AddMonoidHom.compl₂_apply] + -- If we remove the next `rw`, the `erw` after it will complain (when we get an `erw` linter) + -- that it could be a `rw`. But the `erw` and `rw` will rewrite different occurrences. + -- So first get rid of the `rw`-able occurrences to force `erw` to do the expensive rewrite only. + rw [AddMonoidHom.coe_mk, AddMonoidHom.coe_mk] -- This was not needed before leanprover/lean4#2644 erw [AddMonoidHom.coe_mk] simp only [AddMonoidHom.coe_mk, ZeroHom.coe_mk, toDirectSum_single] -- This was not needed before leanprover/lean4#2644 dsimp - erw [AddMonoidAlgebra.single_mul_single, AddMonoidHom.coe_mk, ZeroHom.coe_mk, + rw [AddMonoidAlgebra.single_mul_single, AddMonoidHom.coe_mk, AddMonoidHom.coe_mk, ZeroHom.coe_mk, AddMonoidAlgebra.toDirectSum_single] simp only [AddMonoidHom.coe_comp, AddMonoidHom.coe_mul, AddMonoidHom.coe_mk, ZeroHom.coe_mk, Function.comp_apply, toDirectSum_single, AddMonoidHom.id_apply, Finsupp.singleAddHom_apply, AddMonoidHom.coe_mulLeft] - erw [DirectSum.of_mul_of, Mul.gMul_mul] + rw [DirectSum.of_mul_of, Mul.gMul_mul] end AddMonoidAlgebra diff --git a/Mathlib/Algebra/MvPolynomial/Basic.lean b/Mathlib/Algebra/MvPolynomial/Basic.lean index da687de7c7942..722c1bdf7b69a 100644 --- a/Mathlib/Algebra/MvPolynomial/Basic.lean +++ b/Mathlib/Algebra/MvPolynomial/Basic.lean @@ -1357,6 +1357,11 @@ theorem comp_aeval {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[ ext i simp +lemma comp_aeval_apply {B : Type*} [CommSemiring B] [Algebra R B] (φ : S₁ →ₐ[R] B) + (p : MvPolynomial σ R) : + φ (aeval f p) = aeval (fun i ↦ φ (f i)) p := by + rw [← comp_aeval, AlgHom.coe_comp, comp_apply] + @[simp] theorem map_aeval {B : Type*} [CommSemiring B] (g : σ → S₁) (φ : S₁ →+* B) (p : MvPolynomial σ R) : φ (aeval g p) = eval₂Hom (φ.comp (algebraMap R S₁)) (fun i => φ (g i)) p := by @@ -1537,6 +1542,17 @@ theorem eval_mem {p : MvPolynomial σ S} {s : subS} (hs : ∀ i ∈ p.support, p end EvalMem +variable {S T : Type*} [CommSemiring S] [Algebra R S] [CommSemiring T] [Algebra R T] [Algebra S T] + [IsScalarTower R S T] + +lemma aeval_sum_elim {σ τ : Type*} (p : MvPolynomial (σ ⊕ τ) R) (f : τ → S) (g : σ → T) : + (aeval (Sum.elim g (algebraMap S T ∘ f))) p = + (aeval g) ((aeval (Sum.elim X (C ∘ f))) p) := by + induction' p using MvPolynomial.induction_on with r p q hp hq p i h + · simp [← IsScalarTower.algebraMap_apply] + · simp [hp, hq] + · cases i <;> simp [h] + end CommSemiring end MvPolynomial diff --git a/Mathlib/Algebra/MvPolynomial/PDeriv.lean b/Mathlib/Algebra/MvPolynomial/PDeriv.lean index a4755788c2c2a..2f36da703dccd 100644 --- a/Mathlib/Algebra/MvPolynomial/PDeriv.lean +++ b/Mathlib/Algebra/MvPolynomial/PDeriv.lean @@ -65,12 +65,12 @@ theorem pderiv_def [DecidableEq σ] (i : σ) : pderiv i = mkDerivation R (Pi.sin theorem pderiv_monomial {i : σ} : pderiv i (monomial s a) = monomial (s - single i 1) (a * s i) := by classical - simp only [pderiv_def, mkDerivation_monomial, Finsupp.smul_sum, smul_eq_mul, ← smul_mul_assoc, - ← (monomial _).map_smul] - refine (Finset.sum_eq_single i (fun j _ hne => ?_) fun hi => ?_).trans ?_ - · simp [Pi.single_eq_of_ne hne] - · rw [Finsupp.not_mem_support_iff] at hi; simp [hi] - · simp + simp only [pderiv_def, mkDerivation_monomial, Finsupp.smul_sum, smul_eq_mul, ← smul_mul_assoc, + ← (monomial _).map_smul] + refine (Finset.sum_eq_single i (fun j _ hne => ?_) fun hi => ?_).trans ?_ + · simp [Pi.single_eq_of_ne hne] + · rw [Finsupp.not_mem_support_iff] at hi; simp [hi] + · simp theorem pderiv_C {i : σ} : pderiv i (C a) = 0 := derivation_C _ _ @@ -115,6 +115,28 @@ theorem pderiv_map {S} [CommSemiring S] {φ : R →+* S} {f : MvPolynomial σ R} · simp [eq] · simp [eq, h] +lemma pderiv_rename {τ : Type*} {f : σ → τ} (hf : Function.Injective f) + (x : σ) (p : MvPolynomial σ R) : + pderiv (f x) (rename f p) = rename f (pderiv x p) := by + classical + induction' p using MvPolynomial.induction_on with a p q hp hq p a h + · simp + · simp [hp, hq] + · simp only [map_mul, MvPolynomial.rename_X, Derivation.leibniz, MvPolynomial.pderiv_X, + Pi.single_apply, hf.eq_iff, smul_eq_mul, mul_ite, mul_one, mul_zero, h, map_add, add_left_inj] + split_ifs <;> simp + +lemma aeval_sum_elim_pderiv_inl {S τ : Type*} [CommRing S] [Algebra R S] + (p : MvPolynomial (σ ⊕ τ) R) (f : τ → S) (j : σ) : + aeval (Sum.elim X (C ∘ f)) ((pderiv (Sum.inl j)) p) = + (pderiv j) ((aeval (Sum.elim X (C ∘ f))) p) := by + classical + induction' p using MvPolynomial.induction_on with a p q hp hq p q h + · simp + · simp [hp, hq] + · simp only [Derivation.leibniz, pderiv_X, smul_eq_mul, map_add, map_mul, aeval_X, h] + cases q <;> simp [Pi.single_apply] + end PDeriv end MvPolynomial diff --git a/Mathlib/Algebra/NeZero.lean b/Mathlib/Algebra/NeZero.lean index aaa15d8a6209e..3fdf3e370cb38 100644 --- a/Mathlib/Algebra/NeZero.lean +++ b/Mathlib/Algebra/NeZero.lean @@ -10,32 +10,12 @@ import Mathlib.Order.Defs /-! # `NeZero` typeclass -We create a typeclass `NeZero n` which carries around the fact that `(n : R) ≠ 0`. +We give basic facts about the `NeZero n` typeclass. -## Main declarations - -* `NeZero`: `n ≠ 0` as a typeclass. -/ variable {R : Type*} [Zero R] -/-- A type-class version of `n ≠ 0`. -/ -class NeZero (n : R) : Prop where - /-- The proposition that `n` is not zero. -/ - out : n ≠ 0 - -theorem NeZero.ne (n : R) [h : NeZero n] : n ≠ 0 := - h.out - -theorem NeZero.ne' (n : R) [h : NeZero n] : 0 ≠ n := - h.out.symm - -theorem neZero_iff {n : R} : NeZero n ↔ n ≠ 0 := - ⟨fun h ↦ h.out, NeZero.mk⟩ - -@[simp] lemma neZero_zero_iff_false {α : Type*} [Zero α] : NeZero (0 : α) ↔ False := - ⟨fun h ↦ h.ne rfl, fun h ↦ h.elim⟩ - theorem not_neZero {n : R} : ¬NeZero n ↔ n = 0 := by simp [neZero_iff] theorem eq_zero_or_neZero (a : R) : a = 0 ∨ NeZero a := @@ -77,10 +57,6 @@ namespace NeZero variable {M : Type*} {x : M} -instance succ {n : ℕ} : NeZero (n + 1) := ⟨n.succ_ne_zero⟩ - theorem of_pos [Preorder M] [Zero M] (h : 0 < x) : NeZero x := ⟨ne_of_gt h⟩ end NeZero - -lemma Nat.pos_of_neZero (n : ℕ) [NeZero n] : 0 < n := Nat.pos_of_ne_zero (NeZero.ne _) diff --git a/Mathlib/Algebra/Order/Archimedean/Basic.lean b/Mathlib/Algebra/Order/Archimedean/Basic.lean index 8706c7c0c0d17..4d20bc04708f5 100644 --- a/Mathlib/Algebra/Order/Archimedean/Basic.lean +++ b/Mathlib/Algebra/Order/Archimedean/Basic.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.Algebra.Order.Field.Power +import Mathlib.Algebra.Order.Ring.Pow import Mathlib.Data.Int.LeastGreatest import Mathlib.Data.Rat.Floor import Mathlib.Data.NNRat.Defs @@ -223,7 +223,7 @@ variable [LinearOrderedSemifield α] [Archimedean α] {x y ε : α} lemma exists_nat_one_div_lt (hε : 0 < ε) : ∃ n : ℕ, 1 / (n + 1 : α) < ε := by cases' exists_nat_gt (1 / ε) with n hn use n - rw [div_lt_iff, ← div_lt_iff' hε] + rw [div_lt_iff₀, ← div_lt_iff₀' hε] · apply hn.trans simp [zero_lt_one] · exact n.cast_add_one_pos @@ -241,12 +241,12 @@ theorem exists_mem_Ico_zpow (hx : 0 < x) (hy : 1 < y) : ∃ n : ℤ, x ∈ Ico ( le_of_lt (by rw [zpow_neg y ↑N, zpow_natCast] - exact (inv_lt hx (lt_trans (inv_pos.2 hx) hN)).1 hN)⟩ + exact (inv_lt_comm₀ hx (lt_trans (inv_pos.2 hx) hN)).1 hN)⟩ let ⟨M, hM⟩ := pow_unbounded_of_one_lt x hy have hb : ∃ b : ℤ, ∀ m, y ^ m ≤ x → m ≤ b := ⟨M, fun m hm => le_of_not_lt fun hlt => - not_lt_of_ge (zpow_le_of_le hy.le hlt.le) + not_lt_of_ge (zpow_le_zpow_right₀ hy.le hlt.le) (lt_of_le_of_lt hm (by rwa [← zpow_natCast] at hM))⟩ let ⟨n, hn₁, hn₂⟩ := Int.exists_greatest_of_bdd hb he ⟨n, hn₁, lt_of_not_ge fun hge => not_le_of_gt (Int.lt_succ _) (hn₂ _ hge)⟩ @@ -257,8 +257,8 @@ but with ≤ and < the other way around. -/ theorem exists_mem_Ioc_zpow (hx : 0 < x) (hy : 1 < y) : ∃ n : ℤ, x ∈ Ioc (y ^ n) (y ^ (n + 1)) := let ⟨m, hle, hlt⟩ := exists_mem_Ico_zpow (inv_pos.2 hx) hy have hyp : 0 < y := lt_trans zero_lt_one hy - ⟨-(m + 1), by rwa [zpow_neg, inv_lt (zpow_pos_of_pos hyp _) hx], by - rwa [neg_add, neg_add_cancel_right, zpow_neg, le_inv hx (zpow_pos_of_pos hyp _)]⟩ + ⟨-(m + 1), by rwa [zpow_neg, inv_lt_comm₀ (zpow_pos hyp _) hx], by + rwa [neg_add, neg_add_cancel_right, zpow_neg, le_inv_comm₀ hx (zpow_pos hyp _)]⟩ /-- For any `y < 1` and any positive `x`, there exists `n : ℕ` with `y ^ n < x`. -/ theorem exists_pow_lt_of_lt_one (hx : 0 < x) (hy : y < 1) : ∃ n : ℕ, y ^ n < x := by @@ -267,18 +267,18 @@ theorem exists_pow_lt_of_lt_one (hx : 0 < x) (hy : y < 1) : ∃ n : ℕ, y ^ n < simp only [pow_one] exact y_pos.trans_lt hx rw [not_le] at y_pos - rcases pow_unbounded_of_one_lt x⁻¹ (one_lt_inv y_pos hy) with ⟨q, hq⟩ - exact ⟨q, by rwa [inv_pow, inv_lt_inv hx (pow_pos y_pos _)] at hq⟩ + rcases pow_unbounded_of_one_lt x⁻¹ ((one_lt_inv₀ y_pos).2 hy) with ⟨q, hq⟩ + exact ⟨q, by rwa [inv_pow, inv_lt_inv₀ hx (pow_pos y_pos _)] at hq⟩ /-- Given `x` and `y` between `0` and `1`, `x` is between two successive powers of `y`. This is the same as `exists_nat_pow_near`, but for elements between `0` and `1` -/ theorem exists_nat_pow_near_of_lt_one (xpos : 0 < x) (hx : x ≤ 1) (ypos : 0 < y) (hy : y < 1) : ∃ n : ℕ, y ^ (n + 1) < x ∧ x ≤ y ^ n := by - rcases exists_nat_pow_near (one_le_inv_iff.2 ⟨xpos, hx⟩) (one_lt_inv_iff.2 ⟨ypos, hy⟩) with + rcases exists_nat_pow_near (one_le_inv_iff₀.2 ⟨xpos, hx⟩) (one_lt_inv_iff₀.2 ⟨ypos, hy⟩) with ⟨n, hn, h'n⟩ refine ⟨n, ?_, ?_⟩ - · rwa [inv_pow, inv_lt_inv xpos (pow_pos ypos _)] at h'n - · rwa [inv_pow, inv_le_inv (pow_pos ypos _) xpos] at hn + · rwa [inv_pow, inv_lt_inv₀ xpos (pow_pos ypos _)] at h'n + · rwa [inv_pow, inv_le_inv₀ (pow_pos ypos _) xpos] at hn end LinearOrderedSemifield @@ -299,11 +299,11 @@ theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) refine ⟨(z + 1 : ℤ) / n, ?_⟩ have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh have n0 := Nat.cast_pos.1 n0' - rw [Rat.cast_div_of_ne_zero, Rat.cast_natCast, Rat.cast_intCast, div_lt_iff n0'] - · refine ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), ?_⟩ + rw [Rat.cast_div_of_ne_zero, Rat.cast_natCast, Rat.cast_intCast, div_lt_iff₀ n0'] + · refine ⟨(lt_div_iff₀ n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), ?_⟩ rw [Int.cast_add, Int.cast_one] refine lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) ?_ - rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div] + rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff₀' (sub_pos.2 h), one_div] · rw [Rat.den_intCast, Nat.cast_one] exact one_ne_zero · intro H @@ -352,7 +352,7 @@ variable [LinearOrderedField α] theorem archimedean_iff_nat_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℕ, x < n := ⟨@exists_nat_gt α _, fun H => ⟨fun x y y0 => - (H (x / y)).imp fun n h => le_of_lt <| by rwa [div_lt_iff y0, ← nsmul_eq_mul] at h⟩⟩ + (H (x / y)).imp fun n h => le_of_lt <| by rwa [div_lt_iff₀ y0, ← nsmul_eq_mul] at h⟩⟩ theorem archimedean_iff_nat_le : Archimedean α ↔ ∀ x : α, ∃ n : ℕ, x ≤ n := archimedean_iff_nat_lt.trans diff --git a/Mathlib/Algebra/Order/BigOperators/Expect.lean b/Mathlib/Algebra/Order/BigOperators/Expect.lean new file mode 100644 index 0000000000000..a449b9ce36435 --- /dev/null +++ b/Mathlib/Algebra/Order/BigOperators/Expect.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2024 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.BigOperators.Expect +import Mathlib.Algebra.Module.Rat +import Mathlib.Algebra.Order.BigOperators.Ring.Finset +import Mathlib.Algebra.Order.Module.Rat + +/-! +# Order properties of the average over a finset +-/ + +open Function +open Fintype (card) +open scoped BigOperators Pointwise NNRat + +variable {ι κ α β R : Type*} + +local notation a " /ℚ " q => (q : ℚ≥0)⁻¹ • a + +namespace Finset +section OrderedAddCommMonoid +variable [OrderedAddCommMonoid α] [Module ℚ≥0 α] [OrderedAddCommMonoid β] [Module ℚ≥0 β] + {s : Finset ι} {f g : ι → α} + +lemma expect_eq_zero_iff_of_nonneg (hs : s.Nonempty) (hf : ∀ i ∈ s, 0 ≤ f i) : + 𝔼 i ∈ s, f i = 0 ↔ ∀ i ∈ s, f i = 0 := by + simp [expect, sum_eq_zero_iff_of_nonneg hf, hs.ne_empty] + +lemma expect_eq_zero_iff_of_nonpos (hs : s.Nonempty) (hf : ∀ i ∈ s, f i ≤ 0) : + 𝔼 i ∈ s, f i = 0 ↔ ∀ i ∈ s, f i = 0 := by + simp [expect, sum_eq_zero_iff_of_nonpos hf, hs.ne_empty] + +section PosSMulMono +variable [PosSMulMono ℚ≥0 α] {a : α} + +lemma expect_le_expect (hfg : ∀ i ∈ s, f i ≤ g i) : 𝔼 i ∈ s, f i ≤ 𝔼 i ∈ s, g i := + smul_le_smul_of_nonneg_left (sum_le_sum hfg) <| by positivity + +/-- This is a (beta-reduced) version of the standard lemma `Finset.expect_le_expect`, +convenient for the `gcongr` tactic. -/ +@[gcongr] +lemma _root_.GCongr.expect_le_expect (h : ∀ i ∈ s, f i ≤ g i) : s.expect f ≤ s.expect g := + Finset.expect_le_expect h + +lemma expect_le (hs : s.Nonempty) (h : ∀ x ∈ s, f x ≤ a) : 𝔼 i ∈ s, f i ≤ a := + (inv_smul_le_iff_of_pos <| mod_cast hs.card_pos).2 <| by + rw [Nat.cast_smul_eq_nsmul]; exact sum_le_card_nsmul _ _ _ h + +lemma le_expect (hs : s.Nonempty) (h : ∀ x ∈ s, a ≤ f x) : a ≤ 𝔼 i ∈ s, f i := + (le_inv_smul_iff_of_pos <| mod_cast hs.card_pos).2 <| by + rw [Nat.cast_smul_eq_nsmul]; exact card_nsmul_le_sum _ _ _ h + +lemma expect_nonneg (hf : ∀ i ∈ s, 0 ≤ f i) : 0 ≤ 𝔼 i ∈ s, f i := + smul_nonneg (by positivity) <| sum_nonneg hf + +end PosSMulMono + +section PosSMulMono +variable {M N : Type*} [AddCommMonoid M] [Module ℚ≥0 M] [OrderedAddCommMonoid N] [Module ℚ≥0 N] + [PosSMulMono ℚ≥0 N] {m : M → N} {p : M → Prop} {f : ι → M} {s : Finset ι} + +/-- Let `{a | p a}` be an additive subsemigroup of an additive commutative monoid `M`. If `m` is a +subadditive function (`m (a + b) ≤ m a + m b`) preserved under division by a natural, `f` is a +function valued in that subsemigroup and `s` is a nonempty set, then +`m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i)`. -/ +lemma le_expect_nonempty_of_subadditive_on_pred (h_add : ∀ a b, p a → p b → m (a + b) ≤ m a + m b) + (hp_add : ∀ a b, p a → p b → p (a + b)) (h_div : ∀ (n : ℕ) a, p a → m (a /ℚ n) = m a /ℚ n) + (hs_nonempty : s.Nonempty) (hs : ∀ i ∈ s, p (f i)) : + m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i) := by + simp only [expect, h_div _ _ (sum_induction_nonempty _ _ hp_add hs_nonempty hs)] + exact smul_le_smul_of_nonneg_left + (le_sum_nonempty_of_subadditive_on_pred _ _ h_add hp_add _ _ hs_nonempty hs) <| by positivity + +/-- If `m : M → N` is a subadditive function (`m (a + b) ≤ m a + m b`) and `s` is a nonempty set, +then `m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i)`. -/ +lemma le_expect_nonempty_of_subadditive (m : M → N) (h_mul : ∀ a b, m (a + b) ≤ m a + m b) + (h_div : ∀ (n : ℕ) a, m (a /ℚ n) = m a /ℚ n) (hs : s.Nonempty) : + m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i) := + le_expect_nonempty_of_subadditive_on_pred (p := fun _ ↦ True) (by simpa) (by simp) (by simpa) hs + (by simp) + +/-- Let `{a | p a}` be a subsemigroup of a commutative monoid `M`. If `m` is a subadditive function +(`m (x + y) ≤ m x + m y`, `m 0 = 0`) preserved under division by a natural and `f` is a function +valued in that subsemigroup, then `m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i)`. -/ +lemma le_expect_of_subadditive_on_pred (h_zero : m 0 = 0) + (h_add : ∀ a b, p a → p b → m (a + b) ≤ m a + m b) (hp_add : ∀ a b, p a → p b → p (a + b)) + (h_div : ∀ (n : ℕ) a, p a → m (a /ℚ n) = m a /ℚ n) + (hs : ∀ i ∈ s, p (f i)) : m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i) := by + obtain rfl | hs_nonempty := s.eq_empty_or_nonempty + · simp [h_zero] + · exact le_expect_nonempty_of_subadditive_on_pred h_add hp_add h_div hs_nonempty hs + +-- TODO: Contribute back better docstring to `le_prod_of_submultiplicative` +/-- If `m` is a subadditive function (`m (x + y) ≤ m x + m y`, `m 0 = 0`) preserved under division +by a natural, then `m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i)`. -/ +lemma le_expect_of_subadditive (h_zero : m 0 = 0) (h_add : ∀ a b, m (a + b) ≤ m a + m b) + (h_div : ∀ (n : ℕ) a, m (a /ℚ n) = m a /ℚ n) : m (𝔼 i ∈ s, f i) ≤ 𝔼 i ∈ s, m (f i) := + le_expect_of_subadditive_on_pred (p := fun _ ↦ True) h_zero (by simpa) (by simp) (by simpa) + (by simp) + +end PosSMulMono +end OrderedAddCommMonoid + +section OrderedCancelAddCommMonoid +variable [OrderedCancelAddCommMonoid α] [Module ℚ≥0 α] {s : Finset ι} {f g : ι → α} +section PosSMulStrictMono +variable [PosSMulStrictMono ℚ≥0 α] + +lemma expect_pos (hf : ∀ i ∈ s, 0 < f i) (hs : s.Nonempty) : 0 < 𝔼 i ∈ s, f i := + smul_pos (inv_pos.2 <| mod_cast hs.card_pos) <| sum_pos hf hs + +end PosSMulStrictMono +end OrderedCancelAddCommMonoid + +section LinearOrderedAddCommMonoid +variable [LinearOrderedAddCommMonoid α] [Module ℚ≥0 α] [PosSMulMono ℚ≥0 α] {s : Finset ι} + {f : ι → α} {a : α} + +lemma exists_lt_of_lt_expect (hs : s.Nonempty) (h : a < 𝔼 i ∈ s, f i) : ∃ x ∈ s, a < f x := by + contrapose! h; exact expect_le hs h + +lemma exists_lt_of_expect_lt (hs : s.Nonempty) (h : 𝔼 i ∈ s, f i < a) : ∃ x ∈ s, f x < a := by + contrapose! h; exact le_expect hs h + +end LinearOrderedAddCommMonoid + +section LinearOrderedAddCommGroup +variable [LinearOrderedAddCommGroup α] [Module ℚ≥0 α] [PosSMulMono ℚ≥0 α] + +lemma abs_expect_le (s : Finset ι) (f : ι → α) : |𝔼 i ∈ s, f i| ≤ 𝔼 i ∈ s, |f i| := + le_expect_of_subadditive abs_zero abs_add (fun _ ↦ abs_nnqsmul _) + +end LinearOrderedAddCommGroup + +section LinearOrderedCommSemiring +variable [LinearOrderedCommSemiring R] [ExistsAddOfLE R] [Module ℚ≥0 R] [PosSMulMono ℚ≥0 R] + +/-- **Cauchy-Schwarz inequality** in terms of `Finset.expect`. -/ +lemma expect_mul_sq_le_sq_mul_sq (s : Finset ι) (f g : ι → R) : + (𝔼 i ∈ s, f i * g i) ^ 2 ≤ (𝔼 i ∈ s, f i ^ 2) * 𝔼 i ∈ s, g i ^ 2 := by + simp only [expect, smul_pow, inv_pow, smul_mul_smul_comm, ← sq] + gcongr + exact sum_mul_sq_le_sq_mul_sq .. + +end LinearOrderedCommSemiring +end Finset + +open Finset + +namespace Fintype +variable [Fintype ι] [Fintype κ] + +section OrderedAddCommMonoid +variable [OrderedAddCommMonoid α] [Module ℚ≥0 α] {f : ι → α} + +lemma expect_eq_zero_iff_of_nonneg [Nonempty ι] (hf : 0 ≤ f) : 𝔼 i, f i = 0 ↔ f = 0 := by + simp [expect, sum_eq_zero_iff_of_nonneg hf, univ_nonempty.ne_empty] + +lemma expect_eq_zero_iff_of_nonpos [Nonempty ι] (hf : f ≤ 0) : 𝔼 i, f i = 0 ↔ f = 0 := by + simp [expect, sum_eq_zero_iff_of_nonpos hf, univ_nonempty.ne_empty] + +end OrderedAddCommMonoid +end Fintype + +open Finset + +namespace Mathlib.Meta.Positivity +open Qq Lean Meta Finset +open scoped BigOperators + +/-- Positivity extension for `Finset.expect`. -/ +@[positivity Finset.expect _ _] +def evalFinsetExpect : PositivityExt where eval {u α} zα pα e := do + match e with + | ~q(@Finset.expect $ι _ $instα $instmod $s $f) => + let i : Q($ι) ← mkFreshExprMVarQ q($ι) .syntheticOpaque + have body : Q($α) := .betaRev f #[i] + let rbody ← core zα pα body + let p_pos : Option Q(0 < $e) := ← (do + let .positive pbody := rbody | pure none -- Fail if the body is not provably positive + let .some ps ← proveFinsetNonempty s | pure none + let .some pα' ← trySynthInstanceQ q(OrderedCancelAddCommMonoid $α) | pure none + let .some instαordsmul ← trySynthInstanceQ q(PosSMulStrictMono ℚ≥0 $α) | pure none + assumeInstancesCommute + let pr : Q(∀ i, 0 < $f i) ← mkLambdaFVars #[i] pbody + return some q(@expect_pos $ι $α $pα' $instmod $s $f $instαordsmul (fun i _ ↦ $pr i) $ps)) + -- Try to show that the sum is positive + if let some p_pos := p_pos then + return .positive p_pos + -- Fall back to showing that the sum is nonnegative + else + let pbody ← rbody.toNonneg + let pr : Q(∀ i, 0 ≤ $f i) ← mkLambdaFVars #[i] pbody + let instαordmon ← synthInstanceQ q(OrderedAddCommMonoid $α) + let instαordsmul ← synthInstanceQ q(PosSMulMono ℚ≥0 $α) + assumeInstancesCommute + return .nonnegative q(@expect_nonneg $ι $α $instαordmon $instmod $s $f $instαordsmul + fun i _ ↦ $pr i) + | _ => throwError "not Finset.expect" + +example (n : ℕ) (a : ℕ → ℚ) : 0 ≤ 𝔼 j ∈ range n, a j^2 := by positivity +example (a : ULift.{2} ℕ → ℚ) (s : Finset (ULift.{2} ℕ)) : 0 ≤ 𝔼 j ∈ s, a j^2 := by positivity +example (n : ℕ) (a : ℕ → ℚ) : 0 ≤ 𝔼 j : Fin 8, 𝔼 i ∈ range n, (a j^2 + i ^ 2) := by positivity +example (n : ℕ) (a : ℕ → ℚ) : 0 < 𝔼 j : Fin (n + 1), (a j^2 + 1) := by positivity +example (a : ℕ → ℚ) : 0 < 𝔼 j ∈ ({1} : Finset ℕ), (a j^2 + 1) := by positivity + +end Mathlib.Meta.Positivity diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean index 2f1547de189c6..d5cdc6b8f86e7 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Finset.lean @@ -210,6 +210,16 @@ theorem prod_le_prod_fiberwise_of_prod_fiber_le_one' {t : Finset ι'} {g : ι end OrderedCommMonoid +@[to_additive] +lemma max_prod_le [LinearOrderedCommMonoid M] {f g : ι → M} {s : Finset ι} : + max (s.prod f) (s.prod g) ≤ s.prod (fun i ↦ max (f i) (g i)) := + Multiset.max_prod_le + +@[to_additive] +lemma prod_min_le [LinearOrderedCommMonoid M] {f g : ι → M} {s : Finset ι} : + s.prod (fun i ↦ min (f i) (g i)) ≤ min (s.prod f) (s.prod g) := + Multiset.prod_min_le + theorem abs_sum_le_sum_abs {G : Type*} [LinearOrderedAddCommGroup G] (f : ι → G) (s : Finset ι) : |∑ i ∈ s, f i| ≤ ∑ i ∈ s, |f i| := le_sum_of_subadditive _ abs_zero abs_add s f @@ -221,6 +231,16 @@ theorem abs_sum_of_nonneg' {G : Type*} [LinearOrderedAddCommGroup G] {f : ι → (hf : ∀ i, 0 ≤ f i) : |∑ i ∈ s, f i| = ∑ i ∈ s, f i := by rw [abs_of_nonneg (Finset.sum_nonneg' hf)] +section CommMonoid +variable [CommMonoid α] [LE α] [CovariantClass α α (· * ·) (· ≤ ·)] {s : Finset ι} {f : ι → α} + +@[to_additive (attr := simp)] +lemma mulLECancellable_prod : + MulLECancellable (∏ i ∈ s, f i) ↔ ∀ ⦃i⦄, i ∈ s → MulLECancellable (f i) := by + induction' s using Finset.cons_induction with i s hi ih <;> simp [*] + +end CommMonoid + section Pigeonhole variable [DecidableEq β] diff --git a/Mathlib/Algebra/Order/BigOperators/Group/List.lean b/Mathlib/Algebra/Order/BigOperators/Group/List.lean index 3d5a671d2a7f8..94dd5a115870c 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/List.lean @@ -119,6 +119,24 @@ lemma one_le_prod_of_one_le [Preorder M] [CovariantClass M M (· * ·) (· ≤ rw [prod_cons] exact one_le_mul (hl₁ hd (mem_cons_self hd tl)) (ih fun x h => hl₁ x (mem_cons_of_mem hd h)) +@[to_additive] +lemma max_prod_le (l : List α) (f g : α → M) [LinearOrder M] + [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (Function.swap (· * ·)) (· ≤ ·)] : + max (l.map f).prod (l.map g).prod ≤ (l.map fun i ↦ max (f i) (g i)).prod := by + rw [max_le_iff] + constructor <;> apply List.prod_le_prod' <;> intros + · apply le_max_left + · apply le_max_right + +@[to_additive] +lemma prod_min_le [LinearOrder M] [CovariantClass M M (· * ·) (· ≤ ·)] + [CovariantClass M M (Function.swap (· * ·)) (· ≤ ·)] (l : List α) (f g : α → M) : + (l.map fun i ↦ min (f i) (g i)).prod ≤ min (l.map f).prod (l.map g).prod := by + rw [le_min_iff] + constructor <;> apply List.prod_le_prod' <;> intros + · apply min_le_left + · apply min_le_right + end Monoid -- TODO: develop theory of tropical rings @@ -164,7 +182,7 @@ variable [CanonicallyOrderedCommMonoid M] {l : List M} @[to_additive] lemma prod_eq_one_iff : l.prod = 1 ↔ ∀ x ∈ l, x = (1 : M) := ⟨all_one_of_le_one_le_of_prod_eq_one fun _ _ => one_le _, fun h => by - rw [List.eq_replicate.2 ⟨_, h⟩, prod_replicate, one_pow] + rw [List.eq_replicate_iff.2 ⟨_, h⟩, prod_replicate, one_pow] · exact (length l) · rfl⟩ diff --git a/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean b/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean new file mode 100644 index 0000000000000..f43f25244887d --- /dev/null +++ b/Mathlib/Algebra/Order/BigOperators/Group/LocallyFinite.lean @@ -0,0 +1,80 @@ +/- +Copyright (c) 2024 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.BigOperators.Group.Finset +import Mathlib.Order.Interval.Finset.Basic + +/-! +# Big operators indexed by intervals + +This file proves lemmas about `∏ x ∈ Ixx a b, f x` and `∑ x ∈ Ixx a b, f x`. +-/ + +variable {α β : Type*} [PartialOrder α] [CommMonoid β] {f : α → β} {a b : α} + +namespace Finset +section LocallyFiniteOrder +variable [LocallyFiniteOrder α] + +@[to_additive] +lemma left_mul_prod_Ioc (h : a ≤ b) : f a * ∏ x ∈ Ioc a b, f x = ∏ x ∈ Icc a b, f x := by + rw [Icc_eq_cons_Ioc h, prod_cons] + +@[to_additive] +lemma prod_Ioc_mul_left (h : a ≤ b) : (∏ x ∈ Ioc a b, f x) * f a = ∏ x ∈ Icc a b, f x := by + rw [mul_comm, left_mul_prod_Ioc h] + +@[to_additive] +lemma right_mul_prod_Ico (h : a ≤ b) : f b * ∏ x ∈ Ico a b, f x = ∏ x ∈ Icc a b, f x := by + rw [Icc_eq_cons_Ico h, prod_cons] + +@[to_additive] +lemma prod_Ico_mul_right (h : a ≤ b) : (∏ x ∈ Ico a b, f x) * f b = ∏ x ∈ Icc a b, f x := by + rw [mul_comm, right_mul_prod_Ico h] + +@[to_additive] +lemma left_mul_prod_Ioo (h : a < b) : f a * ∏ x ∈ Ioo a b, f x = ∏ x ∈ Ico a b, f x := by + rw [Ico_eq_cons_Ioo h, prod_cons] + +@[to_additive] +lemma prod_Ioo_mul_left (h : a < b) : (∏ x ∈ Ioo a b, f x) * f a = ∏ x ∈ Ico a b, f x := by + rw [mul_comm, left_mul_prod_Ioo h] + +@[to_additive] +lemma right_mul_prod_Ioo (h : a < b) : f b * ∏ x ∈ Ioo a b, f x = ∏ x ∈ Ioc a b, f x := by + rw [Ioc_eq_cons_Ioo h, prod_cons] + +@[to_additive] +lemma prod_Ioo_mul_right (h : a < b) : (∏ x ∈ Ioo a b, f x) * f b = ∏ x ∈ Ioc a b, f x := by + rw [mul_comm, right_mul_prod_Ioo h] + +end LocallyFiniteOrder + +section LocallyFiniteOrderTop +variable [LocallyFiniteOrderTop α] + +@[to_additive] +lemma left_mul_prod_Ioi (a : α) : f a * ∏ x ∈ Ioi a, f x = ∏ x ∈ Ici a, f x := by + rw [Ici_eq_cons_Ioi, prod_cons] + +@[to_additive] +lemma prod_Ioi_mul_left (a : α) : (∏ x ∈ Ioi a, f x) * f a = ∏ x ∈ Ici a, f x := by + rw [mul_comm, left_mul_prod_Ioi] + +end LocallyFiniteOrderTop + +section LocallyFiniteOrderBot +variable [LocallyFiniteOrderBot α] + +@[to_additive] +lemma right_mul_prod_Iio (a : α) : f a * ∏ x ∈ Iio a, f x = ∏ x ∈ Iic a, f x := by + rw [Iic_eq_cons_Iio, prod_cons] + +@[to_additive] +lemma prod_Iio_mul_right (a : α) : (∏ x ∈ Iio a, f x) * f a = ∏ x ∈ Iic a, f x := by + rw [mul_comm, right_mul_prod_Iio] + +end LocallyFiniteOrderBot +end Finset diff --git a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean index 52ae9a3e331ce..ad405fe75fb40 100644 --- a/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean +++ b/Mathlib/Algebra/Order/BigOperators/Group/Multiset.lean @@ -156,6 +156,20 @@ lemma max_le_of_forall_le {α : Type*} [LinearOrder α] [OrderBot α] (l : Multi induction l using Quotient.inductionOn simpa using List.max_le_of_forall_le _ _ h +@[to_additive] +lemma max_prod_le [LinearOrderedCommMonoid α] {s : Multiset ι} {f g : ι → α} : + max (s.map f).prod (s.map g).prod ≤ (s.map fun i ↦ max (f i) (g i)).prod := by + obtain ⟨l⟩ := s + simp_rw [Multiset.quot_mk_to_coe'', Multiset.map_coe, Multiset.prod_coe] + apply List.max_prod_le + +@[to_additive] +lemma prod_min_le [LinearOrderedCommMonoid α] {s : Multiset ι} {f g : ι → α} : + (s.map fun i ↦ min (f i) (g i)).prod ≤ min (s.map f).prod (s.map g).prod := by + obtain ⟨l⟩ := s + simp_rw [Multiset.quot_mk_to_coe'', Multiset.map_coe, Multiset.prod_coe] + apply List.prod_min_le + lemma abs_sum_le_sum_abs [LinearOrderedAddCommGroup α] {s : Multiset α} : |s.sum| ≤ (s.map abs).sum := le_sum_of_subadditive _ abs_zero abs_add s diff --git a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean index 77f4d768aee3b..e38120c46d7ac 100644 --- a/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean +++ b/Mathlib/Algebra/Order/BigOperators/GroupWithZero/List.lean @@ -51,12 +51,12 @@ theorem prod_map_le_prod_map₀ {ι : Type*} {s : List ι} (f : ι → R) (g : · intro i hi apply h simp [hi] - apply prod_nonneg - · simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + · apply prod_nonneg + simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] intro a ha apply h0 simp [ha] - apply (h0 _ _).trans (h _ _) <;> simp + · apply (h0 _ _).trans (h _ _) <;> simp omit [PosMulMono R] variable [PosMulStrictMono R] [NeZero (1 : R)] @@ -89,11 +89,11 @@ theorem prod_map_lt_prod_map {ι : Type*} {s : List ι} (hs : s ≠ []) apply le_of_lt apply h simp [hi] - apply prod_pos - · simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + · apply prod_pos + simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] intro a ha apply h0 simp [ha] - apply le_of_lt ((h0 _ _).trans (h _ _)) <;> simp + · apply le_of_lt ((h0 _ _).trans (h _ _)) <;> simp end List diff --git a/Mathlib/Algebra/Order/CauSeq/BigOperators.lean b/Mathlib/Algebra/Order/CauSeq/BigOperators.lean index 2ac291cf0c7a6..99ac7eb6f4dd3 100644 --- a/Mathlib/Algebra/Order/CauSeq/BigOperators.lean +++ b/Mathlib/Algebra/Order/CauSeq/BigOperators.lean @@ -188,7 +188,7 @@ lemma geo_series [Nontrivial β] (x : β) (hx1 : abv x < 1) : · gcongr exact sub_le_self _ (abv_pow abv x n ▸ abv_nonneg _ _) refine div_nonneg (sub_nonneg.2 ?_) (sub_nonneg.2 <| le_of_lt hx1) - exact pow_le_one _ (by positivity) hx1.le + exact pow_le_one₀ (by positivity) hx1.le · intro n _ rw [← one_mul (abv x ^ n), pow_succ'] gcongr @@ -213,7 +213,7 @@ lemma series_ratio_test {f : ℕ → β} (n : ℕ) (r : α) (hr0 : 0 ≤ r) (hr1 positivity · have kn : k + n.succ ≥ n.succ := by rw [← zero_add n.succ]; exact add_le_add (Nat.zero_le _) (by simp) - erw [hk, Nat.succ_add, pow_succ r, ← mul_assoc] + rw [hk, Nat.succ_add, pow_succ r, ← mul_assoc] refine le_trans (by rw [mul_comm] <;> exact h _ (Nat.le_of_succ_le kn)) (mul_le_mul_of_nonneg_right ?_ hr0) diff --git a/Mathlib/Algebra/Order/Chebyshev.lean b/Mathlib/Algebra/Order/Chebyshev.lean index ebbe5643ee00c..439d79b0c4e2b 100644 --- a/Mathlib/Algebra/Order/Chebyshev.lean +++ b/Mathlib/Algebra/Order/Chebyshev.lean @@ -4,9 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mantas Bakšys, Yaël Dillies -/ import Mathlib.Algebra.Order.BigOperators.Group.Finset +import Mathlib.Algebra.Order.Monovary import Mathlib.Algebra.Order.Rearrangement -import Mathlib.Algebra.Order.Ring.Basic import Mathlib.GroupTheory.Perm.Cycle.Basic +import Mathlib.Tactic.GCongr +import Mathlib.Tactic.Positivity.Basic +import Mathlib.Tactic.Positivity.Finset /-! # Chebyshev's sum inequality @@ -44,28 +47,26 @@ variable {ι α β : Type*} section SMul - -variable [LinearOrderedRing α] [LinearOrderedAddCommGroup β] [Module α β] [OrderedSMul α β] - {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} +variable [LinearOrderedSemiring α] [ExistsAddOfLE α] [LinearOrderedCancelAddCommMonoid β] + [Module α β] [OrderedSMul α β] {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} /-- **Chebyshev's Sum Inequality**: When `f` and `g` monovary together (eg they are both monotone/antitone), the scalar product of their sum is less than the size of the set times their scalar product. -/ theorem MonovaryOn.sum_smul_sum_le_card_smul_sum (hfg : MonovaryOn f g s) : - ((∑ i ∈ s, f i) • ∑ i ∈ s, g i) ≤ s.card • ∑ i ∈ s, f i • g i := by + (∑ i ∈ s, f i) • ∑ i ∈ s, g i ≤ s.card • ∑ i ∈ s, f i • g i := by classical - obtain ⟨σ, hσ, hs⟩ := s.countable_toSet.exists_cycleOn - rw [← card_range s.card, sum_smul_sum_eq_sum_perm hσ] - exact - sum_le_card_nsmul _ _ _ fun n _ => - hfg.sum_smul_comp_perm_le_sum_smul fun x hx => hs fun h => hx <| IsFixedPt.perm_pow h _ + obtain ⟨σ, hσ, hs⟩ := s.countable_toSet.exists_cycleOn + rw [← card_range s.card, sum_smul_sum_eq_sum_perm hσ] + exact sum_le_card_nsmul _ _ _ fun n _ ↦ + hfg.sum_smul_comp_perm_le_sum_smul fun x hx ↦ hs fun h ↦ hx <| IsFixedPt.perm_pow h _ /-- **Chebyshev's Sum Inequality**: When `f` and `g` antivary together (eg one is monotone, the other is antitone), the scalar product of their sum is less than the size of the set times their scalar product. -/ theorem AntivaryOn.card_smul_sum_le_sum_smul_sum (hfg : AntivaryOn f g s) : - (s.card • ∑ i ∈ s, f i • g i) ≤ (∑ i ∈ s, f i) • ∑ i ∈ s, g i := by - exact hfg.dual_right.sum_smul_sum_le_card_smul_sum + s.card • ∑ i ∈ s, f i • g i ≤ (∑ i ∈ s, f i) • ∑ i ∈ s, g i := + hfg.dual_right.sum_smul_sum_le_card_smul_sum variable [Fintype ι] @@ -73,15 +74,15 @@ variable [Fintype ι] monotone/antitone), the scalar product of their sum is less than the size of the set times their scalar product. -/ theorem Monovary.sum_smul_sum_le_card_smul_sum (hfg : Monovary f g) : - ((∑ i, f i) • ∑ i, g i) ≤ Fintype.card ι • ∑ i, f i • g i := + (∑ i, f i) • ∑ i, g i ≤ Fintype.card ι • ∑ i, f i • g i := (hfg.monovaryOn _).sum_smul_sum_le_card_smul_sum /-- **Chebyshev's Sum Inequality**: When `f` and `g` antivary together (eg one is monotone, the other is antitone), the scalar product of their sum is less than the size of the set times their scalar product. -/ theorem Antivary.card_smul_sum_le_sum_smul_sum (hfg : Antivary f g) : - (Fintype.card ι • ∑ i, f i • g i) ≤ (∑ i, f i) • ∑ i, g i := by - exact (hfg.dual_right.monovaryOn _).sum_smul_sum_le_card_smul_sum + Fintype.card ι • ∑ i, f i • g i ≤ (∑ i, f i) • ∑ i, g i := + (hfg.dual_right.monovaryOn _).sum_smul_sum_le_card_smul_sum end SMul @@ -93,14 +94,13 @@ Special cases of the above when scalar multiplication is actually multiplication section Mul - -variable [LinearOrderedRing α] {s : Finset ι} {σ : Perm ι} {f g : ι → α} +variable [LinearOrderedSemiring α] [ExistsAddOfLE α] {s : Finset ι} {σ : Perm ι} {f g : ι → α} /-- **Chebyshev's Sum Inequality**: When `f` and `g` monovary together (eg they are both monotone/antitone), the product of their sum is less than the size of the set times their scalar product. -/ theorem MonovaryOn.sum_mul_sum_le_card_mul_sum (hfg : MonovaryOn f g s) : - ((∑ i ∈ s, f i) * ∑ i ∈ s, g i) ≤ s.card * ∑ i ∈ s, f i * g i := by + (∑ i ∈ s, f i) * ∑ i ∈ s, g i ≤ s.card * ∑ i ∈ s, f i * g i := by rw [← nsmul_eq_mul] exact hfg.sum_smul_sum_le_card_smul_sum @@ -108,10 +108,26 @@ theorem MonovaryOn.sum_mul_sum_le_card_mul_sum (hfg : MonovaryOn f g s) : other is antitone), the product of their sum is greater than the size of the set times their scalar product. -/ theorem AntivaryOn.card_mul_sum_le_sum_mul_sum (hfg : AntivaryOn f g s) : - ((s.card : α) * ∑ i ∈ s, f i * g i) ≤ (∑ i ∈ s, f i) * ∑ i ∈ s, g i := by + (s.card : α) * ∑ i ∈ s, f i * g i ≤ (∑ i ∈ s, f i) * ∑ i ∈ s, g i := by rw [← nsmul_eq_mul] exact hfg.card_smul_sum_le_sum_smul_sum +/-- Special case of **Jensen's inequality** for sums of powers. -/ +lemma pow_sum_le_card_mul_sum_pow (hf : ∀ i ∈ s, 0 ≤ f i) : + ∀ n, (∑ i ∈ s, f i) ^ (n + 1) ≤ (s.card : α) ^ n * ∑ i ∈ s, f i ^ (n + 1) + | 0 => by simp + | n + 1 => + calc + _ = (∑ i ∈ s, f i) ^ (n + 1) * ∑ i ∈ s, f i := by rw [pow_succ] + _ ≤ (s.card ^ n * ∑ i ∈ s, f i ^ (n + 1)) * ∑ i ∈ s, f i := by + gcongr + exacts [sum_nonneg hf, pow_sum_le_card_mul_sum_pow hf _] + _ = s.card ^ n * ((∑ i ∈ s, f i ^ (n + 1)) * ∑ i ∈ s, f i) := by rw [mul_assoc] + _ ≤ s.card ^ n * (s.card * ∑ i ∈ s, f i ^ (n + 1) * f i) := by + gcongr _ * ?_ + exact ((monovaryOn_self ..).pow_left₀ hf _).sum_mul_sum_le_card_mul_sum + _ = _ := by simp_rw [← mul_assoc, ← pow_succ] + /-- Special case of **Chebyshev's Sum Inequality** or the **Cauchy-Schwarz Inequality**: The square of the sum is less than the size of the set times the sum of the squares. -/ theorem sq_sum_le_card_mul_sum_sq : (∑ i ∈ s, f i) ^ 2 ≤ s.card * ∑ i ∈ s, f i ^ 2 := by @@ -124,25 +140,32 @@ variable [Fintype ι] monotone/antitone), the product of their sum is less than the size of the set times their scalar product. -/ theorem Monovary.sum_mul_sum_le_card_mul_sum (hfg : Monovary f g) : - ((∑ i, f i) * ∑ i, g i) ≤ Fintype.card ι * ∑ i, f i * g i := + (∑ i, f i) * ∑ i, g i ≤ Fintype.card ι * ∑ i, f i * g i := (hfg.monovaryOn _).sum_mul_sum_le_card_mul_sum /-- **Chebyshev's Sum Inequality**: When `f` and `g` antivary together (eg one is monotone, the other is antitone), the product of their sum is less than the size of the set times their scalar product. -/ theorem Antivary.card_mul_sum_le_sum_mul_sum (hfg : Antivary f g) : - ((Fintype.card ι : α) * ∑ i, f i * g i) ≤ (∑ i, f i) * ∑ i, g i := + Fintype.card ι * ∑ i, f i * g i ≤ (∑ i, f i) * ∑ i, g i := (hfg.antivaryOn _).card_mul_sum_le_sum_mul_sum end Mul -variable [LinearOrderedField α] {s : Finset ι} {f : ι → α} +variable [LinearOrderedSemifield α] [ExistsAddOfLE α] {s : Finset ι} {f : ι → α} + +/-- Special case of **Jensen's inequality** for sums of powers. -/ +lemma pow_sum_div_card_le_sum_pow (hf : ∀ i ∈ s, 0 ≤ f i) (n : ℕ) : + (∑ i ∈ s, f i) ^ (n + 1) / s.card ^ n ≤ ∑ i ∈ s, f i ^ (n + 1) := by + obtain rfl | hs := s.eq_empty_or_nonempty + · simp + rw [div_le_iff₀' (by positivity)] + exact pow_sum_le_card_mul_sum_pow hf _ theorem sum_div_card_sq_le_sum_sq_div_card : ((∑ i ∈ s, f i) / s.card) ^ 2 ≤ (∑ i ∈ s, f i ^ 2) / s.card := by obtain rfl | hs := s.eq_empty_or_nonempty · simp - rw [← card_pos, ← @Nat.cast_pos α] at hs - rw [div_pow, div_le_div_iff (sq_pos_of_ne_zero hs.ne') hs, sq (s.card : α), mul_left_comm, ← - mul_assoc] - exact mul_le_mul_of_nonneg_right sq_sum_le_card_mul_sum_sq hs.le + rw [div_pow, div_le_div_iff (by positivity) (by positivity), sq (s.card : α), mul_left_comm, + ← mul_assoc] + exact mul_le_mul_of_nonneg_right sq_sum_le_card_mul_sum_sq (by positivity) diff --git a/Mathlib/Algebra/Order/CompleteField.lean b/Mathlib/Algebra/Order/CompleteField.lean index 2c8942e53c15c..680ebceb3f631 100644 --- a/Mathlib/Algebra/Order/CompleteField.lean +++ b/Mathlib/Algebra/Order/CompleteField.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Alex J. Best, Yaël Dillies -/ import Mathlib.Algebra.Order.Archimedean.Hom -import Mathlib.Algebra.Order.Pointwise +import Mathlib.Algebra.Order.Group.Pointwise.CompleteLattice import Mathlib.Analysis.SpecialFunctions.Pow.Real /-! diff --git a/Mathlib/Algebra/Order/Field/Basic.lean b/Mathlib/Algebra/Order/Field/Basic.lean index 2385c27aac032..4e76076e79d17 100644 --- a/Mathlib/Algebra/Order/Field/Basic.lean +++ b/Mathlib/Algebra/Order/Field/Basic.lean @@ -5,9 +5,9 @@ Authors: Robert Y. Lewis, Leonardo de Moura, Mario Carneiro, Floris van Doorn -/ import Mathlib.Algebra.CharZero.Lemmas import Mathlib.Algebra.Order.Field.Defs +import Mathlib.Algebra.Order.GroupWithZero.Unbundled.Lemmas import Mathlib.Algebra.Order.Ring.Abs import Mathlib.Order.Bounds.OrderIso -import Mathlib.Tactic.Bound.Attribute import Mathlib.Tactic.Positivity.Core /-! @@ -23,171 +23,143 @@ section LinearOrderedSemifield variable [LinearOrderedSemifield α] {a b c d e : α} {m n : ℤ} -/-- `Equiv.mulLeft₀` as an order_iso. -/ -@[simps! (config := { simpRhs := true })] -def OrderIso.mulLeft₀ (a : α) (ha : 0 < a) : α ≃o α := - { Equiv.mulLeft₀ a ha.ne' with map_rel_iff' := @fun _ _ => mul_le_mul_left ha } - -/-- `Equiv.mulRight₀` as an order_iso. -/ -@[simps! (config := { simpRhs := true })] -def OrderIso.mulRight₀ (a : α) (ha : 0 < a) : α ≃o α := - { Equiv.mulRight₀ a ha.ne' with map_rel_iff' := @fun _ _ => mul_le_mul_right ha } - /-! ### Relating one division with another term. -/ -theorem lt_div_iff (hc : 0 < c) : a < b / c ↔ a * c < b := - lt_iff_lt_of_le_iff_le <| div_le_iff₀ hc - -theorem lt_div_iff' (hc : 0 < c) : a < b / c ↔ c * a < b := by rw [mul_comm, lt_div_iff hc] +@[deprecated lt_div_iff₀ (since := "2024-10-02")] +theorem lt_div_iff (hc : 0 < c) : a < b / c ↔ a * c < b := lt_div_iff₀ hc -theorem div_lt_iff (hc : 0 < c) : b / c < a ↔ b < a * c := - lt_iff_lt_of_le_iff_le (le_div_iff₀ hc) +@[deprecated lt_div_iff₀' (since := "2024-10-02")] +theorem lt_div_iff' (hc : 0 < c) : a < b / c ↔ c * a < b := lt_div_iff₀' hc -theorem div_lt_iff' (hc : 0 < c) : b / c < a ↔ b < c * a := by rw [mul_comm, div_lt_iff hc] +@[deprecated div_lt_iff₀ (since := "2024-10-02")] +theorem div_lt_iff (hc : 0 < c) : b / c < a ↔ b < a * c := div_lt_iff₀ hc -lemma div_lt_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b < c ↔ a / c < b := by - rw [div_lt_iff hb, div_lt_iff' hc] +@[deprecated div_lt_iff₀' (since := "2024-10-02")] +theorem div_lt_iff' (hc : 0 < c) : b / c < a ↔ b < c * a := div_lt_iff₀' hc -theorem inv_mul_le_iff (h : 0 < b) : b⁻¹ * a ≤ c ↔ a ≤ b * c := by - rw [inv_eq_one_div, mul_comm, ← div_eq_mul_one_div] - exact div_le_iff₀' h +@[deprecated inv_mul_le_iff₀ (since := "2024-10-02")] +theorem inv_mul_le_iff (h : 0 < b) : b⁻¹ * a ≤ c ↔ a ≤ b * c := inv_mul_le_iff₀ h -theorem inv_mul_le_iff' (h : 0 < b) : b⁻¹ * a ≤ c ↔ a ≤ c * b := by rw [inv_mul_le_iff h, mul_comm] +@[deprecated inv_mul_le_iff₀' (since := "2024-10-02")] +theorem inv_mul_le_iff' (h : 0 < b) : b⁻¹ * a ≤ c ↔ a ≤ c * b := inv_mul_le_iff₀' h -theorem mul_inv_le_iff (h : 0 < b) : a * b⁻¹ ≤ c ↔ a ≤ b * c := by rw [mul_comm, inv_mul_le_iff h] +@[deprecated mul_inv_le_iff₀' (since := "2024-10-02")] +theorem mul_inv_le_iff (h : 0 < b) : a * b⁻¹ ≤ c ↔ a ≤ b * c := mul_inv_le_iff₀' h -theorem mul_inv_le_iff' (h : 0 < b) : a * b⁻¹ ≤ c ↔ a ≤ c * b := by rw [mul_comm, inv_mul_le_iff' h] +@[deprecated mul_inv_le_iff₀ (since := "2024-10-02")] +theorem mul_inv_le_iff' (h : 0 < b) : a * b⁻¹ ≤ c ↔ a ≤ c * b := mul_inv_le_iff₀ h -theorem div_self_le_one (a : α) : a / a ≤ 1 := - if h : a = 0 then by simp [h] else by simp [h] +@[deprecated inv_mul_lt_iff₀ (since := "2024-10-02")] +theorem inv_mul_lt_iff (h : 0 < b) : b⁻¹ * a < c ↔ a < b * c := inv_mul_lt_iff₀ h -theorem inv_mul_lt_iff (h : 0 < b) : b⁻¹ * a < c ↔ a < b * c := by - rw [inv_eq_one_div, mul_comm, ← div_eq_mul_one_div] - exact div_lt_iff' h +@[deprecated inv_mul_lt_iff₀' (since := "2024-10-02")] +theorem inv_mul_lt_iff' (h : 0 < b) : b⁻¹ * a < c ↔ a < c * b := inv_mul_lt_iff₀' h -theorem inv_mul_lt_iff' (h : 0 < b) : b⁻¹ * a < c ↔ a < c * b := by rw [inv_mul_lt_iff h, mul_comm] +@[deprecated mul_inv_lt_iff₀' (since := "2024-10-02")] +theorem mul_inv_lt_iff (h : 0 < b) : a * b⁻¹ < c ↔ a < b * c := mul_inv_lt_iff₀' h -theorem mul_inv_lt_iff (h : 0 < b) : a * b⁻¹ < c ↔ a < b * c := by rw [mul_comm, inv_mul_lt_iff h] +@[deprecated mul_inv_lt_iff₀ (since := "2024-10-02")] +theorem mul_inv_lt_iff' (h : 0 < b) : a * b⁻¹ < c ↔ a < c * b := mul_inv_lt_iff₀ h -theorem mul_inv_lt_iff' (h : 0 < b) : a * b⁻¹ < c ↔ a < c * b := by rw [mul_comm, inv_mul_lt_iff' h] +@[deprecated inv_le_iff_one_le_mul₀ (since := "2024-10-03")] +theorem inv_pos_le_iff_one_le_mul (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ b * a := inv_le_iff_one_le_mul₀ ha -theorem inv_pos_le_iff_one_le_mul (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ b * a := by - rw [inv_eq_one_div] - exact div_le_iff₀ ha +@[deprecated inv_le_iff_one_le_mul₀' (since := "2024-10-03")] +theorem inv_pos_le_iff_one_le_mul' (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ a * b := inv_le_iff_one_le_mul₀' ha -theorem inv_pos_le_iff_one_le_mul' (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ a * b := by - rw [inv_eq_one_div] - exact div_le_iff₀' ha +@[deprecated inv_lt_iff_one_lt_mul₀ (since := "2024-10-03")] +theorem inv_pos_lt_iff_one_lt_mul (ha : 0 < a) : a⁻¹ < b ↔ 1 < b * a := inv_lt_iff_one_lt_mul₀ ha -theorem inv_pos_lt_iff_one_lt_mul (ha : 0 < a) : a⁻¹ < b ↔ 1 < b * a := by - rw [inv_eq_one_div] - exact div_lt_iff ha - -theorem inv_pos_lt_iff_one_lt_mul' (ha : 0 < a) : a⁻¹ < b ↔ 1 < a * b := by - rw [inv_eq_one_div] - exact div_lt_iff' ha +@[deprecated inv_lt_iff_one_lt_mul₀' (since := "2024-10-03")] +theorem inv_pos_lt_iff_one_lt_mul' (ha : 0 < a) : a⁻¹ < b ↔ 1 < a * b := inv_lt_iff_one_lt_mul₀' ha /-- One direction of `div_le_iff` where `b` is allowed to be `0` (but `c` must be nonnegative) -/ -theorem div_le_of_nonneg_of_le_mul (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ c * b) : a / b ≤ c := by - rcases eq_or_lt_of_le hb with (rfl | hb') - · simp only [div_zero, hc] - · rwa [div_le_iff₀ hb'] +@[deprecated div_le_of_le_mul₀ (since := "2024-10-03")] +theorem div_le_of_nonneg_of_le_mul (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ c * b) : a / b ≤ c := + div_le_of_le_mul₀ hb hc h /-- One direction of `div_le_iff` where `c` is allowed to be `0` (but `b` must be nonnegative) -/ -lemma mul_le_of_nonneg_of_le_div (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ b / c) : a * c ≤ b := by - obtain rfl | hc := hc.eq_or_lt - · simpa using hb - · rwa [le_div_iff₀ hc] at h +@[deprecated mul_le_of_le_div₀ (since := "2024-10-03")] +lemma mul_le_of_nonneg_of_le_div (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ b / c) : a * c ≤ b := + mul_le_of_le_div₀ hb hc h -@[bound] -theorem div_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : a / b ≤ 1 := - div_le_of_nonneg_of_le_mul hb zero_le_one <| by rwa [one_mul] +@[deprecated div_le_one_of_le₀ (since := "2024-10-03")] +theorem div_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : a / b ≤ 1 := div_le_one_of_le₀ h hb -@[bound] -lemma mul_inv_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : a * b⁻¹ ≤ 1 := by - simpa only [← div_eq_mul_inv] using div_le_one_of_le h hb +@[deprecated mul_inv_le_one_of_le₀ (since := "2024-10-03")] +lemma mul_inv_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : a * b⁻¹ ≤ 1 := mul_inv_le_one_of_le₀ h hb -@[bound] -lemma inv_mul_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : b⁻¹ * a ≤ 1 := by - simpa only [← div_eq_inv_mul] using div_le_one_of_le h hb +@[deprecated inv_mul_le_one_of_le₀ (since := "2024-10-03")] +lemma inv_mul_le_one_of_le (h : a ≤ b) (hb : 0 ≤ b) : b⁻¹ * a ≤ 1 := inv_mul_le_one_of_le₀ h hb /-! ### Bi-implications of inequalities using inversions -/ -@[gcongr, bound] -theorem inv_le_inv_of_le (ha : 0 < a) (h : a ≤ b) : b⁻¹ ≤ a⁻¹ := by - rwa [← one_div a, le_div_iff₀' ha, ← div_eq_mul_inv, div_le_iff₀ (ha.trans_le h), one_mul] +@[deprecated inv_anti₀ (since := "2024-10-05")] +theorem inv_le_inv_of_le (ha : 0 < a) (h : a ≤ b) : b⁻¹ ≤ a⁻¹ := inv_anti₀ ha h /-- See `inv_le_inv_of_le` for the implication from right-to-left with one fewer assumption. -/ -theorem inv_le_inv (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b⁻¹ ↔ b ≤ a := by - rw [← one_div, div_le_iff₀ ha, ← div_eq_inv_mul, le_div_iff₀ hb, one_mul] +@[deprecated inv_le_inv₀ (since := "2024-10-05")] +theorem inv_le_inv (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b⁻¹ ↔ b ≤ a := inv_le_inv₀ ha hb /-- In a linear ordered field, for positive `a` and `b` we have `a⁻¹ ≤ b ↔ b⁻¹ ≤ a`. See also `inv_le_of_inv_le` for a one-sided implication with one fewer assumption. -/ -theorem inv_le (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b ↔ b⁻¹ ≤ a := by - rw [← inv_le_inv hb (inv_pos.2 ha), inv_inv] +@[deprecated inv_le_comm₀ (since := "2024-10-05")] +theorem inv_le (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b ↔ b⁻¹ ≤ a := inv_le_comm₀ ha hb -theorem inv_le_of_inv_le (ha : 0 < a) (h : a⁻¹ ≤ b) : b⁻¹ ≤ a := - (inv_le ha ((inv_pos.2 ha).trans_le h)).1 h +@[deprecated inv_le_of_inv_le₀ (since := "2024-10-05")] +theorem inv_le_of_inv_le (ha : 0 < a) (h : a⁻¹ ≤ b) : b⁻¹ ≤ a := inv_le_of_inv_le₀ ha h -theorem le_inv (ha : 0 < a) (hb : 0 < b) : a ≤ b⁻¹ ↔ b ≤ a⁻¹ := by - rw [← inv_le_inv (inv_pos.2 hb) ha, inv_inv] +@[deprecated le_inv_comm₀ (since := "2024-10-05")] +theorem le_inv (ha : 0 < a) (hb : 0 < b) : a ≤ b⁻¹ ↔ b ≤ a⁻¹ := le_inv_comm₀ ha hb /-- See `inv_lt_inv_of_lt` for the implication from right-to-left with one fewer assumption. -/ -theorem inv_lt_inv (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b⁻¹ ↔ b < a := - lt_iff_lt_of_le_iff_le (inv_le_inv hb ha) +@[deprecated inv_lt_inv₀ (since := "2024-10-05")] +theorem inv_lt_inv (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b⁻¹ ↔ b < a := inv_lt_inv₀ ha hb -@[gcongr] -theorem inv_lt_inv_of_lt (hb : 0 < b) (h : b < a) : a⁻¹ < b⁻¹ := - (inv_lt_inv (hb.trans h) hb).2 h +@[deprecated inv_strictAnti₀ (since := "2024-10-05")] +theorem inv_lt_inv_of_lt (hb : 0 < b) (h : b < a) : a⁻¹ < b⁻¹ := inv_strictAnti₀ hb h /-- In a linear ordered field, for positive `a` and `b` we have `a⁻¹ < b ↔ b⁻¹ < a`. See also `inv_lt_of_inv_lt` for a one-sided implication with one fewer assumption. -/ -theorem inv_lt (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b ↔ b⁻¹ < a := - lt_iff_lt_of_le_iff_le (le_inv hb ha) +@[deprecated inv_lt_comm₀ (since := "2024-10-05")] +theorem inv_lt (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b ↔ b⁻¹ < a := inv_lt_comm₀ ha hb -theorem inv_lt_of_inv_lt (ha : 0 < a) (h : a⁻¹ < b) : b⁻¹ < a := - (inv_lt ha ((inv_pos.2 ha).trans h)).1 h +@[deprecated inv_lt_of_inv_lt₀ (since := "2024-10-05")] +theorem inv_lt_of_inv_lt (ha : 0 < a) (h : a⁻¹ < b) : b⁻¹ < a := inv_lt_of_inv_lt₀ ha h -theorem lt_inv (ha : 0 < a) (hb : 0 < b) : a < b⁻¹ ↔ b < a⁻¹ := - lt_iff_lt_of_le_iff_le (inv_le hb ha) +@[deprecated lt_inv_comm₀ (since := "2024-10-05")] +theorem lt_inv (ha : 0 < a) (hb : 0 < b) : a < b⁻¹ ↔ b < a⁻¹ := lt_inv_comm₀ ha hb -theorem inv_lt_one (ha : 1 < a) : a⁻¹ < 1 := by - rwa [inv_lt (zero_lt_one.trans ha) zero_lt_one, inv_one] +@[deprecated inv_lt_one_of_one_lt₀ (since := "2024-10-05")] +theorem inv_lt_one (ha : 1 < a) : a⁻¹ < 1 := inv_lt_one_of_one_lt₀ ha -theorem one_lt_inv (h₁ : 0 < a) (h₂ : a < 1) : 1 < a⁻¹ := by - rwa [lt_inv (@zero_lt_one α _ _ _ _ _) h₁, inv_one] +@[deprecated one_lt_inv₀ (since := "2024-10-05")] +theorem one_lt_inv (h₁ : 0 < a) (h₂ : a < 1) : 1 < a⁻¹ := (one_lt_inv₀ h₁).2 h₂ -@[bound] -theorem inv_le_one (ha : 1 ≤ a) : a⁻¹ ≤ 1 := by - rwa [inv_le (zero_lt_one.trans_le ha) zero_lt_one, inv_one] +@[deprecated inv_le_one_of_one_le₀ (since := "2024-10-05")] +theorem inv_le_one (ha : 1 ≤ a) : a⁻¹ ≤ 1 := inv_le_one_of_one_le₀ ha -theorem one_le_inv (h₁ : 0 < a) (h₂ : a ≤ 1) : 1 ≤ a⁻¹ := by - rwa [le_inv (@zero_lt_one α _ _ _ _ _) h₁, inv_one] +@[deprecated one_le_inv₀ (since := "2024-10-05")] +theorem one_le_inv (h₁ : 0 < a) (h₂ : a ≤ 1) : 1 ≤ a⁻¹ := (one_le_inv₀ h₁).2 h₂ -theorem inv_lt_one_iff_of_pos (h₀ : 0 < a) : a⁻¹ < 1 ↔ 1 < a := - ⟨fun h₁ => inv_inv a ▸ one_lt_inv (inv_pos.2 h₀) h₁, inv_lt_one⟩ +@[deprecated inv_lt_one₀ (since := "2024-10-05")] +theorem inv_lt_one_iff_of_pos (h₀ : 0 < a) : a⁻¹ < 1 ↔ 1 < a := inv_lt_one₀ h₀ -theorem inv_lt_one_iff : a⁻¹ < 1 ↔ a ≤ 0 ∨ 1 < a := by - rcases le_or_lt a 0 with ha | ha - · simp [ha, (inv_nonpos.2 ha).trans_lt zero_lt_one] - · simp only [ha.not_le, false_or, inv_lt_one_iff_of_pos ha] +@[deprecated inv_lt_one_iff₀ (since := "2024-10-05")] +theorem inv_lt_one_iff : a⁻¹ < 1 ↔ a ≤ 0 ∨ 1 < a := inv_lt_one_iff₀ -theorem one_lt_inv_iff : 1 < a⁻¹ ↔ 0 < a ∧ a < 1 := - ⟨fun h => ⟨inv_pos.1 (zero_lt_one.trans h), - inv_inv a ▸ inv_lt_one h⟩, and_imp.2 one_lt_inv⟩ +@[deprecated one_lt_inv_iff₀ (since := "2024-10-05")] +theorem one_lt_inv_iff : 1 < a⁻¹ ↔ 0 < a ∧ a < 1 := one_lt_inv_iff₀ -theorem inv_le_one_iff : a⁻¹ ≤ 1 ↔ a ≤ 0 ∨ 1 ≤ a := by - rcases em (a = 1) with (rfl | ha) - · simp [le_rfl] - · simp only [Ne.le_iff_lt (Ne.symm ha), Ne.le_iff_lt (mt inv_eq_one.1 ha), inv_lt_one_iff] +@[deprecated inv_le_one_iff₀ (since := "2024-10-05")] +theorem inv_le_one_iff : a⁻¹ ≤ 1 ↔ a ≤ 0 ∨ 1 ≤ a := inv_le_one_iff₀ -theorem one_le_inv_iff : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 := - ⟨fun h => ⟨inv_pos.1 (zero_lt_one.trans_le h), - inv_inv a ▸ inv_le_one h⟩, and_imp.2 one_le_inv⟩ +@[deprecated one_le_inv_iff₀ (since := "2024-10-05")] +theorem one_le_inv_iff : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 := one_le_inv_iff₀ /-! ### Relating two divisions. @@ -208,11 +180,11 @@ lemma div_lt_div_of_pos_right (h : a < b) (hc : 0 < c) : a / c < b / c := by @[gcongr] lemma div_le_div_of_nonneg_left (ha : 0 ≤ a) (hc : 0 < c) (h : c ≤ b) : a / b ≤ a / c := by rw [div_eq_mul_inv, div_eq_mul_inv] - exact mul_le_mul_of_nonneg_left ((inv_le_inv (hc.trans_le h) hc).mpr h) ha + exact mul_le_mul_of_nonneg_left ((inv_le_inv₀ (hc.trans_le h) hc).mpr h) ha @[gcongr, bound] lemma div_lt_div_of_pos_left (ha : 0 < a) (hc : 0 < c) (h : c < b) : a / b < a / c := by - simpa only [div_eq_mul_inv, mul_lt_mul_left ha, inv_lt_inv (hc.trans h) hc] + simpa only [div_eq_mul_inv, mul_lt_mul_left ha, inv_lt_inv₀ (hc.trans h) hc] @[deprecated (since := "2024-02-16")] alias div_le_div_of_le_of_nonneg := div_le_div_of_nonneg_right @[deprecated (since := "2024-02-16")] alias div_lt_div_of_lt := div_lt_div_of_pos_right @@ -231,13 +203,13 @@ theorem div_lt_div_right (hc : 0 < c) : a / c < b / c ↔ a < b := lt_iff_lt_of_le_iff_le <| div_le_div_right hc theorem div_lt_div_left (ha : 0 < a) (hb : 0 < b) (hc : 0 < c) : a / b < a / c ↔ c < b := by - simp only [div_eq_mul_inv, mul_lt_mul_left ha, inv_lt_inv hb hc] + simp only [div_eq_mul_inv, mul_lt_mul_left ha, inv_lt_inv₀ hb hc] theorem div_le_div_left (ha : 0 < a) (hb : 0 < b) (hc : 0 < c) : a / b ≤ a / c ↔ c ≤ b := le_iff_le_iff_lt_iff_lt.2 (div_lt_div_left ha hc hb) theorem div_lt_div_iff (b0 : 0 < b) (d0 : 0 < d) : a / b < c / d ↔ a * d < c * b := by - rw [lt_div_iff d0, div_mul_eq_mul_div, div_lt_iff b0] + rw [lt_div_iff₀ d0, div_mul_eq_mul_div, div_lt_iff₀ b0] theorem div_le_div_iff (b0 : 0 < b) (d0 : 0 < d) : a / b ≤ c / d ↔ a * d ≤ c * b := by rw [le_div_iff₀ d0, div_mul_eq_mul_div, div_le_iff₀ b0] @@ -275,17 +247,21 @@ theorem one_le_div (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff theorem div_le_one (hb : 0 < b) : a / b ≤ 1 ↔ a ≤ b := by rw [div_le_iff₀ hb, one_mul] -theorem one_lt_div (hb : 0 < b) : 1 < a / b ↔ b < a := by rw [lt_div_iff hb, one_mul] +theorem one_lt_div (hb : 0 < b) : 1 < a / b ↔ b < a := by rw [lt_div_iff₀ hb, one_mul] -theorem div_lt_one (hb : 0 < b) : a / b < 1 ↔ a < b := by rw [div_lt_iff hb, one_mul] +theorem div_lt_one (hb : 0 < b) : a / b < 1 ↔ a < b := by rw [div_lt_iff₀ hb, one_mul] -theorem one_div_le (ha : 0 < a) (hb : 0 < b) : 1 / a ≤ b ↔ 1 / b ≤ a := by simpa using inv_le ha hb +theorem one_div_le (ha : 0 < a) (hb : 0 < b) : 1 / a ≤ b ↔ 1 / b ≤ a := by + simpa using inv_le_comm₀ ha hb -theorem one_div_lt (ha : 0 < a) (hb : 0 < b) : 1 / a < b ↔ 1 / b < a := by simpa using inv_lt ha hb +theorem one_div_lt (ha : 0 < a) (hb : 0 < b) : 1 / a < b ↔ 1 / b < a := by + simpa using inv_lt_comm₀ ha hb -theorem le_one_div (ha : 0 < a) (hb : 0 < b) : a ≤ 1 / b ↔ b ≤ 1 / a := by simpa using le_inv ha hb +theorem le_one_div (ha : 0 < a) (hb : 0 < b) : a ≤ 1 / b ↔ b ≤ 1 / a := by + simpa using le_inv_comm₀ ha hb -theorem lt_one_div (ha : 0 < a) (hb : 0 < b) : a < 1 / b ↔ b < 1 / a := by simpa using lt_inv ha hb +theorem lt_one_div (ha : 0 < a) (hb : 0 < b) : a < 1 / b ↔ b < 1 / a := by + simpa using lt_inv_comm₀ ha hb @[bound] lemma Bound.one_lt_div_of_pos_of_lt (b0 : 0 < b) : b < a → 1 < a / b := (one_lt_div b0).mpr @@ -297,10 +273,10 @@ theorem lt_one_div (ha : 0 < a) (hb : 0 < b) : a < 1 / b ↔ b < 1 / a := by sim theorem one_div_le_one_div_of_le (ha : 0 < a) (h : a ≤ b) : 1 / b ≤ 1 / a := by - simpa using inv_le_inv_of_le ha h + simpa using inv_anti₀ ha h theorem one_div_lt_one_div_of_lt (ha : 0 < a) (h : a < b) : 1 / b < 1 / a := by - rwa [lt_div_iff' ha, ← div_eq_mul_one_div, div_lt_one (ha.trans h)] + rwa [lt_div_iff₀' ha, ← div_eq_mul_one_div, div_lt_one (ha.trans h)] theorem le_of_one_div_le_one_div (ha : 0 < a) (h : 1 / a ≤ 1 / b) : b ≤ a := le_imp_le_of_lt_imp_lt (one_div_lt_one_div_of_lt ha) h @@ -341,7 +317,7 @@ theorem half_le_self_iff : a / 2 ≤ a ↔ 0 ≤ a := by @[simp] theorem half_lt_self_iff : a / 2 < a ↔ 0 < a := by - rw [div_lt_iff (zero_lt_two' α), mul_two, lt_add_iff_pos_left] + rw [div_lt_iff₀ (zero_lt_two' α), mul_two, lt_add_iff_pos_left] alias ⟨_, half_le_self⟩ := half_le_self_iff @@ -355,9 +331,9 @@ theorem one_half_lt_one : (1 / 2 : α) < 1 := theorem two_inv_lt_one : (2⁻¹ : α) < 1 := (one_div _).symm.trans_lt one_half_lt_one -theorem left_lt_add_div_two : a < (a + b) / 2 ↔ a < b := by simp [lt_div_iff, mul_two] +theorem left_lt_add_div_two : a < (a + b) / 2 ↔ a < b := by simp [lt_div_iff₀, mul_two] -theorem add_div_two_lt_right : (a + b) / 2 < b ↔ a < b := by simp [div_lt_iff, mul_two] +theorem add_div_two_lt_right : (a + b) / 2 < b ↔ a < b := by simp [div_lt_iff₀, mul_two] theorem add_thirds (a : α) : a / 3 + a / 3 + a / 3 = a := by rw [div_add_div_same, div_add_div_same, ← two_mul, ← add_one_mul 2 a, two_add_one_eq_three, @@ -385,12 +361,12 @@ theorem div_mul_le_div_mul_of_div_le_div (h : a / b ≤ c / d) (he : 0 ≤ e) : theorem exists_pos_mul_lt {a : α} (h : 0 < a) (b : α) : ∃ c : α, 0 < c ∧ b * c < a := by have : 0 < a / max (b + 1) 1 := div_pos h (lt_max_iff.2 (Or.inr zero_lt_one)) refine ⟨a / max (b + 1) 1, this, ?_⟩ - rw [← lt_div_iff this, div_div_cancel' h.ne'] + rw [← lt_div_iff₀ this, div_div_cancel' h.ne'] exact lt_max_iff.2 (Or.inl <| lt_add_one _) theorem exists_pos_lt_mul {a : α} (h : 0 < a) (b : α) : ∃ c : α, 0 < c ∧ b < c * a := let ⟨c, hc₀, hc⟩ := exists_pos_mul_lt h b; - ⟨c⁻¹, inv_pos.2 hc₀, by rwa [← div_eq_inv_mul, lt_div_iff hc₀]⟩ + ⟨c⁻¹, inv_pos.2 hc₀, by rwa [← div_eq_inv_mul, lt_div_iff₀ hc₀]⟩ lemma monotone_div_right_of_nonneg (ha : 0 ≤ a) : Monotone (· / a) := fun _b _c hbc ↦ div_le_div_of_nonneg_right hbc ha @@ -429,7 +405,7 @@ theorem one_div_strictAntiOn : StrictAntiOn (fun x : α => 1 / x) (Set.Ioi 0) := theorem one_div_pow_le_one_div_pow_of_le (a1 : 1 ≤ a) {m n : ℕ} (mn : m ≤ n) : 1 / a ^ n ≤ 1 / a ^ m := by - refine (one_div_le_one_div ?_ ?_).mpr (pow_le_pow_right a1 mn) <;> + refine (one_div_le_one_div ?_ ?_).mpr (pow_right_mono₀ a1 mn) <;> exact pow_pos (zero_lt_one.trans_le a1) _ theorem one_div_pow_lt_one_div_pow_of_lt (a1 : 1 < a) {m n : ℕ} (mn : m < n) : @@ -444,7 +420,7 @@ theorem one_div_pow_strictAnti (a1 : 1 < a) : StrictAnti fun n : ℕ => 1 / a ^ one_div_pow_lt_one_div_pow_of_lt a1 theorem inv_strictAntiOn : StrictAntiOn (fun x : α => x⁻¹) (Set.Ioi 0) := fun _ hx _ hy xy => - (inv_lt_inv hy hx).2 xy + (inv_lt_inv₀ hy hx).2 xy theorem inv_pow_le_inv_pow_of_le (a1 : 1 ≤ a) {m n : ℕ} (mn : m ≤ n) : (a ^ n)⁻¹ ≤ (a ^ m)⁻¹ := by convert one_div_pow_le_one_div_pow_of_le a1 mn using 1 <;> simp @@ -538,7 +514,7 @@ theorem lt_div_iff_of_neg' (hc : c < 0) : a < b / c ↔ b < c * a := by rw [mul_comm, lt_div_iff_of_neg hc] theorem div_le_one_of_ge (h : b ≤ a) (hb : b ≤ 0) : a / b ≤ 1 := by - simpa only [neg_div_neg_eq] using div_le_one_of_le (neg_le_neg h) (neg_nonneg_of_nonpos hb) + simpa only [neg_div_neg_eq] using div_le_one_of_le₀ (neg_le_neg h) (neg_nonneg_of_nonpos hb) /-! ### Bi-implications of inequalities using inversions -/ @@ -569,7 +545,7 @@ theorem lt_inv_of_neg (ha : a < 0) (hb : b < 0) : a < b⁻¹ ↔ b < a⁻¹ := theorem sub_inv_antitoneOn_Ioi : AntitoneOn (fun x ↦ (x-c)⁻¹) (Set.Ioi c) := antitoneOn_iff_forall_lt.mpr fun _ ha _ hb hab ↦ - inv_le_inv (sub_pos.mpr hb) (sub_pos.mpr ha) |>.mpr <| sub_le_sub (le_of_lt hab) le_rfl + inv_le_inv₀ (sub_pos.mpr hb) (sub_pos.mpr ha) |>.mpr <| sub_le_sub (le_of_lt hab) le_rfl theorem sub_inv_antitoneOn_Iio : AntitoneOn (fun x ↦ (x-c)⁻¹) (Set.Iio c) := @@ -723,11 +699,11 @@ theorem add_sub_div_two_lt (h : a < b) : a + (b - a) / 2 < b := by /-- An inequality involving `2`. -/ theorem sub_one_div_inv_le_two (a2 : 2 ≤ a) : (1 - 1 / a)⁻¹ ≤ 2 := by -- Take inverses on both sides to obtain `2⁻¹ ≤ 1 - 1 / a` - refine (inv_le_inv_of_le (inv_pos.2 <| zero_lt_two' α) ?_).trans_eq (inv_inv (2 : α)) + refine (inv_anti₀ (inv_pos.2 <| zero_lt_two' α) ?_).trans_eq (inv_inv (2 : α)) -- move `1 / a` to the left and `2⁻¹` to the right. rw [le_sub_iff_add_le, add_comm, ← le_sub_iff_add_le] -- take inverses on both sides and use the assumption `2 ≤ a`. - convert (one_div a).le.trans (inv_le_inv_of_le zero_lt_two a2) using 1 + convert (one_div a).le.trans (inv_anti₀ zero_lt_two a2) using 1 -- show `1 - 1 / 2 = 1 / 2`. rw [sub_eq_iff_eq_add, ← two_mul, mul_inv_cancel₀ two_ne_zero] diff --git a/Mathlib/Algebra/Order/Field/Defs.lean b/Mathlib/Algebra/Order/Field/Defs.lean index ad7ae9d36bb7a..86284a304dde6 100644 --- a/Mathlib/Algebra/Order/Field/Defs.lean +++ b/Mathlib/Algebra/Order/Field/Defs.lean @@ -36,7 +36,7 @@ instance (priority := 100) LinearOrderedField.toLinearOrderedSemifield [LinearOr LinearOrderedSemifield α := { LinearOrderedRing.toLinearOrderedSemiring, ‹LinearOrderedField α› with } -variable [LinearOrderedSemifield α] {a b : α} +variable [LinearOrderedSemifield α] {a b c : α} /-- Equality holds when `a ≠ 0`. See `mul_inv_cancel`. -/ lemma mul_inv_le_one : a * a⁻¹ ≤ 1 := by obtain rfl | ha := eq_or_ne a 0 <;> simp [*] @@ -75,3 +75,27 @@ lemma inv_mul_right_le (ha : 0 ≤ a) : a * b⁻¹ * b ≤ a := by /-- Equality holds when `b ≠ 0`. See `inv_mul_cancel_right`. -/ lemma le_inv_mul_right (ha : a ≤ 0) : a ≤ a * b⁻¹ * b := by obtain rfl | hb := eq_or_ne b 0 <;> simp [*] + +/-- Equality holds when `c ≠ 0`. See `mul_div_mul_left`. -/ +lemma mul_div_mul_left_le (h : 0 ≤ a / b) : c * a / (c * b) ≤ a / b := by + obtain rfl | hc := eq_or_ne c 0 + · simpa + · rw [mul_div_mul_left _ _ hc] + +/-- Equality holds when `c ≠ 0`. See `mul_div_mul_left`. -/ +lemma le_mul_div_mul_left (h : a / b ≤ 0) : a / b ≤ c * a / (c * b) := by + obtain rfl | hc := eq_or_ne c 0 + · simpa + · rw [mul_div_mul_left _ _ hc] + +/-- Equality holds when `c ≠ 0`. See `mul_div_mul_right`. -/ +lemma mul_div_mul_right_le (h : 0 ≤ a / b) : a * c / (b * c) ≤ a / b := by + obtain rfl | hc := eq_or_ne c 0 + · simpa + · rw [mul_div_mul_right _ _ hc] + +/-- Equality holds when `c ≠ 0`. See `mul_div_mul_right`. -/ +lemma le_mul_div_mul_right (h : a / b ≤ 0) : a / b ≤ a * c / (b * c) := by + obtain rfl | hc := eq_or_ne c 0 + · simpa + · rw [mul_div_mul_right _ _ hc] diff --git a/Mathlib/Algebra/Order/Field/Pointwise.lean b/Mathlib/Algebra/Order/Field/Pointwise.lean new file mode 100644 index 0000000000000..01d4453c22523 --- /dev/null +++ b/Mathlib/Algebra/Order/Field/Pointwise.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2021 Alex J. Best. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Alex J. Best, Yaël Dillies +-/ +import Mathlib.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Order.Field.Defs +import Mathlib.Algebra.SMulWithZero + +/-! +# Pointwise operations on ordered algebraic objects + +This file contains lemmas about the effect of pointwise operations on sets with an order structure. +-/ + +open Function Set +open scoped Pointwise + +variable {α : Type*} + +namespace LinearOrderedField + +variable {K : Type*} [LinearOrderedField K] {a b r : K} (hr : 0 < r) +include hr + +theorem smul_Ioo : r • Ioo a b = Ioo (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioo] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_lt_mul_left hr).mpr a_h_left_left + · exact (mul_lt_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(lt_div_iff₀' hr).mpr a_left, (div_lt_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Icc : r • Icc a b = Icc (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Icc] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_le_mul_left hr).mpr a_h_left_left + · exact (mul_le_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ico : r • Ico a b = Ico (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ico] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_le_mul_left hr).mpr a_h_left_left + · exact (mul_lt_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_lt_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ioc : r • Ioc a b = Ioc (r • a) (r • b) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioc] + constructor + · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ + constructor + · exact (mul_lt_mul_left hr).mpr a_h_left_left + · exact (mul_le_mul_left hr).mpr a_h_left_right + · rintro ⟨a_left, a_right⟩ + use x / r + refine ⟨⟨(lt_div_iff₀' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ + rw [mul_div_cancel₀ _ (ne_of_gt hr)] + +theorem smul_Ioi : r • Ioi a = Ioi (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioi] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_lt_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (lt_div_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Iio : r • Iio a = Iio (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Iio] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_lt_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (div_lt_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Ici : r • Ici a = Ici (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Ioi] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_le_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (le_div_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +theorem smul_Iic : r • Iic a = Iic (r • a) := by + ext x + simp only [mem_smul_set, smul_eq_mul, mem_Iio] + constructor + · rintro ⟨a_w, a_h_left, rfl⟩ + exact (mul_le_mul_left hr).mpr a_h_left + · rintro h + use x / r + constructor + · exact (div_le_iff₀' hr).mpr h + · exact mul_div_cancel₀ _ (ne_of_gt hr) + +end LinearOrderedField diff --git a/Mathlib/Algebra/Order/Field/Power.lean b/Mathlib/Algebra/Order/Field/Power.lean index 8dfd3676717c3..67ff27a9c705f 100644 --- a/Mathlib/Algebra/Order/Field/Power.lean +++ b/Mathlib/Algebra/Order/Field/Power.lean @@ -24,80 +24,68 @@ variable [LinearOrderedSemifield α] {a b c d e : α} {m n : ℤ} /-! ### Integer powers -/ -@[gcongr] -theorem zpow_le_of_le (ha : 1 ≤ a) (h : m ≤ n) : a ^ m ≤ a ^ n := by - have ha₀ : 0 < a := one_pos.trans_le ha - lift n - m to ℕ using sub_nonneg.2 h with k hk - calc - a ^ m = a ^ m * 1 := (mul_one _).symm - _ ≤ a ^ m * a ^ k := - mul_le_mul_of_nonneg_left (one_le_pow_of_one_le ha _) (zpow_nonneg ha₀.le _) - _ = a ^ n := by rw [← zpow_natCast, ← zpow_add₀ ha₀.ne', hk, add_sub_cancel] +@[deprecated zpow_le_zpow_right₀ (since := "2024-10-08")] +theorem zpow_le_of_le (ha : 1 ≤ a) (h : m ≤ n) : a ^ m ≤ a ^ n := zpow_le_zpow_right₀ ha h +@[deprecated zpow_le_one_of_nonpos₀ (since := "2024-10-08")] theorem zpow_le_one_of_nonpos (ha : 1 ≤ a) (hn : n ≤ 0) : a ^ n ≤ 1 := - (zpow_le_of_le ha hn).trans_eq <| zpow_zero _ + zpow_le_one_of_nonpos₀ ha hn +@[deprecated one_le_zpow₀ (since := "2024-10-08")] theorem one_le_zpow_of_nonneg (ha : 1 ≤ a) (hn : 0 ≤ n) : 1 ≤ a ^ n := - (zpow_zero _).symm.trans_le <| zpow_le_of_le ha hn + one_le_zpow₀ ha hn -protected theorem Nat.zpow_pos_of_pos {a : ℕ} (h : 0 < a) (n : ℤ) : 0 < (a : α) ^ n := by - apply zpow_pos_of_pos - exact mod_cast h +@[deprecated zpow_pos (since := "2024-10-08")] +protected theorem Nat.zpow_pos_of_pos {a : ℕ} (h : 0 < a) (n : ℤ) : 0 < (a : α) ^ n := + zpow_pos (mod_cast h) _ +@[deprecated zpow_ne_zero (since := "2024-10-08")] theorem Nat.zpow_ne_zero_of_pos {a : ℕ} (h : 0 < a) (n : ℤ) : (a : α) ^ n ≠ 0 := - (Nat.zpow_pos_of_pos h n).ne' + zpow_ne_zero _ (mod_cast h.ne') -theorem one_lt_zpow (ha : 1 < a) : ∀ n : ℤ, 0 < n → 1 < a ^ n - | (n : ℕ), h => (zpow_natCast _ _).symm.subst (one_lt_pow ha <| Int.natCast_ne_zero.mp h.ne') - | -[_+1], h => ((Int.negSucc_not_pos _).mp h).elim +@[deprecated one_lt_zpow₀ (since := "2024-10-08")] +theorem one_lt_zpow (ha : 1 < a) (n : ℤ) (hn : 0 < n) : 1 < a ^ n := one_lt_zpow₀ ha hn +@[deprecated zpow_right_strictMono₀ (since := "2024-10-08")] theorem zpow_strictMono (hx : 1 < a) : StrictMono (a ^ · : ℤ → α) := - strictMono_int_of_lt_succ fun n => - have xpos : 0 < a := zero_lt_one.trans hx - calc - a ^ n < a ^ n * a := lt_mul_of_one_lt_right (zpow_pos_of_pos xpos _) hx - _ = a ^ (n + 1) := (zpow_add_one₀ xpos.ne' _).symm + zpow_right_strictMono₀ hx +@[deprecated zpow_right_strictAnti₀ (since := "2024-10-08")] theorem zpow_strictAnti (h₀ : 0 < a) (h₁ : a < 1) : StrictAnti (a ^ · : ℤ → α) := - strictAnti_int_of_succ_lt fun n => - calc - a ^ (n + 1) = a ^ n * a := zpow_add_one₀ h₀.ne' _ - _ < a ^ n * 1 := (mul_lt_mul_left <| zpow_pos_of_pos h₀ _).2 h₁ - _ = a ^ n := mul_one _ + zpow_right_strictAnti₀ h₀ h₁ -@[simp] +@[deprecated zpow_lt_zpow_iff_right₀ (since := "2024-10-08")] theorem zpow_lt_iff_lt (hx : 1 < a) : a ^ m < a ^ n ↔ m < n := - (zpow_strictMono hx).lt_iff_lt + zpow_lt_zpow_iff_right₀ hx -@[gcongr] alias ⟨_, GCongr.zpow_lt_of_lt⟩ := zpow_lt_iff_lt +@[deprecated (since := "2024-02-10")] alias ⟨_, zpow_lt_of_lt⟩ := zpow_lt_iff_lt -@[deprecated (since := "2024-02-10")] alias zpow_lt_of_lt := GCongr.zpow_lt_of_lt - -@[simp] +@[deprecated zpow_le_zpow_iff_right₀ (since := "2024-10-08")] theorem zpow_le_iff_le (hx : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := - (zpow_strictMono hx).le_iff_le + zpow_le_zpow_iff_right₀ hx -@[simp] +@[deprecated div_le_self (since := "2024-10-08")] theorem div_pow_le (ha : 0 ≤ a) (hb : 1 ≤ b) (k : ℕ) : a / b ^ k ≤ a := - div_le_self ha <| one_le_pow_of_one_le hb _ + div_le_self ha <| one_le_pow₀ hb -theorem zpow_injective (h₀ : 0 < a) (h₁ : a ≠ 1) : Injective (a ^ · : ℤ → α) := by - rcases h₁.lt_or_lt with (H | H) - · exact (zpow_strictAnti h₀ H).injective - · exact (zpow_strictMono H).injective +@[deprecated zpow_right_injective₀ (since := "2024-10-08")] +theorem zpow_injective (h₀ : 0 < a) (h₁ : a ≠ 1) : Injective (a ^ · : ℤ → α) := + zpow_right_injective₀ h₀ h₁ -@[simp] +@[deprecated zpow_right_inj₀ (since := "2024-10-08")] theorem zpow_inj (h₀ : 0 < a) (h₁ : a ≠ 1) : a ^ m = a ^ n ↔ m = n := - (zpow_injective h₀ h₁).eq_iff + zpow_right_inj₀ h₀ h₁ +@[deprecated (since := "2024-10-08")] theorem zpow_le_max_of_min_le {x : α} (hx : 1 ≤ x) {a b c : ℤ} (h : min a b ≤ c) : x ^ (-c) ≤ max (x ^ (-a)) (x ^ (-b)) := - have : Antitone fun n : ℤ => x ^ (-n) := fun _ _ h => zpow_le_of_le hx (neg_le_neg h) + have : Antitone fun n : ℤ => x ^ (-n) := fun _ _ h => zpow_le_zpow_right₀ hx (neg_le_neg h) (this h).trans_eq this.map_min +@[deprecated (since := "2024-10-08")] theorem zpow_le_max_iff_min_le {x : α} (hx : 1 < x) {a b c : ℤ} : x ^ (-c) ≤ max (x ^ (-a)) (x ^ (-b)) ↔ min a b ≤ c := by - simp_rw [le_max_iff, min_le_iff, zpow_le_iff_le hx, neg_le_neg_iff] + simp_rw [le_max_iff, min_le_iff, zpow_le_zpow_iff_right₀ hx, neg_le_neg_iff] end LinearOrderedSemifield @@ -205,7 +193,7 @@ def evalZPow : PositivityExt where eval {u α} zα pα e := do let _a ← synthInstanceQ (q(LinearOrderedSemifield $α) : Q(Type u)) haveI' : $e =Q $a ^ $b := ⟨⟩ assumeInstancesCommute - pure (.positive q(zpow_pos_of_pos $pa $b)) + pure (.positive q(zpow_pos $pa $b)) catch e : Exception => trace[Tactic.positivity.failure] "{e.toMessageData}" let oα ← synthInstanceQ q(LinearOrderedSemifield $α) diff --git a/Mathlib/Algebra/Order/Floor.lean b/Mathlib/Algebra/Order/Floor.lean index 7d9f071cca4ea..09bdb68063e38 100644 --- a/Mathlib/Algebra/Order/Floor.lean +++ b/Mathlib/Algebra/Order/Floor.lean @@ -484,7 +484,7 @@ theorem floor_div_nat (a : α) (n : ℕ) : ⌊a / n⌋₊ = ⌊a⌋₊ / n := by · exact div_nonneg ha n.cast_nonneg constructor · exact cast_div_le.trans (div_le_div_of_nonneg_right (floor_le ha) n.cast_nonneg) - rw [div_lt_iff, add_mul, one_mul, ← cast_mul, ← cast_add, ← floor_lt ha] + rw [div_lt_iff₀, add_mul, one_mul, ← cast_mul, ← cast_add, ← floor_lt ha] · exact lt_div_mul_add hn · exact cast_pos.2 hn @@ -515,7 +515,7 @@ lemma ceil_lt_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉₊ / b < a) : ⌈a⌉ obtain hab | hba := le_total a (b - 1)⁻¹ · calc ⌈a⌉₊ ≤ (⌈(b - 1)⁻¹⌉₊ : α) := by gcongr - _ < b * a := by rwa [← div_lt_iff']; positivity + _ < b * a := by rwa [← div_lt_iff₀']; positivity · rw [← sub_pos] at hb calc ⌈a⌉₊ < a + 1 := ceil_lt_add_one <| hba.trans' <| by positivity @@ -526,7 +526,7 @@ lemma ceil_lt_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉₊ / b < a) : ⌈a⌉ lemma ceil_le_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉₊ / b ≤ a) : ⌈a⌉₊ ≤ b * a := by obtain rfl | hba := hba.eq_or_lt · rw [mul_div_cancel₀, cast_le, ceil_le] - exact _root_.div_le_self (by positivity) hb.le + · exact _root_.div_le_self (by positivity) hb.le · positivity · exact (ceil_lt_mul hb hba).le @@ -1027,7 +1027,7 @@ theorem sub_floor_div_mul_nonneg (a : k) (hb : 0 < b) : 0 ≤ a - ⌊a / b⌋ * theorem sub_floor_div_mul_lt (a : k) (hb : 0 < b) : a - ⌊a / b⌋ * b < b := sub_lt_iff_lt_add.2 <| by -- Porting note: `← one_add_mul` worked in mathlib3 without the argument - rw [← one_add_mul _ b, ← div_lt_iff hb, add_comm] + rw [← one_add_mul _ b, ← div_lt_iff₀ hb, add_comm] exact lt_floor_add_one _ theorem fract_div_natCast_eq_div_natCast_mod {m n : ℕ} : fract ((m : k) / n) = ↑(m % n) / n := by @@ -1054,7 +1054,7 @@ theorem fract_div_intCast_eq_div_intCast_mod {m : ℤ} {n : ℕ} : obtain ⟨l₀, rfl | rfl⟩ := l.eq_nat_or_neg · rw [cast_natCast, ← natCast_mod, cast_natCast, fract_div_natCast_eq_div_natCast_mod] · rw [Right.nonneg_neg_iff, natCast_nonpos_iff] at hl - simp [hl, zero_mod] + simp [hl] obtain ⟨m₀, rfl | rfl⟩ := m.eq_nat_or_neg · exact this (ofNat_nonneg m₀) let q := ⌈↑m₀ / (n : k)⌉ @@ -1261,7 +1261,7 @@ lemma ceil_div_ceil_inv_sub_one (ha : 1 ≤ a) : ⌈⌈(a - 1)⁻¹⌉ / a⌉ = have : 0 < ⌈(a - 1)⁻¹⌉ := ceil_pos.2 <| by positivity refine le_antisymm (ceil_le.2 <| div_le_self (by positivity) ha.le) <| ?_ rw [le_ceil_iff, sub_lt_comm, div_eq_mul_inv, ← mul_one_sub, - ← lt_div_iff (sub_pos.2 <| inv_lt_one ha)] + ← lt_div_iff₀ (sub_pos.2 <| inv_lt_one_of_one_lt₀ ha)] convert ceil_lt_add_one _ using 1 field_simp @@ -1269,7 +1269,7 @@ lemma ceil_lt_mul (hb : 1 < b) (hba : ⌈(b - 1)⁻¹⌉ / b < a) : ⌈a⌉ < b obtain hab | hba := le_total a (b - 1)⁻¹ · calc ⌈a⌉ ≤ (⌈(b - 1)⁻¹⌉ : k) := by gcongr - _ < b * a := by rwa [← div_lt_iff']; positivity + _ < b * a := by rwa [← div_lt_iff₀']; positivity · rw [← sub_pos] at hb calc ⌈a⌉ < a + 1 := ceil_lt_add_one _ @@ -1453,7 +1453,7 @@ section LinearOrderedField variable [LinearOrderedField α] [FloorRing α] theorem round_eq (x : α) : round x = ⌊x + 1 / 2⌋ := by - simp_rw [round, (by simp only [lt_div_iff', two_pos] : 2 * fract x < 1 ↔ fract x < 1 / 2)] + simp_rw [round, (by simp only [lt_div_iff₀', two_pos] : 2 * fract x < 1 ↔ fract x < 1 / 2)] cases' lt_or_le (fract x) (1 / 2) with hx hx · conv_rhs => rw [← fract_add_floor x, add_assoc, add_left_comm, floor_int_add] rw [if_pos hx, self_eq_add_right, floor_eq_iff, cast_zero, zero_add] @@ -1694,4 +1694,4 @@ def evalIntCeil : PositivityExt where eval {u α} _zα _pα e := do end Mathlib.Meta.Positivity -set_option linter.style.longFile 1700 +set_option linter.style.longFile 1800 diff --git a/Mathlib/Algebra/Order/Floor/Div.lean b/Mathlib/Algebra/Order/Floor/Div.lean index 35d76dbf57197..20b853e6e5f94 100644 --- a/Mathlib/Algebra/Order/Floor/Div.lean +++ b/Mathlib/Algebra/Order/Floor/Div.lean @@ -119,7 +119,7 @@ end OrderedAddCommMonoid section LinearOrderedAddCommMonoid variable [LinearOrderedAddCommMonoid α] [OrderedAddCommMonoid β] [SMulZeroClass α β] - [PosSMulReflectLE α β] [FloorDiv α β] [CeilDiv α β] {a : α} {b c : β} + [PosSMulReflectLE α β] [FloorDiv α β] [CeilDiv α β] {a : α} {b : β} lemma floorDiv_le_ceilDiv : b ⌊/⌋ a ≤ b ⌈/⌉ a := by obtain ha | ha := le_or_lt a 0 diff --git a/Mathlib/Algebra/Order/Floor/Prime.lean b/Mathlib/Algebra/Order/Floor/Prime.lean index 6c418d3d3d34b..f3545648ae511 100644 --- a/Mathlib/Algebra/Order/Floor/Prime.lean +++ b/Mathlib/Algebra/Order/Floor/Prime.lean @@ -3,40 +3,44 @@ Copyright (c) 2022 Yuyang Zhao. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yuyang Zhao -/ - -import Mathlib.Algebra.Order.Floor import Mathlib.Data.Nat.Prime.Basic +import Mathlib.Topology.Algebra.Order.Floor /-! # Existence of a sufficiently large prime for which `a * c ^ p / (p - 1)! < 1` This is a technical result used in the proof of the Lindemann-Weierstrass theorem. --/ -namespace FloorRing +TODO: delete this file, as all its lemmas have been deprecated. +-/ open scoped Nat +@[deprecated eventually_mul_pow_lt_factorial_sub (since := "2024-09-25")] +theorem Nat.exists_prime_mul_pow_lt_factorial (n a c : ℕ) : + ∃ p > n, p.Prime ∧ a * c ^ p < (p - 1)! := + ((Filter.frequently_atTop.mpr Nat.exists_infinite_primes).and_eventually + (eventually_mul_pow_lt_factorial_sub a c 1)).forall_exists_of_atTop (n + 1) + +namespace FloorRing + variable {K : Type*} +@[deprecated FloorSemiring.eventually_mul_pow_lt_factorial_sub (since := "2024-09-25")] theorem exists_prime_mul_pow_lt_factorial [LinearOrderedRing K] [FloorRing K] (n : ℕ) (a c : K) : - ∃ p > n, p.Prime ∧ a * c ^ p < (p - 1)! := by - obtain ⟨p, pn, pp, h⟩ := n.exists_prime_mul_pow_lt_factorial ⌈|a|⌉.natAbs ⌈|c|⌉.natAbs - use p, pn, pp - calc a * c ^ p - _ ≤ |a * c ^ p| := le_abs_self _ - _ ≤ ⌈|a|⌉ * (⌈|c|⌉ : K) ^ p := ?_ - _ = ↑(Int.natAbs ⌈|a|⌉ * Int.natAbs ⌈|c|⌉ ^ p) := ?_ - _ < ↑(p - 1)! := Nat.cast_lt.mpr h - · rw [abs_mul, abs_pow] - gcongr <;> try first | positivity | apply Int.le_ceil - · simp_rw [Nat.cast_mul, Nat.cast_pow, Int.cast_natAbs, - abs_eq_self.mpr (Int.ceil_nonneg (abs_nonneg (_ : K)))] + ∃ p > n, p.Prime ∧ a * c ^ p < (p - 1)! := + ((Filter.frequently_atTop.mpr Nat.exists_infinite_primes).and_eventually + (FloorSemiring.eventually_mul_pow_lt_factorial_sub a c 1)).forall_exists_of_atTop (n + 1) +@[deprecated FloorSemiring.tendsto_mul_pow_div_factorial_sub_atTop (since := "2024-09-25")] theorem exists_prime_mul_pow_div_factorial_lt_one [LinearOrderedField K] [FloorRing K] (n : ℕ) (a c : K) : - ∃ p > n, p.Prime ∧ a * c ^ p / (p - 1)! < 1 := by - simp_rw [div_lt_one (α := K) (Nat.cast_pos.mpr (Nat.factorial_pos _))] - exact exists_prime_mul_pow_lt_factorial .. + ∃ p > n, p.Prime ∧ a * c ^ p / (p - 1)! < 1 := + letI := Preorder.topology K + haveI : OrderTopology K := ⟨rfl⟩ + ((Filter.frequently_atTop.mpr Nat.exists_infinite_primes).and_eventually + (eventually_lt_of_tendsto_lt zero_lt_one + (FloorSemiring.tendsto_mul_pow_div_factorial_sub_atTop a c 1))).forall_exists_of_atTop + (n + 1) end FloorRing diff --git a/Mathlib/Algebra/Order/Group/Abs.lean b/Mathlib/Algebra/Order/Group/Abs.lean index 3d6763c037cfa..9693c189cfb6c 100644 --- a/Mathlib/Algebra/Order/Group/Abs.lean +++ b/Mathlib/Algebra/Order/Group/Abs.lean @@ -94,7 +94,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 _) ((@neg_le α ..).2 <| neg_le_abs _), + add_le_add (neg_le.2 <| neg_le_abs _) (neg_le.2 <| neg_le_abs _), add_le_add (le_abs_self _) (le_abs_self _)⟩ theorem abs_add' (a b : α) : |a| ≤ |b| + |b + a| := by simpa using abs_add (-b) (b + a) @@ -122,7 +122,7 @@ theorem sub_lt_of_abs_sub_lt_right (h : |a - b| < c) : a - c < b := sub_lt_of_abs_sub_lt_left (abs_sub_comm a b ▸ h) theorem abs_sub_abs_le_abs_sub (a b : α) : |a| - |b| ≤ |a - b| := - (@sub_le_iff_le_add α ..).2 <| + sub_le_iff_le_add.2 <| calc |a| = |a - b + b| := by rw [sub_add_cancel] _ ≤ |a - b| + |b| := abs_add _ _ diff --git a/Mathlib/Algebra/Order/Group/CompleteLattice.lean b/Mathlib/Algebra/Order/Group/CompleteLattice.lean new file mode 100644 index 0000000000000..19c8f5fda8e68 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/CompleteLattice.lean @@ -0,0 +1,49 @@ +/- +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.Algebra.Order.Group.OrderIso +import Mathlib.Order.ConditionallyCompleteLattice.Basic + +/-! +# Distributivity of group operations over supremum/infimum +-/ + +open Function Set + +variable {ι G : Type*} [Group G] [ConditionallyCompleteLattice G] [Nonempty ι] {f : ι → G} + +section Right +variable [CovariantClass G G (swap (· * ·)) (· ≤ ·)] + +@[to_additive] +lemma ciSup_mul (hf : BddAbove (range f)) (a : G) : (⨆ i, f i) * a = ⨆ i, f i * a := + (OrderIso.mulRight a).map_ciSup hf + +@[to_additive] +lemma 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] + +@[to_additive] +lemma ciInf_mul (hf : BddBelow (range f)) (a : G) : (⨅ i, f i) * a = ⨅ i, f i * a := + (OrderIso.mulRight a).map_ciInf hf + +@[to_additive] +lemma 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 + +section Left +variable [CovariantClass G G (· * ·) (· ≤ ·)] + +@[to_additive] +lemma mul_ciSup (hf : BddAbove (range f)) (a : G) : (a * ⨆ i, f i) = ⨆ i, a * f i := + (OrderIso.mulLeft a).map_ciSup hf + +@[to_additive] +lemma 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/Order/Group/Cone.lean b/Mathlib/Algebra/Order/Group/Cone.lean index a49307108ac8e..6d794594f08df 100644 --- a/Mathlib/Algebra/Order/Group/Cone.lean +++ b/Mathlib/Algebra/Order/Group/Cone.lean @@ -18,13 +18,13 @@ cones in groups and the corresponding ordered groups. -/ /-- `AddGroupConeClass S G` says that `S` is a type of cones in `G`. -/ -class AddGroupConeClass (S G : Type*) [AddCommGroup G] [SetLike S G] extends - AddSubmonoidClass S G : Prop where +class AddGroupConeClass (S : Type*) (G : outParam Type*) [AddCommGroup G] [SetLike S G] + extends AddSubmonoidClass S G : Prop where eq_zero_of_mem_of_neg_mem {C : S} {a : G} : a ∈ C → -a ∈ C → a = 0 /-- `GroupConeClass S G` says that `S` is a type of cones in `G`. -/ @[to_additive] -class GroupConeClass (S G : Type*) [CommGroup G] [SetLike S G] extends +class GroupConeClass (S : Type*) (G : outParam Type*) [CommGroup G] [SetLike S G] extends SubmonoidClass S G : Prop where eq_one_of_mem_of_inv_mem {C : S} {a : G} : a ∈ C → a⁻¹ ∈ C → a = 1 diff --git a/Mathlib/Algebra/Order/Group/Defs.lean b/Mathlib/Algebra/Order/Group/Defs.lean index a47229cb3489f..53b53337c45d3 100644 --- a/Mathlib/Algebra/Order/Group/Defs.lean +++ b/Mathlib/Algebra/Order/Group/Defs.lean @@ -21,9 +21,9 @@ The reason is that we did not want to change existing names in the library. -/ /- -`NeZero` should not be needed at this point in the ordered algebraic hierarchy. +`NeZero` theory should not be needed at this point in the ordered algebraic hierarchy. -/ -assert_not_exists NeZero +assert_not_imported Mathlib.Algebra.NeZero open Function @@ -175,13 +175,11 @@ variable [OrderedCommGroup α] {a b : α} @[to_additive (attr := gcongr) neg_le_neg] theorem inv_le_inv' : a ≤ b → b⁻¹ ≤ a⁻¹ := - -- Porting note: explicit type annotation was not needed before. - (@inv_le_inv_iff α ..).mpr + inv_le_inv_iff.mpr @[to_additive (attr := gcongr) neg_lt_neg] theorem inv_lt_inv' : a < b → b⁻¹ < a⁻¹ := - -- Porting note: explicit type annotation was not needed before. - (@inv_lt_inv_iff α ..).mpr + inv_lt_inv_iff.mpr -- The additive version is also a `linarith` lemma. @[to_additive] diff --git a/Mathlib/Algebra/Order/Group/DenselyOrdered.lean b/Mathlib/Algebra/Order/Group/DenselyOrdered.lean index 5548fdf7d08d1..2e25d60a9f7e1 100644 --- a/Mathlib/Algebra/Order/Group/DenselyOrdered.lean +++ b/Mathlib/Algebra/Order/Group/DenselyOrdered.lean @@ -18,7 +18,7 @@ section DenselyOrdered variable [Group α] [LinearOrder α] variable [CovariantClass α α (· * ·) (· ≤ ·)] -variable [DenselyOrdered α] {a b c : α} +variable [DenselyOrdered α] {a b : α} @[to_additive] theorem le_of_forall_lt_one_mul_le (h : ∀ ε < 1, a * ε ≤ b) : a ≤ b := diff --git a/Mathlib/Algebra/Order/Group/Indicator.lean b/Mathlib/Algebra/Order/Group/Indicator.lean index 6ae4c61cca65e..a8e229c800374 100644 --- a/Mathlib/Algebra/Order/Group/Indicator.lean +++ b/Mathlib/Algebra/Order/Group/Indicator.lean @@ -106,18 +106,25 @@ lemma mulIndicator_le_mulIndicator' (h : a ∈ s → f a ≤ g a) : mulIndicator s f a ≤ mulIndicator s g a := mulIndicator_rel_mulIndicator le_rfl h -@[to_additive] +@[to_additive (attr := mono, gcongr)] lemma mulIndicator_le_mulIndicator (h : f a ≤ g a) : mulIndicator s f a ≤ mulIndicator s g a := mulIndicator_rel_mulIndicator le_rfl fun _ ↦ h -attribute [mono] mulIndicator_le_mulIndicator indicator_le_indicator +@[to_additive (attr := gcongr)] +lemma mulIndicator_mono (h : f ≤ g) : s.mulIndicator f ≤ s.mulIndicator g := + fun _ ↦ mulIndicator_le_mulIndicator (h _) @[to_additive] -lemma mulIndicator_le_mulIndicator_of_subset (h : s ⊆ t) (hf : ∀ a, 1 ≤ f a) (a : α) : +lemma mulIndicator_le_mulIndicator_apply_of_subset (h : s ⊆ t) (hf : 1 ≤ f a) : mulIndicator s f a ≤ mulIndicator t f a := mulIndicator_apply_le' (fun ha ↦ le_mulIndicator_apply (fun _ ↦ le_rfl) fun hat ↦ (hat <| h ha).elim) fun _ ↦ - one_le_mulIndicator_apply fun _ ↦ hf _ + one_le_mulIndicator_apply fun _ ↦ hf + +@[to_additive] +lemma mulIndicator_le_mulIndicator_of_subset (h : s ⊆ t) (hf : 1 ≤ f) : + mulIndicator s f ≤ mulIndicator t f := + fun _ ↦ mulIndicator_le_mulIndicator_apply_of_subset h (hf _) @[to_additive] lemma mulIndicator_le_self' (hf : ∀ x ∉ s, 1 ≤ f x) : mulIndicator s f ≤ f := @@ -174,6 +181,23 @@ lemma mulIndicator_iInter_apply (h1 : (⊥ : M) = 1) (s : ι → Set α) (f : α refine le_antisymm (by simp only [← h1, le_iInf_iff, bot_le, forall_const]) ?_ simpa [mulIndicator_of_not_mem hj] using (iInf_le (fun i ↦ (s i).mulIndicator f) j) x +@[to_additive] +lemma iSup_mulIndicator {ι : Type*} [Preorder ι] [IsDirected ι (· ≤ ·)] {f : ι → α → M} + {s : ι → Set α} (h1 : (⊥ : M) = 1) (hf : Monotone f) (hs : Monotone s) : + ⨆ i, (s i).mulIndicator (f i) = (⋃ i, s i).mulIndicator (⨆ i, f i) := by + simp only [le_antisymm_iff, iSup_le_iff] + refine ⟨fun i ↦ (mulIndicator_mono (le_iSup _ _)).trans (mulIndicator_le_mulIndicator_of_subset + (subset_iUnion _ _) (fun _ ↦ by simp [← h1])), fun a ↦ ?_⟩ + by_cases ha : a ∈ ⋃ i, s i + · obtain ⟨i, hi⟩ : ∃ i, a ∈ s i := by simpa using ha + rw [mulIndicator_of_mem ha, iSup_apply, iSup_apply] + refine iSup_le fun j ↦ ?_ + obtain ⟨k, hik, hjk⟩ := exists_ge_ge i j + refine le_iSup_of_le k <| (hf hjk _).trans_eq ?_ + rw [mulIndicator_of_mem (hs hik hi)] + · rw [mulIndicator_of_not_mem ha, ← h1] + exact bot_le + end CompleteLattice section CanonicallyOrderedCommMonoid diff --git a/Mathlib/Algebra/Order/Group/MinMax.lean b/Mathlib/Algebra/Order/Group/MinMax.lean index 4e53be43c3ca4..adf6af1c4b904 100644 --- a/Mathlib/Algebra/Order/Group/MinMax.lean +++ b/Mathlib/Algebra/Order/Group/MinMax.lean @@ -30,7 +30,7 @@ end section LinearOrderedCommGroup -variable {α : Type*} [LinearOrderedCommGroup α] {a b c : α} +variable {α : Type*} [LinearOrderedCommGroup α] @[to_additive min_neg_neg] theorem min_inv_inv' (a b : α) : min a⁻¹ b⁻¹ = (max a b)⁻¹ := @@ -64,7 +64,7 @@ end LinearOrderedCommGroup section LinearOrderedAddCommGroup -variable {α : Type*} [LinearOrderedAddCommGroup α] {a b c : α} +variable {α : Type*} [LinearOrderedAddCommGroup α] theorem max_sub_max_le_max (a b c d : α) : max a b - max c d ≤ max (a - c) (b - d) := by simp only [sub_le_iff_le_add, max_le_iff]; constructor diff --git a/Mathlib/Algebra/Order/Group/Opposite.lean b/Mathlib/Algebra/Order/Group/Opposite.lean new file mode 100644 index 0000000000000..e145f616c4c11 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Opposite.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2024 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.Defs +import Mathlib.Algebra.Group.Opposite + +/-! +# Order instances for `MulOpposite`/`AddOpposite` + +This files transfers order instances and ordered monoid/group instances from `α` to `αᵐᵒᵖ` and +`αᵃᵒᵖ`. +-/ + +variable {α : Type*} + +namespace MulOpposite +section Preorder +variable [Preorder α] + +@[to_additive] instance : Preorder αᵐᵒᵖ := Preorder.lift unop + +@[to_additive (attr := simp)] lemma unop_le_unop {a b : αᵐᵒᵖ} : a.unop ≤ b.unop ↔ a ≤ b := .rfl +@[to_additive (attr := simp)] lemma op_le_op {a b : α} : op a ≤ op b ↔ a ≤ b := .rfl + +end Preorder + +@[to_additive] instance [PartialOrder α] : PartialOrder αᵐᵒᵖ := PartialOrder.lift _ unop_injective + +section OrderedCommMonoid +variable [OrderedCommMonoid α] + +@[to_additive] instance : OrderedCommMonoid αᵐᵒᵖ where + mul_le_mul_left a b hab c := mul_le_mul_right' (by simpa) c.unop + +@[to_additive (attr := simp)] lemma unop_le_one {a : αᵐᵒᵖ} : unop a ≤ 1 ↔ a ≤ 1 := .rfl +@[to_additive (attr := simp)] lemma one_le_unop {a : αᵐᵒᵖ} : 1 ≤ unop a ↔ 1 ≤ a := .rfl +@[to_additive (attr := simp)] lemma op_le_one {a : α} : op a ≤ 1 ↔ a ≤ 1 := .rfl +@[to_additive (attr := simp)] lemma one_le_op {a : α} : 1 ≤ op a ↔ 1 ≤ a := .rfl + +end OrderedCommMonoid + +@[to_additive] instance [OrderedCommGroup α] : OrderedCommGroup αᵐᵒᵖ where + __ := instCommGroup + __ := instOrderedCommMonoid + +section OrderedAddCommMonoid +variable [OrderedAddCommMonoid α] + +instance : OrderedAddCommMonoid αᵐᵒᵖ where + add_le_add_left a b hab c := add_le_add_left (by simpa) c.unop + +@[simp] lemma unop_nonneg {a : αᵐᵒᵖ} : unop a ≤ 0 ↔ a ≤ 0 := .rfl +@[simp] lemma unop_nonpos {a : αᵐᵒᵖ} : 0 ≤ unop a ↔ 0 ≤ a := .rfl +@[simp] lemma op_nonneg {a : α} : op a ≤ 0 ↔ a ≤ 0 := .rfl +@[simp] lemma op_nonpos {a : α} : 0 ≤ op a ↔ 0 ≤ a := .rfl + +end OrderedAddCommMonoid + +instance [OrderedAddCommGroup α] : OrderedAddCommGroup αᵐᵒᵖ where + __ := instAddCommGroup + __ := instOrderedAddCommMonoid + +end MulOpposite + +namespace AddOpposite +section OrderedCommMonoid +variable [OrderedCommMonoid α] + +instance : OrderedCommMonoid αᵃᵒᵖ where + mul_le_mul_left a b hab c := mul_le_mul_left' (by simpa) c.unop + +@[simp] lemma unop_le_one {a : αᵃᵒᵖ} : unop a ≤ 1 ↔ a ≤ 1 := .rfl +@[simp] lemma one_le_unop {a : αᵃᵒᵖ} : 1 ≤ unop a ↔ 1 ≤ a := .rfl +@[simp] lemma op_le_one {a : α} : op a ≤ 1 ↔ a ≤ 1 := .rfl +@[simp] lemma one_le_op {a : α} : 1 ≤ op a ↔ 1 ≤ a := .rfl + +end OrderedCommMonoid + +instance [OrderedCommGroup α] : OrderedCommGroup αᵃᵒᵖ where + __ := instCommGroup + __ := instOrderedCommMonoid + +end AddOpposite diff --git a/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean new file mode 100644 index 0000000000000..1b1e0d3b70882 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Pointwise/Bounds.lean @@ -0,0 +1,117 @@ +/- +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.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Order.Group.OrderIso +import Mathlib.Algebra.Order.Monoid.Unbundled.OrderDual +import Mathlib.Order.Bounds.OrderIso + +/-! +# Upper/lower bounds in ordered monoids and groups + +In this file we prove a few facts like “`-s` is bounded above iff `s` is bounded below” +(`bddAbove_neg`). +-/ + +open Function Set +open scoped Pointwise + +variable {ι G M : Type*} + +section Mul +variable [Mul M] [Preorder M] [CovariantClass M M (· * ·) (· ≤ ·)] + [CovariantClass M M (swap (· * ·)) (· ≤ ·)] {f g : ι → M} {s t : Set M} {a b : M} + +@[to_additive] +lemma mul_mem_upperBounds_mul (ha : a ∈ upperBounds s) (hb : b ∈ upperBounds t) : + a * b ∈ upperBounds (s * t) := forall_image2_iff.2 fun _ hx _ hy => mul_le_mul' (ha hx) (hb hy) + +@[to_additive] +lemma subset_upperBounds_mul (s t : Set M) : upperBounds s * upperBounds t ⊆ upperBounds (s * t) := + image2_subset_iff.2 fun _ hx _ hy => mul_mem_upperBounds_mul hx hy + +@[to_additive] +lemma mul_mem_lowerBounds_mul (ha : a ∈ lowerBounds s) (hb : b ∈ lowerBounds t) : + a * b ∈ lowerBounds (s * t) := mul_mem_upperBounds_mul (M := Mᵒᵈ) ha hb + +@[to_additive] +lemma subset_lowerBounds_mul (s t : Set M) : lowerBounds s * lowerBounds t ⊆ lowerBounds (s * t) := + subset_upperBounds_mul (M := Mᵒᵈ) _ _ + +@[to_additive] +lemma BddAbove.mul (hs : BddAbove s) (ht : BddAbove t) : BddAbove (s * t) := + (Nonempty.mul hs ht).mono (subset_upperBounds_mul s t) + +@[to_additive] +lemma BddBelow.mul (hs : BddBelow s) (ht : BddBelow t) : BddBelow (s * t) := + (Nonempty.mul hs ht).mono (subset_lowerBounds_mul s t) + +@[to_additive] +lemma BddAbove.range_mul (hf : BddAbove (range f)) (hg : BddAbove (range g)) : + BddAbove (range fun i ↦ f i * g i) := + .range_comp (f := fun i ↦ (f i, g i)) (bddAbove_range_prod.2 ⟨hf, hg⟩) + (monotone_fst.mul' monotone_snd) + +@[to_additive] +lemma BddBelow.range_mul (hf : BddBelow (range f)) (hg : BddBelow (range g)) : + BddBelow (range fun i ↦ f i * g i) := BddAbove.range_mul (M := Mᵒᵈ) hf hg + +end Mul + +section InvNeg +variable [Group G] [Preorder G] [CovariantClass G G (· * ·) (· ≤ ·)] + [CovariantClass G G (swap (· * ·)) (· ≤ ·)] {s : Set G} {a : G} + +@[to_additive (attr := simp)] +theorem bddAbove_inv : BddAbove s⁻¹ ↔ BddBelow s := + (OrderIso.inv G).bddAbove_preimage + +@[to_additive (attr := simp)] +theorem bddBelow_inv : BddBelow s⁻¹ ↔ BddAbove s := + (OrderIso.inv G).bddBelow_preimage + +@[to_additive] +theorem BddAbove.inv (h : BddAbove s) : BddBelow s⁻¹ := + bddBelow_inv.2 h + +@[to_additive] +theorem BddBelow.inv (h : BddBelow s) : BddAbove s⁻¹ := + bddAbove_inv.2 h + +@[to_additive (attr := simp)] +theorem isLUB_inv : IsLUB s⁻¹ a ↔ IsGLB s a⁻¹ := + (OrderIso.inv G).isLUB_preimage + +@[to_additive] +theorem isLUB_inv' : IsLUB s⁻¹ a⁻¹ ↔ IsGLB s a := + (OrderIso.inv G).isLUB_preimage' + +@[to_additive] +theorem IsGLB.inv (h : IsGLB s a) : IsLUB s⁻¹ a⁻¹ := + isLUB_inv'.2 h + +@[to_additive (attr := simp)] +theorem isGLB_inv : IsGLB s⁻¹ a ↔ IsLUB s a⁻¹ := + (OrderIso.inv G).isGLB_preimage + +@[to_additive] +theorem isGLB_inv' : IsGLB s⁻¹ a⁻¹ ↔ IsLUB s a := + (OrderIso.inv G).isGLB_preimage' + +@[to_additive] +theorem IsLUB.inv (h : IsLUB s a) : IsGLB s⁻¹ a⁻¹ := + isGLB_inv'.2 h + +@[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 diff --git a/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean b/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean new file mode 100644 index 0000000000000..6f09d373cffd4 --- /dev/null +++ b/Mathlib/Algebra/Order/Group/Pointwise/CompleteLattice.lean @@ -0,0 +1,117 @@ +/- +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.Algebra.Order.Group.Pointwise.Bounds +import Mathlib.Order.ConditionallyCompleteLattice.Basic + +/-! +# Infima/suprema in ordered monoids and groups + +In this file we prove a few facts like “The infimum of `-s` is `-` the supremum of `s`”. + +## TODO + +`sSup (s • t) = sSup s • sSup t` and `sInf (s • t) = sInf s • sInf t` hold as well but +`CovariantClass` is currently not polymorphic enough to state it. +-/ + +open Function Set +open scoped Pointwise + +variable {ι G M : Type*} + +section ConditionallyCompleteLattice +variable [ConditionallyCompleteLattice M] + +section One +variable [One M] + +@[to_additive (attr := simp)] lemma csSup_one : sSup (1 : Set M) = 1 := csSup_singleton _ +@[to_additive (attr := simp)] lemma csInf_one : sInf (1 : Set M) = 1 := csInf_singleton _ + +end One + +section Group +variable [Group M] [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (swap (· * ·)) (· ≤ ·)] + {s t : Set M} + +@[to_additive] +lemma csSup_inv (hs₀ : s.Nonempty) (hs₁ : BddBelow s) : sSup s⁻¹ = (sInf s)⁻¹ := by + rw [← image_inv] + exact ((OrderIso.inv _).map_csInf' hs₀ hs₁).symm + +@[to_additive] +lemma csInf_inv (hs₀ : s.Nonempty) (hs₁ : BddAbove s) : sInf s⁻¹ = (sSup s)⁻¹ := by + rw [← image_inv] + exact ((OrderIso.inv _).map_csSup' hs₀ hs₁).symm + +@[to_additive] +lemma csSup_mul (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : + sSup (s * t) = sSup s * sSup t := + csSup_image2_eq_csSup_csSup (fun _ => (OrderIso.mulRight _).to_galoisConnection) + (fun _ => (OrderIso.mulLeft _).to_galoisConnection) hs₀ hs₁ ht₀ ht₁ + +@[to_additive] +lemma csInf_mul (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : + sInf (s * t) = sInf s * sInf t := + csInf_image2_eq_csInf_csInf (fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) + (fun _ => (OrderIso.mulLeft _).symm.to_galoisConnection) hs₀ hs₁ ht₀ ht₁ + +@[to_additive] +lemma csSup_div (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : + sSup (s / t) = sSup s / sInf t := by + rw [div_eq_mul_inv, csSup_mul hs₀ hs₁ ht₀.inv ht₁.inv, csSup_inv ht₀ ht₁, div_eq_mul_inv] + +@[to_additive] +lemma csInf_div (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : + sInf (s / t) = sInf s / sSup t := by + rw [div_eq_mul_inv, csInf_mul hs₀ hs₁ ht₀.inv ht₁.inv, csInf_inv ht₀ ht₁, div_eq_mul_inv] + +end Group +end ConditionallyCompleteLattice + +section CompleteLattice +variable [CompleteLattice M] + +section One +variable [One M] + +@[to_additive] lemma sSup_one : sSup (1 : Set M) = 1 := sSup_singleton +@[to_additive] lemma sInf_one : sInf (1 : Set M) = 1 := sInf_singleton + +end One + +section Group +variable [Group M] [CovariantClass M M (· * ·) (· ≤ ·)] [CovariantClass M M (swap (· * ·)) (· ≤ ·)] + (s t : Set M) + +@[to_additive] +lemma sSup_inv (s : Set M) : sSup s⁻¹ = (sInf s)⁻¹ := by + rw [← image_inv, sSup_image] + exact ((OrderIso.inv M).map_sInf _).symm + +@[to_additive] +lemma sInf_inv (s : Set M) : sInf s⁻¹ = (sSup s)⁻¹ := by + rw [← image_inv, sInf_image] + exact ((OrderIso.inv M).map_sSup _).symm + +@[to_additive] +lemma sSup_mul : sSup (s * t) = sSup s * sSup t := + (sSup_image2_eq_sSup_sSup fun _ => (OrderIso.mulRight _).to_galoisConnection) fun _ => + (OrderIso.mulLeft _).to_galoisConnection + +@[to_additive] +lemma sInf_mul : sInf (s * t) = sInf s * sInf t := + (sInf_image2_eq_sInf_sInf fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) fun _ => + (OrderIso.mulLeft _).symm.to_galoisConnection + +@[to_additive] +lemma sSup_div : sSup (s / t) = sSup s / sInf t := by simp_rw [div_eq_mul_inv, sSup_mul, sSup_inv] + +@[to_additive] +lemma sInf_div : sInf (s / t) = sInf s / sSup t := by simp_rw [div_eq_mul_inv, sInf_mul, sInf_inv] + +end Group +end CompleteLattice diff --git a/Mathlib/Algebra/Order/Group/PosPart.lean b/Mathlib/Algebra/Order/Group/PosPart.lean index b8af733a70b23..8374c0a8ed405 100644 --- a/Mathlib/Algebra/Order/Group/PosPart.lean +++ b/Mathlib/Algebra/Order/Group/PosPart.lean @@ -242,12 +242,12 @@ end covariantmul end LinearOrder namespace Pi -variable {ι : Type*} {α : ι → Type*} [∀ i, Lattice (α i)] [∀ i, AddCommGroup (α i)] +variable {ι : Type*} {α : ι → Type*} [∀ i, Lattice (α i)] [∀ i, Group (α i)] -@[to_additive (attr := simp)] lemma oneLePart_apply (f : ∀ i, α i) (i : ι) : f⁺ i = (f i)⁺ := rfl -@[to_additive (attr := simp)] lemma leOnePart_apply (f : ∀ i, α i) (i : ι) : f⁻ i = (f i)⁻ := rfl +@[to_additive (attr := simp)] lemma oneLePart_apply (f : ∀ i, α i) (i : ι) : f⁺ᵐ i = (f i)⁺ᵐ := rfl +@[to_additive (attr := simp)] lemma leOnePart_apply (f : ∀ i, α i) (i : ι) : f⁻ᵐ i = (f i)⁻ᵐ := rfl -@[to_additive] lemma oneLePart_def (f : ∀ i, α i) : f⁺ = fun i ↦ (f i)⁺ := rfl -@[to_additive] lemma leOnePart_def (f : ∀ i, α i) : f⁻ = fun i ↦ (f i)⁻ := rfl +@[to_additive] lemma oneLePart_def (f : ∀ i, α i) : f⁺ᵐ = fun i ↦ (f i)⁺ᵐ := rfl +@[to_additive] lemma leOnePart_def (f : ∀ i, α i) : f⁻ᵐ = fun i ↦ (f i)⁻ᵐ := rfl end Pi diff --git a/Mathlib/Algebra/Order/Group/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Group/Unbundled/Basic.lean index f0e95176dbb3d..4d59951456a6e 100644 --- a/Mathlib/Algebra/Order/Group/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Group/Unbundled/Basic.lean @@ -33,7 +33,7 @@ variable [Group α] section TypeclassesLeftLE -variable [LE α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b c d : α} +variable [LE α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b c : α} /-- Uses `left` co(ntra)variant. -/ @[to_additive (attr := simp) "Uses `left` co(ntra)variant."] @@ -471,7 +471,7 @@ variable [Group α] [LE α] section Right -variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] {a b c d : α} +variable [CovariantClass α α (swap (· * ·)) (· ≤ ·)] {a b c : α} @[to_additive] theorem div_le_div_iff_right (c : α) : a / c ≤ b / c ↔ a ≤ b := by @@ -594,7 +594,7 @@ variable [Group α] [LT α] section Right -variable [CovariantClass α α (swap (· * ·)) (· < ·)] {a b c d : α} +variable [CovariantClass α α (swap (· * ·)) (· < ·)] {a b c : α} @[to_additive (attr := simp)] theorem div_lt_div_iff_right (c : α) : a / c < b / c ↔ a < b := by @@ -722,7 +722,7 @@ variable [CovariantClass α α (· * ·) (· ≤ ·)] section VariableNames -variable {a b c : α} +variable {a b : α} @[to_additive] theorem le_of_forall_one_lt_lt_mul (h : ∀ ε : α, 1 < ε → a < b * ε) : a ≤ b := diff --git a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean index 773e4ce5f46eb..96c6eed502379 100644 --- a/Mathlib/Algebra/Order/Group/Unbundled/Int.lean +++ b/Mathlib/Algebra/Order/Group/Unbundled/Int.lean @@ -82,6 +82,15 @@ theorem abs_le_one_iff {a : ℤ} : |a| ≤ 1 ↔ a = 0 ∨ a = 1 ∨ a = -1 := b theorem one_le_abs {z : ℤ} (h₀ : z ≠ 0) : 1 ≤ |z| := add_one_le_iff.mpr (abs_pos.mpr h₀) +lemma eq_zero_of_abs_lt_dvd {m x : ℤ} (h1 : m ∣ x) (h2 : |x| < m) : x = 0 := by + by_contra h + have := Int.natAbs_le_of_dvd_ne_zero h1 h + rw [Int.abs_eq_natAbs] at h2 + omega + +lemma abs_sub_lt_of_lt_lt {m a b : ℕ} (ha : a < m) (hb : b < m) : |(b : ℤ) - a| < m := by + rw [abs_lt]; omega + /-! #### `/` -/ theorem ediv_eq_zero_of_lt_abs {a b : ℤ} (H1 : 0 ≤ a) (H2 : a < |b|) : a / b = 0 := diff --git a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean index f8df22be3c53e..1808690367f6d 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Canonical.lean @@ -130,11 +130,6 @@ instance (priority := 100) LinearOrderedCommGroupWithZero.toMulPosStrictMono : MulPosStrictMono α where elim a b c hbc := by by_contra! h; exact hbc.not_le <| (mul_le_mul_right a.2).1 h -/-- Alias of `mul_le_one'` for unification. -/ -@[deprecated mul_le_one' (since := "2024-08-21")] -theorem mul_le_one₀ (ha : a ≤ 1) (hb : b ≤ 1) : a * b ≤ 1 := - mul_le_one' ha hb - /-- Alias of `one_le_mul'` for unification. -/ @[deprecated one_le_mul (since := "2024-08-21")] theorem one_le_mul₀ (ha : 1 ≤ a) (hb : 1 ≤ b) : 1 ≤ a * b := @@ -185,25 +180,9 @@ theorem inv_mul_lt_of_lt_mul₀ (h : a < b * c) : b⁻¹ * a < c := by theorem mul_lt_right₀ (c : α) (h : a < b) (hc : c ≠ 0) : a * c < b * c := mul_lt_mul_of_pos_right h (zero_lt_iff.2 hc) -theorem inv_lt_one₀ (ha : a ≠ 0) : a⁻¹ < 1 ↔ 1 < a := - inv_lt_one' (a := Units.mk0 a ha) - -theorem one_lt_inv₀ (ha : a ≠ 0) : 1 < a⁻¹ ↔ a < 1 := - one_lt_inv' (a := Units.mk0 a ha) - -theorem inv_lt_inv₀ (ha : a ≠ 0) (hb : b ≠ 0) : a⁻¹ < b⁻¹ ↔ b < a := - show (Units.mk0 a ha)⁻¹ < (Units.mk0 b hb)⁻¹ ↔ Units.mk0 b hb < Units.mk0 a ha from - have : CovariantClass αˣ αˣ (· * ·) (· < ·) := - IsLeftCancelMul.covariant_mul_lt_of_covariant_mul_le αˣ - inv_lt_inv_iff - -theorem inv_le_inv₀ (ha : a ≠ 0) (hb : b ≠ 0) : a⁻¹ ≤ b⁻¹ ↔ b ≤ a := - show (Units.mk0 a ha)⁻¹ ≤ (Units.mk0 b hb)⁻¹ ↔ Units.mk0 b hb ≤ Units.mk0 a ha from - inv_le_inv_iff - theorem lt_of_mul_lt_mul_of_le₀ (h : a * b < c * d) (hc : 0 < c) (hh : c ≤ a) : b < d := by have ha : a ≠ 0 := ne_of_gt (lt_of_lt_of_le hc hh) - simp_rw [← inv_le_inv₀ ha (ne_of_gt hc)] at hh + rw [← inv_le_inv₀ (zero_lt_iff.2 ha) hc] at hh have := mul_lt_mul_of_lt_of_le₀ hh (inv_ne_zero (ne_of_gt hc)) h simpa [inv_mul_cancel_left₀ ha, inv_mul_cancel_left₀ (ne_of_gt hc)] using this @@ -219,7 +198,8 @@ theorem div_le_div_right₀ (hc : c ≠ 0) : a / c ≤ b / c ↔ a ≤ b := by rw [div_eq_mul_inv, div_eq_mul_inv, mul_le_mul_right (zero_lt_iff.2 (inv_ne_zero hc))] theorem div_le_div_left₀ (ha : a ≠ 0) (hb : b ≠ 0) (hc : c ≠ 0) : a / b ≤ a / c ↔ c ≤ b := by - simp only [div_eq_mul_inv, mul_le_mul_left (zero_lt_iff.2 ha), inv_le_inv₀ hb hc] + simp only [div_eq_mul_inv, mul_le_mul_left (zero_lt_iff.2 ha), + inv_le_inv₀ (zero_lt_iff.2 hb) (zero_lt_iff.2 hc)] /-- `Equiv.mulLeft₀` as an `OrderIso` on a `LinearOrderedCommGroupWithZero.`. @@ -263,8 +243,6 @@ lemma pow_lt_pow_succ (ha : 1 < a) : a ^ n < a ^ n.succ := by lemma pow_lt_pow_right₀ (ha : 1 < a) (hmn : m < n) : a ^ m < a ^ n := by induction' hmn with n _ ih; exacts [pow_lt_pow_succ ha, lt_trans ih (pow_lt_pow_succ ha)] -@[deprecated (since := "2023-12-23")] alias pow_lt_pow₀ := pow_lt_pow_right₀ - end LinearOrderedCommGroupWithZero instance instLinearOrderedCommMonoidWithZeroMultiplicativeOrderDual diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean index ce7ed361fd599..b238cd2ab171e 100644 --- a/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled.lean @@ -7,6 +7,7 @@ import Mathlib.Algebra.Group.Pi.Basic import Mathlib.Algebra.GroupWithZero.Units.Basic import Mathlib.Algebra.Order.Monoid.Unbundled.Defs import Mathlib.Algebra.Order.ZeroLEOne +import Mathlib.Tactic.Bound.Attribute import Mathlib.Tactic.GCongr.CoreAttrs import Mathlib.Tactic.Nontriviality @@ -83,6 +84,8 @@ for a discussion about this notation, and whether to enable it globally (note th currently global but broken, hence actually only works locally). -/ +open Function + variable {M₀ G₀ : Type*} (α : Type*) set_option quotPrecheck false in @@ -935,12 +938,16 @@ section MonoidWithZero variable [MonoidWithZero M₀] section Preorder -variable [Preorder M₀] {a b c d : M₀} {n : ℕ} +variable [Preorder M₀] {a b : M₀} {m n : ℕ} @[simp] lemma pow_nonneg [ZeroLEOneClass M₀] [PosMulMono M₀] (ha : 0 ≤ a) : ∀ n, 0 ≤ a ^ n | 0 => pow_zero a ▸ zero_le_one | n + 1 => pow_succ a n ▸ mul_nonneg (pow_nonneg ha _) ha +lemma zero_pow_le_one [ZeroLEOneClass M₀] : ∀ n : ℕ, (0 : M₀) ^ n ≤ 1 + | 0 => (pow_zero _).le + | n + 1 => by rw [zero_pow n.succ_ne_zero]; exact zero_le_one + lemma pow_le_pow_of_le_one [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] (ha₀ : 0 ≤ a) (ha₁ : a ≤ 1) : ∀ {m n : ℕ}, m ≤ n → a ^ n ≤ a ^ m | _, _, Nat.le.refl => le_rfl @@ -958,9 +965,6 @@ lemma sq_le [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] (h₀ : 0 lemma one_le_mul_of_one_le_of_one_le [ZeroLEOneClass M₀] [PosMulMono M₀] (ha : 1 ≤ a) (hb : 1 ≤ b) : (1 : M₀) ≤ a * b := Left.one_le_mul_of_le_of_le ha hb <| zero_le_one.trans ha -lemma mul_le_one [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] (ha : a ≤ 1) (hb₀ : 0 ≤ b) - (hb : b ≤ 1) : a * b ≤ 1 := one_mul (1 : M₀) ▸ mul_le_mul ha hb hb₀ zero_le_one - lemma one_lt_mul_of_le_of_lt [ZeroLEOneClass M₀] [MulPosMono M₀] (ha : 1 ≤ a) (hb : 1 < b) : 1 < a * b := hb.trans_le <| le_mul_of_one_le_left (zero_le_one.trans hb.le) ha @@ -975,6 +979,43 @@ lemma mul_lt_one_of_nonneg_of_lt_one_left [PosMulMono M₀] (ha₀ : 0 ≤ a) (h lemma mul_lt_one_of_nonneg_of_lt_one_right [MulPosMono M₀] (ha : a ≤ 1) (hb₀ : 0 ≤ b) (hb : b < 1) : a * b < 1 := (mul_le_of_le_one_left hb₀ ha).trans_lt hb +section +variable [ZeroLEOneClass M₀] [PosMulMono M₀] [MulPosMono M₀] + +lemma mul_le_one₀ (ha : a ≤ 1) (hb₀ : 0 ≤ b) (hb : b ≤ 1) : a * b ≤ 1 := + one_mul (1 : M₀) ▸ mul_le_mul ha hb hb₀ zero_le_one + +lemma pow_le_one₀ : ∀ {n : ℕ}, 0 ≤ a → a ≤ 1 → a ^ n ≤ 1 + | 0, _, _ => (pow_zero a).le + | n + 1, h₀, h₁ => (pow_succ a n).le.trans (mul_le_one₀ (pow_le_one₀ h₀ h₁) h₀ h₁) + +lemma pow_lt_one₀ (h₀ : 0 ≤ a) (h₁ : a < 1) : ∀ {n : ℕ}, n ≠ 0 → a ^ n < 1 + | 0, h => (h rfl).elim + | n + 1, _ => by + rw [pow_succ']; exact mul_lt_one_of_nonneg_of_lt_one_left h₀ h₁ (pow_le_one₀ h₀ h₁.le) + +lemma one_le_pow₀ (ha : 1 ≤ a) : ∀ {n : ℕ}, 1 ≤ a ^ n + | 0 => by rw [pow_zero] + | n + 1 => by + simpa only [pow_succ', mul_one] + using mul_le_mul ha (one_le_pow₀ ha) zero_le_one (zero_le_one.trans ha) + +lemma one_lt_pow₀ (ha : 1 < a) : ∀ {n : ℕ}, n ≠ 0 → 1 < a ^ n + | 0, h => (h rfl).elim + | n + 1, _ => by rw [pow_succ']; exact one_lt_mul_of_lt_of_le ha (one_le_pow₀ ha.le) + +lemma pow_right_mono₀ (h : 1 ≤ a) : Monotone (a ^ ·) := + monotone_nat_of_le_succ fun n => by + rw [pow_succ']; exact le_mul_of_one_le_left (pow_nonneg (zero_le_one.trans h) _) h + +@[gcongr] +lemma pow_le_pow_right₀ (ha : 1 ≤ a) (hmn : m ≤ n) : a ^ m ≤ a ^ n := pow_right_mono₀ ha hmn + +lemma le_self_pow₀ (ha : 1 ≤ a) (hn : n ≠ 0) : a ≤ a ^ n := by + simpa only [pow_one] using pow_le_pow_right₀ ha <| Nat.pos_iff_ne_zero.2 hn + +end + variable [Preorder α] {f g : α → M₀} lemma monotone_mul_left_of_nonneg [PosMulMono M₀] (ha : 0 ≤ a) : Monotone fun x ↦ a * x := @@ -1113,8 +1154,16 @@ end CancelMonoidWithZero section GroupWithZero variable [GroupWithZero G₀] +section Preorder +variable [Preorder G₀] [ZeroLEOneClass G₀] + +/-- See `div_self` for the version with equality when `a ≠ 0`. -/ +lemma div_self_le_one (a : G₀) : a / a ≤ 1 := by obtain rfl | ha := eq_or_ne a 0 <;> simp [*] + +end Preorder + section PartialOrder -variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b c d : G₀} +variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b c : G₀} @[simp] lemma inv_pos : 0 < a⁻¹ ↔ 0 < a := suffices ∀ a : G₀, 0 < a → 0 < a⁻¹ from ⟨fun h ↦ inv_inv a ▸ this _ h, this a⟩ @@ -1142,17 +1191,21 @@ lemma zpow_nonneg [PosMulMono G₀] (ha : 0 ≤ a) : ∀ n : ℤ, 0 ≤ a ^ n | (n : ℕ) => by rw [zpow_natCast]; exact pow_nonneg ha _ |-(n + 1 : ℕ) => by rw [zpow_neg, inv_nonneg, zpow_natCast]; exact pow_nonneg ha _ -lemma zpow_pos_of_pos [PosMulStrictMono G₀] (ha : 0 < a) : ∀ n : ℤ, 0 < a ^ n +lemma zpow_pos [PosMulStrictMono G₀] (ha : 0 < a) : ∀ n : ℤ, 0 < a ^ n | (n : ℕ) => by rw [zpow_natCast]; exact pow_pos ha _ |-(n + 1 : ℕ) => by rw [zpow_neg, inv_pos, zpow_natCast]; exact pow_pos ha _ +@[deprecated (since := "2024-10-08")] alias zpow_pos_of_pos := zpow_pos + section PosMulMono -variable [PosMulMono G₀] +variable [PosMulMono G₀] {m n : ℤ} +/-- See `le_inv_mul_iff₀'` for a version with multiplication on the other side. -/ lemma le_inv_mul_iff₀ (hc : 0 < c) : a ≤ c⁻¹ * b ↔ c * a ≤ b where mp h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_left h hc.le mpr h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_left h (inv_nonneg.2 hc.le) +/-- See `inv_mul_le_iff₀'` for a version with multiplication on the other side. -/ lemma inv_mul_le_iff₀ (hc : 0 < c) : c⁻¹ * b ≤ a ↔ b ≤ c * a where mp h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_left h hc.le mpr h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_left h (inv_nonneg.2 hc.le) @@ -1160,39 +1213,277 @@ lemma inv_mul_le_iff₀ (hc : 0 < c) : c⁻¹ * b ≤ a ↔ b ≤ c * a where lemma one_le_inv_mul₀ (ha : 0 < a) : 1 ≤ a⁻¹ * b ↔ a ≤ b := by rw [le_inv_mul_iff₀ ha, mul_one] lemma inv_mul_le_one₀ (ha : 0 < a) : a⁻¹ * b ≤ 1 ↔ b ≤ a := by rw [inv_mul_le_iff₀ ha, mul_one] +/-- See `inv_le_iff_one_le_mul₀` for a version with multiplication on the other side. -/ +lemma inv_le_iff_one_le_mul₀' (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ a * b := by + rw [← inv_mul_le_iff₀ ha, mul_one] + lemma one_le_inv₀ (ha : 0 < a) : 1 ≤ a⁻¹ ↔ a ≤ 1 := by simpa using one_le_inv_mul₀ ha (b := 1) lemma inv_le_one₀ (ha : 0 < a) : a⁻¹ ≤ 1 ↔ 1 ≤ a := by simpa using inv_mul_le_one₀ ha (b := 1) +@[bound] +lemma inv_le_one_of_one_le₀ (ha : 1 ≤ a) : a⁻¹ ≤ 1 := (inv_le_one₀ <| zero_lt_one.trans_le ha).2 ha + +lemma one_le_inv_iff₀ : 1 ≤ a⁻¹ ↔ 0 < a ∧ a ≤ 1 where + mp h := ⟨inv_pos.1 (zero_lt_one.trans_le h), + inv_inv a ▸ (inv_le_one₀ <| zero_lt_one.trans_le h).2 h⟩ + mpr h := (one_le_inv₀ h.1).2 h.2 + +/-- One direction of `le_inv_mul_iff₀` where `c` is allowed to be `0` (but `b` must be nonnegative). +-/ +lemma mul_le_of_le_inv_mul₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ c⁻¹ * b) : c * a ≤ b := by + obtain rfl | hc := hc.eq_or_lt + · simpa using hb + · rwa [le_inv_mul_iff₀ hc] at h + +/-- One direction of `inv_mul_le_iff₀` where `b` is allowed to be `0` (but `c` must be nonnegative). +-/ +lemma inv_mul_le_of_le_mul₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ b * c) : b⁻¹ * a ≤ c := by + obtain rfl | hb := hb.eq_or_lt + · simp [hc] + · rwa [inv_mul_le_iff₀ hb] + +@[bound] +lemma inv_mul_le_one_of_le₀ (h : a ≤ b) (hb : 0 ≤ b) : b⁻¹ * a ≤ 1 := + inv_mul_le_of_le_mul₀ hb zero_le_one <| by rwa [mul_one] + +lemma zpow_right_mono₀ (ha : 1 ≤ a) : Monotone fun n : ℤ ↦ a ^ n := by + refine monotone_int_of_le_succ fun n ↦ ?_ + rw [zpow_add_one₀ (zero_lt_one.trans_le ha).ne'] + exact le_mul_of_one_le_right (zpow_nonneg (zero_le_one.trans ha) _) ha + +lemma zpow_right_anti₀ (ha₀ : 0 < a) (ha₁ : a ≤ 1) : Antitone fun n : ℤ ↦ a ^ n := by + refine antitone_int_of_succ_le fun n ↦ ?_ + rw [zpow_add_one₀ ha₀.ne'] + exact mul_le_of_le_one_right (zpow_nonneg ha₀.le _) ha₁ + +@[gcongr] +lemma zpow_le_zpow_right₀ (ha : 1 ≤ a) (hmn : m ≤ n) : a ^ m ≤ a ^ n := zpow_right_mono₀ ha hmn + +@[gcongr] +lemma zpow_le_zpow_right_of_le_one₀ (ha₀ : 0 < a) (ha₁ : a ≤ 1) (hmn : m ≤ n) : a ^ n ≤ a ^ m := + zpow_right_anti₀ ha₀ ha₁ hmn + +lemma one_le_zpow₀ (ha : 1 ≤ a) (hn : 0 ≤ n) : 1 ≤ a ^ n := by simpa using zpow_right_mono₀ ha hn + +lemma zpow_le_one₀ (ha₀ : 0 < a) (ha₁ : a ≤ 1) (hn : 0 ≤ n) : a ^ n ≤ 1 := by + simpa using zpow_right_anti₀ ha₀ ha₁ hn + +lemma zpow_le_one_of_nonpos₀ (ha : 1 ≤ a) (hn : n ≤ 0) : a ^ n ≤ 1 := by + simpa using zpow_right_mono₀ ha hn + +lemma one_le_zpow_of_nonpos₀ (ha₀ : 0 < a) (ha₁ : a ≤ 1) (hn : n ≤ 0) : 1 ≤ a ^ n := by + simpa using zpow_right_anti₀ ha₀ ha₁ hn + end PosMulMono section MulPosMono variable [MulPosMono G₀] +/-- See `le_mul_inv_iff₀'` for a version with multiplication on the other side. -/ lemma le_mul_inv_iff₀ (hc : 0 < c) : a ≤ b * c⁻¹ ↔ a * c ≤ b where mp h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_right h hc.le mpr h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_right h (inv_nonneg.2 hc.le) +/-- See `mul_inv_le_iff₀'` for a version with multiplication on the other side. -/ lemma mul_inv_le_iff₀ (hc : 0 < c) : b * c⁻¹ ≤ a ↔ b ≤ a * c where mp h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_right h hc.le mpr h := by simpa [hc.ne'] using mul_le_mul_of_nonneg_right h (inv_nonneg.2 hc.le) +/-- See `le_div_iff₀'` for a version with multiplication on the other side. -/ lemma le_div_iff₀ (hc : 0 < c) : a ≤ b / c ↔ a * c ≤ b := by rw [div_eq_mul_inv, le_mul_inv_iff₀ hc] +/-- See `div_le_iff₀'` for a version with multiplication on the other side. -/ lemma div_le_iff₀ (hc : 0 < c) : b / c ≤ a ↔ b ≤ a * c := by rw [div_eq_mul_inv, mul_inv_le_iff₀ hc] +/-- See `inv_le_iff_one_le_mul₀'` for a version with multiplication on the other side. -/ +lemma inv_le_iff_one_le_mul₀ (ha : 0 < a) : a⁻¹ ≤ b ↔ 1 ≤ b * a := by + rw [← mul_inv_le_iff₀ ha, one_mul] + lemma one_le_div₀ (hb : 0 < b) : 1 ≤ a / b ↔ b ≤ a := by rw [le_div_iff₀ hb, one_mul] lemma div_le_one₀ (hb : 0 < b) : a / b ≤ 1 ↔ a ≤ b := by rw [div_le_iff₀ hb, one_mul] +/-- One direction of `le_mul_inv_iff₀` where `c` is allowed to be `0` (but `b` must be nonnegative). +-/ +lemma mul_le_of_le_mul_inv₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ b * c⁻¹) : a * c ≤ b := by + obtain rfl | hc := hc.eq_or_lt + · simpa using hb + · rwa [le_mul_inv_iff₀ hc] at h + +/-- One direction of `mul_inv_le_iff₀` where `b` is allowed to be `0` (but `c` must be nonnegative). +-/ +lemma mul_inv_le_of_le_mul₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ c * b) : a * b⁻¹ ≤ c := by + obtain rfl | hb := hb.eq_or_lt + · simp [hc] + · rwa [mul_inv_le_iff₀ hb] + +/-- One direction of `le_div_iff₀` where `c` is allowed to be `0` (but `b` must be nonnegative). -/ +lemma mul_le_of_le_div₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ b / c) : a * c ≤ b := + mul_le_of_le_mul_inv₀ hb hc (div_eq_mul_inv b _ ▸ h) + +/-- One direction of `div_le_iff₀` where `b` is allowed to be `0` (but `c` must be nonnegative). -/ +lemma div_le_of_le_mul₀ (hb : 0 ≤ b) (hc : 0 ≤ c) (h : a ≤ c * b) : a / b ≤ c := + div_eq_mul_inv a _ ▸ mul_inv_le_of_le_mul₀ hb hc h + +@[bound] +lemma mul_inv_le_one_of_le₀ (h : a ≤ b) (hb : 0 ≤ b) : a * b⁻¹ ≤ 1 := + mul_inv_le_of_le_mul₀ hb zero_le_one <| by rwa [one_mul] + +@[bound] +lemma div_le_one_of_le₀ (h : a ≤ b) (hb : 0 ≤ b) : a / b ≤ 1 := + div_le_of_le_mul₀ hb zero_le_one <| by rwa [one_mul] + @[deprecated (since := "2024-08-21")] alias le_div_iff := le_div_iff₀ @[deprecated (since := "2024-08-21")] alias div_le_iff := div_le_iff₀ +variable [PosMulMono G₀] + +/-- See `inv_anti₀` for the implication from right-to-left with one fewer assumption. -/ +lemma inv_le_inv₀ (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b⁻¹ ↔ b ≤ a := by + rw [inv_le_iff_one_le_mul₀' ha, le_mul_inv_iff₀ hb, one_mul] + +@[gcongr, bound] +lemma inv_anti₀ (hb : 0 < b) (hba : b ≤ a) : a⁻¹ ≤ b⁻¹ := (inv_le_inv₀ (hb.trans_le hba) hb).2 hba + +/-- See also `inv_le_of_inv_le₀` for a one-sided implication with one fewer assumption. -/ +lemma inv_le_comm₀ (ha : 0 < a) (hb : 0 < b) : a⁻¹ ≤ b ↔ b⁻¹ ≤ a := by + rw [← inv_le_inv₀ hb (inv_pos.2 ha), inv_inv] + +lemma inv_le_of_inv_le₀ (ha : 0 < a) (h : a⁻¹ ≤ b) : b⁻¹ ≤ a := + (inv_le_comm₀ ha <| (inv_pos.2 ha).trans_le h).1 h + +/-- See also `le_inv_of_le_inv₀` for a one-sided implication with one fewer assumption. -/ +lemma le_inv_comm₀ (ha : 0 < a) (hb : 0 < b) : a ≤ b⁻¹ ↔ b ≤ a⁻¹ := by + rw [← inv_le_inv₀ (inv_pos.2 hb) ha, inv_inv] + +lemma le_inv_of_le_inv₀ (ha : 0 < a) (h : a ≤ b⁻¹) : b ≤ a⁻¹ := + (le_inv_comm₀ ha <| inv_pos.1 <| ha.trans_le h).1 h + end MulPosMono + +section PosMulStrictMono +variable [PosMulStrictMono G₀] {m n : ℤ} + +/-- See `lt_inv_mul_iff₀'` for a version with multiplication on the other side. -/ +lemma lt_inv_mul_iff₀ (hc : 0 < c) : a < c⁻¹ * b ↔ c * a < b where + mp h := by simpa [hc.ne'] using mul_lt_mul_of_pos_left h hc + mpr h := by simpa [hc.ne'] using mul_lt_mul_of_pos_left h (inv_pos.2 hc) + +/-- See `inv_mul_lt_iff₀'` for a version with multiplication on the other side. -/ +lemma inv_mul_lt_iff₀ (hc : 0 < c) : c⁻¹ * b < a ↔ b < c * a where + mp h := by simpa [hc.ne'] using mul_lt_mul_of_pos_left h hc + mpr h := by simpa [hc.ne'] using mul_lt_mul_of_pos_left h (inv_pos.2 hc) + +/-- See `inv_lt_iff_one_lt_mul₀` for a version with multiplication on the other side. -/ +lemma inv_lt_iff_one_lt_mul₀' (ha : 0 < a) : a⁻¹ < b ↔ 1 < a * b := by + rw [← inv_mul_lt_iff₀ ha, mul_one] + +lemma one_lt_inv_mul₀ (ha : 0 < a) : 1 < a⁻¹ * b ↔ a < b := by rw [lt_inv_mul_iff₀ ha, mul_one] +lemma inv_mul_lt_one₀ (ha : 0 < a) : a⁻¹ * b < 1 ↔ b < a := by rw [inv_mul_lt_iff₀ ha, mul_one] + +lemma one_lt_inv₀ (ha : 0 < a) : 1 < a⁻¹ ↔ a < 1 := by simpa using one_lt_inv_mul₀ ha (b := 1) +lemma inv_lt_one₀ (ha : 0 < a) : a⁻¹ < 1 ↔ 1 < a := by simpa using inv_mul_lt_one₀ ha (b := 1) + +@[bound] +lemma inv_lt_one_of_one_lt₀ (ha : 1 < a) : a⁻¹ < 1 := (inv_lt_one₀ <| zero_lt_one.trans ha).2 ha + +lemma one_lt_inv_iff₀ : 1 < a⁻¹ ↔ 0 < a ∧ a < 1 where + mp h := ⟨inv_pos.1 (zero_lt_one.trans h), inv_inv a ▸ (inv_lt_one₀ <| zero_lt_one.trans h).2 h⟩ + mpr h := (one_lt_inv₀ h.1).2 h.2 + +lemma zpow_right_strictMono₀ (ha : 1 < a) : StrictMono fun n : ℤ ↦ a ^ n := by + refine strictMono_int_of_lt_succ fun n ↦ ?_ + rw [zpow_add_one₀ (zero_lt_one.trans ha).ne'] + exact lt_mul_of_one_lt_right (zpow_pos (zero_lt_one.trans ha) _) ha + +lemma zpow_right_strictAnti₀ (ha₀ : 0 < a) (ha₁ : a < 1) : StrictAnti fun n : ℤ ↦ a ^ n := by + refine strictAnti_int_of_succ_lt fun n ↦ ?_ + rw [zpow_add_one₀ ha₀.ne'] + exact mul_lt_of_lt_one_right (zpow_pos ha₀ _) ha₁ + +@[gcongr] +lemma zpow_lt_zpow_right₀ (ha : 1 < a) (hmn : m < n) : a ^ m < a ^ n := + zpow_right_strictMono₀ ha hmn + +@[gcongr] +lemma zpow_lt_zpow_right_of_lt_one₀ (ha₀ : 0 < a) (ha₁ : a ≤ 1) (hmn : m ≤ n) : a ^ n ≤ a ^ m := + zpow_right_anti₀ ha₀ ha₁ hmn + +lemma one_lt_zpow₀ (ha : 1 < a) (hn : 0 < n) : 1 < a ^ n := by + simpa using zpow_right_strictMono₀ ha hn + +lemma zpow_lt_one₀ (ha₀ : 0 < a) (ha₁ : a < 1) (hn : 0 < n) : a ^ n < 1 := by + simpa using zpow_right_strictAnti₀ ha₀ ha₁ hn + +lemma zpow_lt_one_of_neg₀ (ha : 1 < a) (hn : n < 0) : a ^ n < 1 := by + simpa using zpow_right_strictMono₀ ha hn + +lemma one_lt_zpow_of_neg₀ (ha₀ : 0 < a) (ha₁ : a < 1) (hn : n < 0) : 1 < a ^ n := by + simpa using zpow_right_strictAnti₀ ha₀ ha₁ hn + +@[simp] lemma zpow_le_zpow_iff_right₀ (ha : 1 < a) : a ^ m ≤ a ^ n ↔ m ≤ n := + (zpow_right_strictMono₀ ha).le_iff_le + +@[simp] lemma zpow_lt_zpow_iff_right₀ (ha : 1 < a) : a ^ m < a ^ n ↔ m < n := + (zpow_right_strictMono₀ ha).lt_iff_lt + +end PosMulStrictMono + +section MulPosStrictMono +variable [MulPosStrictMono G₀] + +/-- See `lt_mul_inv_iff₀'` for a version with multiplication on the other side. -/ +lemma lt_mul_inv_iff₀ (hc : 0 < c) : a < b * c⁻¹ ↔ a * c < b where + mp h := by simpa [hc.ne'] using mul_lt_mul_of_pos_right h hc + mpr h := by simpa [hc.ne'] using mul_lt_mul_of_pos_right h (inv_pos.2 hc) + +/-- See `mul_inv_lt_iff₀'` for a version with multiplication on the other side. -/ +lemma mul_inv_lt_iff₀ (hc : 0 < c) : b * c⁻¹ < a ↔ b < a * c where + mp h := by simpa [hc.ne'] using mul_lt_mul_of_pos_right h hc + mpr h := by simpa [hc.ne'] using mul_lt_mul_of_pos_right h (inv_pos.2 hc) + +/-- See `lt_div_iff₀'` for a version with multiplication on the other side. -/ +lemma lt_div_iff₀ (hc : 0 < c) : a < b / c ↔ a * c < b := by + rw [div_eq_mul_inv, lt_mul_inv_iff₀ hc] + +/-- See `div_le_iff₀'` for a version with multiplication on the other side. -/ +lemma div_lt_iff₀ (hc : 0 < c) : b / c < a ↔ b < a * c := by + rw [div_eq_mul_inv, mul_inv_lt_iff₀ hc] + +/-- See `inv_lt_iff_one_lt_mul₀'` for a version with multiplication on the other side. -/ +lemma inv_lt_iff_one_lt_mul₀ (ha : 0 < a) : a⁻¹ < b ↔ 1 < b * a := by + rw [← mul_inv_lt_iff₀ ha, one_mul] + +variable [PosMulStrictMono G₀] + +/-- See `inv_strictAnti₀` for the implication from right-to-left with one fewer assumption. -/ +lemma inv_lt_inv₀ (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b⁻¹ ↔ b < a := by + rw [inv_lt_iff_one_lt_mul₀' ha, lt_mul_inv_iff₀ hb, one_mul] + +@[gcongr, bound] +lemma inv_strictAnti₀ (hb : 0 < b) (hba : b < a) : a⁻¹ < b⁻¹ := + (inv_lt_inv₀ (hb.trans hba) hb).2 hba + +/-- See also `inv_lt_of_inv_lt₀` for a one-sided implication with one fewer assumption. -/ +lemma inv_lt_comm₀ (ha : 0 < a) (hb : 0 < b) : a⁻¹ < b ↔ b⁻¹ < a := by + rw [← inv_lt_inv₀ hb (inv_pos.2 ha), inv_inv] + +lemma inv_lt_of_inv_lt₀ (ha : 0 < a) (h : a⁻¹ < b) : b⁻¹ < a := + (inv_lt_comm₀ ha <| (inv_pos.2 ha).trans h).1 h + +/-- See also `lt_inv_of_lt_inv₀` for a one-sided implication with one fewer assumption. -/ +lemma lt_inv_comm₀ (ha : 0 < a) (hb : 0 < b) : a < b⁻¹ ↔ b < a⁻¹ := by + rw [← inv_lt_inv₀ (inv_pos.2 hb) ha, inv_inv] + +lemma lt_inv_of_lt_inv₀ (ha : 0 < a) (h : a < b⁻¹) : b < a⁻¹ := + (lt_inv_comm₀ ha <| inv_pos.1 <| ha.trans h).1 h + +end MulPosStrictMono end PartialOrder section LinearOrder -variable [LinearOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b c : G₀} +variable [LinearOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] {a b : G₀} @[simp] lemma inv_neg'' : a⁻¹ < 0 ↔ a < 0 := by simp only [← not_le, inv_nonneg] @[simp] lemma inv_nonpos : a⁻¹ ≤ 0 ↔ a ≤ 0 := by simp only [← not_lt, inv_pos] @@ -1205,6 +1496,22 @@ lemma one_div_nonpos : 1 / a ≤ 0 ↔ a ≤ 0 := one_div a ▸ inv_nonpos lemma div_nonpos_of_nonneg_of_nonpos [PosMulMono G₀] (ha : 0 ≤ a) (hb : b ≤ 0) : a / b ≤ 0 := by rw [div_eq_mul_inv]; exact mul_nonpos_of_nonneg_of_nonpos ha (inv_nonpos.2 hb) +variable [PosMulStrictMono G₀] {m n : ℤ} + +lemma inv_lt_one_iff₀ : a⁻¹ < 1 ↔ a ≤ 0 ∨ 1 < a := by + simp_rw [← not_le, one_le_inv_iff₀, not_and_or, not_lt] + +lemma inv_le_one_iff₀ : a⁻¹ ≤ 1 ↔ a ≤ 0 ∨ 1 ≤ a := by + simp only [← not_lt, one_lt_inv_iff₀, not_and_or] + +lemma zpow_right_injective₀ (ha₀ : 0 < a) (ha₁ : a ≠ 1) : Injective fun n : ℤ ↦ a ^ n := by + obtain ha₁ | ha₁ := ha₁.lt_or_lt + · exact (zpow_right_strictAnti₀ ha₀ ha₁).injective + · exact (zpow_right_strictMono₀ ha₁).injective + +@[simp] lemma zpow_right_inj₀ (ha₀ : 0 < a) (ha₁ : a ≠ 1) : a ^ m = a ^ n ↔ m = n := + (zpow_right_injective₀ ha₀ ha₁).eq_iff + end GroupWithZero.LinearOrder section CommSemigroupHasZero @@ -1227,22 +1534,97 @@ end CommSemigroupHasZero section CommGroupWithZero variable [CommGroupWithZero G₀] -variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] [MulPosMono G₀] {a b c d : G₀} +variable [PartialOrder G₀] [ZeroLEOneClass G₀] [PosMulReflectLT G₀] + +section PosMulMono +variable [PosMulMono G₀] {a b c d : G₀} + +/-- See `le_inv_mul_iff₀` for a version with multiplication on the other side. -/ +lemma le_inv_mul_iff₀' (hc : 0 < c) : a ≤ c⁻¹ * b ↔ c * a ≤ b := by + rw [le_inv_mul_iff₀ hc, mul_comm] + +/-- See `inv_mul_le_iff₀` for a version with multiplication on the other side. -/ +lemma inv_mul_le_iff₀' (hc : 0 < c) : c⁻¹ * b ≤ a ↔ b ≤ a * c := by + rw [inv_mul_le_iff₀ hc, mul_comm] + +/-- See `le_mul_inv_iff₀` for a version with multiplication on the other side. -/ +lemma le_mul_inv_iff₀' (hc : 0 < c) : a ≤ b * c⁻¹ ↔ c * a ≤ b := by + have := posMulMono_iff_mulPosMono.1 ‹_› + rw [le_mul_inv_iff₀ hc, mul_comm] + +/-- See `mul_inv_le_iff₀` for a version with multiplication on the other side. -/ +lemma mul_inv_le_iff₀' (hc : 0 < c) : b * c⁻¹ ≤ a ↔ b ≤ c * a := by + have := posMulMono_iff_mulPosMono.1 ‹_› + rw [mul_inv_le_iff₀ hc, mul_comm] lemma div_le_div₀ (hb : 0 < b) (hd : 0 < d) : a / b ≤ c / d ↔ a * d ≤ c * b := by + have := posMulMono_iff_mulPosMono.1 ‹_› rw [div_le_iff₀ hb, ← mul_div_right_comm, le_div_iff₀ hd] -lemma le_div_iff₀' (hc : 0 < c) : a ≤ b / c ↔ c * a ≤ b := by rw [le_div_iff₀ hc, mul_comm] -lemma div_le_iff₀' (hc : 0 < c) : b / c ≤ a ↔ b ≤ c * a := by rw [div_le_iff₀ hc, mul_comm] +/-- See `le_div_iff₀` for a version with multiplication on the other side. -/ +lemma le_div_iff₀' (hc : 0 < c) : a ≤ b / c ↔ c * a ≤ b := by + have := posMulMono_iff_mulPosMono.1 ‹_› + rw [le_div_iff₀ hc, mul_comm] + +/-- See `div_le_iff₀` for a version with multiplication on the other side. -/ +lemma div_le_iff₀' (hc : 0 < c) : b / c ≤ a ↔ b ≤ c * a := by + have := posMulMono_iff_mulPosMono.1 ‹_› + rw [div_le_iff₀ hc, mul_comm] lemma le_div_comm₀ (ha : 0 < a) (hc : 0 < c) : a ≤ b / c ↔ c ≤ b / a := by + have := posMulMono_iff_mulPosMono.1 ‹_› rw [le_div_iff₀ ha, le_div_iff₀' hc] lemma div_le_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b ≤ c ↔ a / c ≤ b := by + have := posMulMono_iff_mulPosMono.1 ‹_› rw [div_le_iff₀ hb, div_le_iff₀' hc] @[deprecated (since := "2024-08-21")] alias le_div_iff' := le_div_iff₀' @[deprecated (since := "2024-08-21")] alias div_le_iff' := div_le_iff₀' +end PosMulMono + +section PosMulStrictMono +variable [PosMulStrictMono G₀] {a b c : G₀} + +/-- See `lt_inv_mul_iff₀` for a version with multiplication on the other side. -/ +lemma lt_inv_mul_iff₀' (hc : 0 < c) : a < c⁻¹ * b ↔ a * c < b := by + rw [lt_inv_mul_iff₀ hc, mul_comm] + +/-- See `inv_mul_lt_iff₀` for a version with multiplication on the other side. -/ +lemma inv_mul_lt_iff₀' (hc : 0 < c) : c⁻¹ * b < a ↔ b < a * c := by + rw [inv_mul_lt_iff₀ hc, mul_comm] + +/-- See `lt_mul_inv_iff₀` for a version with multiplication on the other side. -/ +lemma lt_mul_inv_iff₀' (hc : 0 < c) : a < b * c⁻¹ ↔ c * a < b := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [lt_mul_inv_iff₀ hc, mul_comm] + +/-- See `mul_inv_lt_iff₀` for a version with multiplication on the other side. -/ +lemma mul_inv_lt_iff₀' (hc : 0 < c) : b * c⁻¹ < a ↔ b < c * a := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [mul_inv_lt_iff₀ hc, mul_comm] + +/-- See `lt_div_iff₀` for a version with multiplication on the other side. -/ +lemma lt_div_iff₀' (hc : 0 < c) : a < b / c ↔ c * a < b := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [lt_div_iff₀ hc, mul_comm] + +/-- See `div_lt_iff₀` for a version with multiplication on the other side. -/ +lemma div_lt_iff₀' (hc : 0 < c) : b / c < a ↔ b < c * a := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [div_lt_iff₀ hc, mul_comm] + +lemma lt_div_comm₀ (ha : 0 < a) (hc : 0 < c) : a < b / c ↔ c < b / a := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [lt_div_iff₀ ha, lt_div_iff₀' hc] + +lemma div_lt_comm₀ (hb : 0 < b) (hc : 0 < c) : a / b < c ↔ a / c < b := by + have := posMulStrictMono_iff_mulPosStrictMono.1 ‹_› + rw [div_lt_iff₀ hb, div_lt_iff₀' hc] + +end PosMulStrictMono end CommGroupWithZero + +set_option linter.style.longFile 1700 diff --git a/Mathlib/Algebra/Order/GroupWithZero/Unbundled/Lemmas.lean b/Mathlib/Algebra/Order/GroupWithZero/Unbundled/Lemmas.lean new file mode 100644 index 0000000000000..edc0cb47b953d --- /dev/null +++ b/Mathlib/Algebra/Order/GroupWithZero/Unbundled/Lemmas.lean @@ -0,0 +1,27 @@ +/- +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.Group.Pi.Basic +import Mathlib.Algebra.Order.GroupWithZero.Unbundled +import Mathlib.Algebra.GroupWithZero.Units.Equiv +import Mathlib.Order.Hom.Basic + +/-! +# Multiplication by a positive element as an order isomorphism +-/ + +variable {G₀} [GroupWithZero G₀] [Preorder G₀] [ZeroLEOneClass G₀] {a b c d : G₀} + +/-- `Equiv.mulLeft₀` as an order isomorphism. -/ +@[simps! (config := { simpRhs := true })] +def OrderIso.mulLeft₀ [PosMulMono G₀] [PosMulReflectLE G₀] (a : G₀) (ha : 0 < a) : G₀ ≃o G₀ where + toEquiv := .mulLeft₀ a ha.ne' + map_rel_iff' := mul_le_mul_left ha + +/-- `Equiv.mulRight₀` as an order isomorphism. -/ +@[simps! (config := { simpRhs := true })] +def OrderIso.mulRight₀ [MulPosMono G₀] [MulPosReflectLE G₀] (a : G₀) (ha : 0 < a) : G₀ ≃o G₀ where + toEquiv := .mulRight₀ a ha.ne' + map_rel_iff' := mul_le_mul_right ha diff --git a/Mathlib/Algebra/Order/Hom/Basic.lean b/Mathlib/Algebra/Order/Hom/Basic.lean index dbcb880887ff3..b97b19b03d22d 100644 --- a/Mathlib/Algebra/Order/Hom/Basic.lean +++ b/Mathlib/Algebra/Order/Hom/Basic.lean @@ -73,29 +73,33 @@ variable {ι F α β γ δ : Type*} /-! ### Basics -/ /-- `NonnegHomClass F α β` states that `F` is a type of nonnegative morphisms. -/ -class NonnegHomClass (F α β : Type*) [Zero β] [LE β] [FunLike F α β] : Prop where +class NonnegHomClass (F : Type*) (α β : outParam Type*) [Zero β] [LE β] [FunLike F α β] : Prop where /-- the image of any element is non negative. -/ apply_nonneg (f : F) : ∀ a, 0 ≤ f a /-- `SubadditiveHomClass F α β` states that `F` is a type of subadditive morphisms. -/ -class SubadditiveHomClass (F α β : Type*) [Add α] [Add β] [LE β] [FunLike F α β] : Prop where +class SubadditiveHomClass (F : Type*) (α β : outParam Type*) + [Add α] [Add β] [LE β] [FunLike F α β] : Prop 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 /-- `SubmultiplicativeHomClass F α β` states that `F` is a type of submultiplicative morphisms. -/ @[to_additive SubadditiveHomClass] -class SubmultiplicativeHomClass (F α β : Type*) [Mul α] [Mul β] [LE β] [FunLike F α β] : Prop where +class SubmultiplicativeHomClass (F : Type*) (α β : outParam (Type*)) [Mul α] [Mul β] [LE β] + [FunLike F α β] : Prop 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 /-- `MulLEAddHomClass F α β` states that `F` is a type of subadditive morphisms. -/ @[to_additive SubadditiveHomClass] -class MulLEAddHomClass (F α β : Type*) [Mul α] [Add β] [LE β] [FunLike F α β] : Prop where +class MulLEAddHomClass (F : Type*) (α β : outParam Type*) [Mul α] [Add β] [LE β] [FunLike F α β] : + Prop 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 /-- `NonarchimedeanHomClass F α β` states that `F` is a type of non-archimedean morphisms. -/ -class NonarchimedeanHomClass (F α β : Type*) [Add α] [LinearOrder β] [FunLike F α β] : Prop where +class NonarchimedeanHomClass (F : Type*) (α β : outParam Type*) + [Add α] [LinearOrder β] [FunLike F α β] : Prop 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) @@ -154,7 +158,8 @@ end Mathlib.Meta.Positivity group `α`. You should extend this class when you extend `AddGroupSeminorm`. -/ -class AddGroupSeminormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β] +class AddGroupSeminormClass (F : Type*) (α β : outParam Type*) + [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β] extends SubadditiveHomClass F α β : Prop where /-- The image of zero is zero. -/ map_zero (f : F) : f 0 = 0 @@ -165,7 +170,8 @@ class AddGroupSeminormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoi You should extend this class when you extend `GroupSeminorm`. -/ @[to_additive] -class GroupSeminormClass (F α β : Type*) [Group α] [OrderedAddCommMonoid β] [FunLike F α β] +class GroupSeminormClass (F : Type*) (α β : outParam Type*) + [Group α] [OrderedAddCommMonoid β] [FunLike F α β] extends MulLEAddHomClass F α β : Prop where /-- The image of one is zero. -/ map_one_eq_zero (f : F) : f 1 = 0 @@ -176,7 +182,8 @@ class GroupSeminormClass (F α β : Type*) [Group α] [OrderedAddCommMonoid β] `α`. You should extend this class when you extend `AddGroupNorm`. -/ -class AddGroupNormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β] +class AddGroupNormClass (F : Type*) (α β : outParam Type*) + [AddGroup α] [OrderedAddCommMonoid β] [FunLike F α β] extends AddGroupSeminormClass F α β : Prop where /-- The argument is zero if its image under the map is zero. -/ eq_zero_of_map_eq_zero (f : F) {a : α} : f a = 0 → a = 0 @@ -185,7 +192,8 @@ class AddGroupNormClass (F α β : Type*) [AddGroup α] [OrderedAddCommMonoid β You should extend this class when you extend `GroupNorm`. -/ @[to_additive] -class GroupNormClass (F α β : Type*) [Group α] [OrderedAddCommMonoid β] [FunLike F α β] +class GroupNormClass (F : Type*) (α β : outParam Type*) + [Group α] [OrderedAddCommMonoid β] [FunLike F α β] extends GroupSeminormClass F α β : Prop where /-- The argument is one if its image under the map is zero. -/ eq_one_of_map_eq_zero (f : F) {a : α} : f a = 0 → a = 1 @@ -275,20 +283,23 @@ theorem map_pos_of_ne_one [Group α] [LinearOrderedAddCommMonoid β] [GroupNormC /-- `RingSeminormClass F α` states that `F` is a type of `β`-valued seminorms on the ring `α`. You should extend this class when you extend `RingSeminorm`. -/ -class RingSeminormClass (F α β : Type*) [NonUnitalNonAssocRing α] [OrderedSemiring β] - [FunLike F α β] extends AddGroupSeminormClass F α β, SubmultiplicativeHomClass F α β : Prop +class RingSeminormClass (F : Type*) (α β : outParam Type*) + [NonUnitalNonAssocRing α] [OrderedSemiring β] [FunLike F α β] + extends AddGroupSeminormClass F α β, SubmultiplicativeHomClass F α β : Prop /-- `RingNormClass F α` states that `F` is a type of `β`-valued norms on the ring `α`. You should extend this class when you extend `RingNorm`. -/ -class RingNormClass (F α β : Type*) [NonUnitalNonAssocRing α] [OrderedSemiring β] [FunLike F α β] +class RingNormClass (F : Type*) (α β : outParam Type*) + [NonUnitalNonAssocRing α] [OrderedSemiring β] [FunLike F α β] extends RingSeminormClass F α β, AddGroupNormClass F α β : Prop /-- `MulRingSeminormClass F α` states that `F` is a type of `β`-valued multiplicative seminorms on the ring `α`. You should extend this class when you extend `MulRingSeminorm`. -/ -class MulRingSeminormClass (F α β : Type*) [NonAssocRing α] [OrderedSemiring β] [FunLike F α β] +class MulRingSeminormClass (F : Type*) (α β : outParam Type*) + [NonAssocRing α] [OrderedSemiring β] [FunLike F α β] extends AddGroupSeminormClass F α β, MonoidWithZeroHomClass F α β : Prop -- Lower the priority of these instances since they require synthesizing an order structure. @@ -299,7 +310,8 @@ attribute [instance 50] ring `α`. You should extend this class when you extend `MulRingNorm`. -/ -class MulRingNormClass (F α β : Type*) [NonAssocRing α] [OrderedSemiring β] [FunLike F α β] +class MulRingNormClass (F : Type*) (α β : outParam Type*) + [NonAssocRing α] [OrderedSemiring β] [FunLike F α β] extends MulRingSeminormClass F α β, AddGroupNormClass F α β : Prop -- See note [out-param inheritance] diff --git a/Mathlib/Algebra/Order/Interval/Basic.lean b/Mathlib/Algebra/Order/Interval/Basic.lean index 53c70afe40a7b..dcd8a5d261e09 100644 --- a/Mathlib/Algebra/Order/Interval/Basic.lean +++ b/Mathlib/Algebra/Order/Interval/Basic.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.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Order.Interval.Basic diff --git a/Mathlib/Algebra/Order/Interval/Set/Instances.lean b/Mathlib/Algebra/Order/Interval/Set/Instances.lean index 74e41d229a3ff..4624971afef4b 100644 --- a/Mathlib/Algebra/Order/Interval/Set/Instances.lean +++ b/Mathlib/Algebra/Order/Interval/Set/Instances.lean @@ -3,7 +3,8 @@ Copyright (c) 2022 Stuart Presnell. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Stuart Presnell, Eric Wieser, Yaël Dillies, Patrick Massot, Kim Morrison -/ -import Mathlib.Algebra.Order.Ring.Basic +import Mathlib.Algebra.GroupWithZero.InjSurj +import Mathlib.Algebra.Order.Ring.Defs import Mathlib.Algebra.Ring.Regular import Mathlib.Order.Interval.Set.Basic @@ -98,10 +99,10 @@ theorem le_one {t : Icc (0 : α) 1} : t ≤ 1 := t.2.2 instance mul : Mul (Icc (0 : α) 1) where - mul p q := ⟨p * q, ⟨mul_nonneg p.2.1 q.2.1, mul_le_one p.2.2 q.2.1 q.2.2⟩⟩ + mul p q := ⟨p * q, ⟨mul_nonneg p.2.1 q.2.1, mul_le_one₀ p.2.2 q.2.1 q.2.2⟩⟩ instance pow : Pow (Icc (0 : α) 1) ℕ where - pow p n := ⟨p.1 ^ n, ⟨pow_nonneg p.2.1 n, pow_le_one n p.2.1 p.2.2⟩⟩ + pow p n := ⟨p.1 ^ n, ⟨pow_nonneg p.2.1 n, pow_le_one₀ p.2.1 p.2.2⟩⟩ @[simp, norm_cast] theorem coe_mul (x y : Icc (0 : α) 1) : ↑(x * y) = (x * y : α) := @@ -236,10 +237,10 @@ theorem le_one {t : Ioc (0 : α) 1} : t ≤ 1 := t.2.2 instance mul : Mul (Ioc (0 : α) 1) where - mul p q := ⟨p.1 * q.1, ⟨mul_pos p.2.1 q.2.1, mul_le_one p.2.2 (le_of_lt q.2.1) q.2.2⟩⟩ + mul p q := ⟨p.1 * q.1, ⟨mul_pos p.2.1 q.2.1, mul_le_one₀ p.2.2 (le_of_lt q.2.1) q.2.2⟩⟩ instance pow : Pow (Ioc (0 : α) 1) ℕ where - pow p n := ⟨p.1 ^ n, ⟨pow_pos p.2.1 n, pow_le_one n (le_of_lt p.2.1) p.2.2⟩⟩ + pow p n := ⟨p.1 ^ n, ⟨pow_pos p.2.1 n, pow_le_one₀ (le_of_lt p.2.1) p.2.2⟩⟩ @[simp, norm_cast] theorem coe_mul (x y : Ioc (0 : α) 1) : ↑(x * y) = (x * y : α) := diff --git a/Mathlib/Algebra/Order/Kleene.lean b/Mathlib/Algebra/Order/Kleene.lean index 064a1499bf6bf..08c772b601a9e 100644 --- a/Mathlib/Algebra/Order/Kleene.lean +++ b/Mathlib/Algebra/Order/Kleene.lean @@ -321,7 +321,7 @@ protected abbrev idemSemiring [IdemSemiring α] [Zero β] [One β] [Add β] [Mul IdemSemiring β := { hf.semiring f zero one add mul nsmul npow natCast, hf.semilatticeSup _ sup, ‹Bot β› with - add_eq_sup := fun a b ↦ hf <| by erw [sup, add, add_eq_sup] + add_eq_sup := fun a b ↦ hf <| by rw [sup, add, add_eq_sup] bot := ⊥ bot_le := fun a ↦ bot.trans_le <| @bot_le _ _ _ <| f a } @@ -347,25 +347,25 @@ protected abbrev kleeneAlgebra [KleeneAlgebra α] [Zero β] [One β] [Add β] [M { hf.idemSemiring f zero one add mul nsmul npow natCast sup bot, ‹KStar β› with one_le_kstar := fun a ↦ one.trans_le <| by - erw [kstar] + rw [kstar] exact one_le_kstar mul_kstar_le_kstar := fun a ↦ by change f _ ≤ _ - erw [mul, kstar] + rw [mul, kstar] exact mul_kstar_le_kstar kstar_mul_le_kstar := fun a ↦ by change f _ ≤ _ - erw [mul, kstar] + rw [mul, kstar] exact kstar_mul_le_kstar mul_kstar_le_self := fun a b (h : f _ ≤ _) ↦ by change f _ ≤ _ - erw [mul, kstar] - erw [mul] at h + rw [mul, kstar] + rw [mul] at h exact mul_kstar_le_self h kstar_mul_le_self := fun a b (h : f _ ≤ _) ↦ by change f _ ≤ _ - erw [mul, kstar] - erw [mul] at h + rw [mul, kstar] + rw [mul] at h exact kstar_mul_le_self h } end Function.Injective diff --git a/Mathlib/Algebra/Order/Module/Defs.lean b/Mathlib/Algebra/Order/Module/Defs.lean index 0b51dcd81ec13..8323669b29434 100644 --- a/Mathlib/Algebra/Order/Module/Defs.lean +++ b/Mathlib/Algebra/Order/Module/Defs.lean @@ -1198,46 +1198,3 @@ def evalHSMul : PositivityExt where eval {_u α} zα pα (e : Q($α)) := do | _, _ => pure .none end Mathlib.Meta.Positivity - -/-! -### Deprecated lemmas - -Those lemmas have been deprecated on 2023-12-23. --/ - -@[deprecated (since := "2023-12-23")] alias monotone_smul_left := monotone_smul_left_of_nonneg -@[deprecated (since := "2023-12-23")] alias strict_mono_smul_left := strictMono_smul_left_of_pos -@[deprecated (since := "2023-12-23")] alias smul_le_smul_of_nonneg := smul_le_smul_of_nonneg_left -@[deprecated (since := "2023-12-23")] alias smul_lt_smul_of_pos := smul_lt_smul_of_pos_left - -@[deprecated (since := "2023-12-23")] -alias lt_of_smul_lt_smul_of_nonneg := lt_of_smul_lt_smul_of_nonneg_left - -@[deprecated (since := "2023-12-23")] alias smul_le_smul_iff_of_pos := smul_le_smul_iff_of_pos_left -@[deprecated (since := "2023-12-23")] alias smul_lt_smul_iff_of_pos := smul_lt_smul_iff_of_pos_left -@[deprecated (since := "2023-12-23")] alias smul_max := smul_max_of_nonneg -@[deprecated (since := "2023-12-23")] alias smul_min := smul_min_of_nonneg -@[deprecated (since := "2023-12-23")] alias smul_pos_iff_of_pos := smul_pos_iff_of_pos_left -@[deprecated (since := "2023-12-23")] alias inv_smul_le_iff := inv_smul_le_iff_of_pos -@[deprecated (since := "2023-12-23")] alias le_inv_smul_iff := le_inv_smul_iff_of_pos -@[deprecated (since := "2023-12-23")] alias inv_smul_lt_iff := inv_smul_lt_iff_of_pos -@[deprecated (since := "2023-12-23")] alias lt_inv_smul_iff := lt_inv_smul_iff_of_pos -@[deprecated (since := "2023-12-23")] alias OrderIso.smulLeft := OrderIso.smulRight - -@[deprecated (since := "2023-12-23")] -alias OrderIso.smulLeft_symm_apply := OrderIso.smulRight_symm_apply - -@[deprecated (since := "2023-12-23")] alias OrderIso.smulLeft_apply := OrderIso.smulRight_apply -@[deprecated (since := "2023-12-23")] alias smul_neg_iff_of_pos := smul_neg_iff_of_pos_left - -/-! -Those lemmas have been deprecated on 2023-12-27. --/ - -@[deprecated (since := "2023-12-27")] alias strict_anti_smul_left := strictAnti_smul_left -@[deprecated (since := "2023-12-27")] alias smul_le_smul_of_nonpos := smul_le_smul_of_nonpos_left -@[deprecated (since := "2023-12-27")] alias smul_lt_smul_of_neg := smul_lt_smul_of_neg_left -@[deprecated (since := "2023-12-27")] alias smul_pos_iff_of_neg := smul_pos_iff_of_neg_left -@[deprecated (since := "2023-12-27")] alias smul_neg_iff_of_neg := smul_neg_iff_of_neg_left -@[deprecated (since := "2023-12-27")] alias smul_le_smul_iff_of_neg := smul_le_smul_iff_of_neg_left -@[deprecated (since := "2023-12-27")] alias smul_lt_smul_iff_of_neg := smul_lt_smul_iff_of_neg_left diff --git a/Mathlib/Algebra/Order/Module/Pointwise.lean b/Mathlib/Algebra/Order/Module/Pointwise.lean index a8bede48a1df5..147291c9cdcef 100644 --- a/Mathlib/Algebra/Order/Module/Pointwise.lean +++ b/Mathlib/Algebra/Order/Module/Pointwise.lean @@ -3,7 +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.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.Module.Defs import Mathlib.Order.Bounds.OrderIso diff --git a/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean b/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean new file mode 100644 index 0000000000000..6005ed71ee499 --- /dev/null +++ b/Mathlib/Algebra/Order/Monoid/Canonical/Basic.lean @@ -0,0 +1,19 @@ +/- +Copyright (c) 2024 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.Monoid.Canonical.Defs +import Mathlib.Data.Finset.Lattice + +/-! +# Extra lemmas about canonically ordered monoids +-/ + +namespace Finset +variable {ι α : Type*} [CanonicallyLinearOrderedAddCommMonoid α] {s : Finset ι} {f : ι → α} + +@[simp] lemma sup_eq_zero : s.sup f = 0 ↔ ∀ i ∈ s, f i = 0 := by simp [← bot_eq_zero'] +@[simp] lemma sup'_eq_zero (hs) : s.sup' hs f = 0 ↔ ∀ i ∈ s, f i = 0 := by simp [sup'_eq_sup] + +end Finset diff --git a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean index 6e2104c91ef78..7cf5e1c4143ca 100644 --- a/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Canonical/Defs.lean @@ -58,7 +58,7 @@ instance (priority := 100) CanonicallyOrderedCommMonoid.existsMulOfLE (α : Type section CanonicallyOrderedCommMonoid -variable [CanonicallyOrderedCommMonoid α] {a b c d : α} +variable [CanonicallyOrderedCommMonoid α] {a b c : α} @[to_additive] theorem le_self_mul : a ≤ a * c := diff --git a/Mathlib/Algebra/Order/Monoid/Defs.lean b/Mathlib/Algebra/Order/Monoid/Defs.lean index 3e9fcaaa3a139..61e8c9e8a30d9 100644 --- a/Mathlib/Algebra/Order/Monoid/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Defs.lean @@ -15,7 +15,7 @@ This file provides the definitions of ordered monoids. open Function -variable {α β : Type*} +variable {α : Type*} /-- An ordered (additive) commutative monoid is a commutative monoid with a partial order such that addition is monotone. -/ diff --git a/Mathlib/Algebra/Order/Monoid/Prod.lean b/Mathlib/Algebra/Order/Monoid/Prod.lean index c6998f304353c..e3d9ab5369849 100644 --- a/Mathlib/Algebra/Order/Monoid/Prod.lean +++ b/Mathlib/Algebra/Order/Monoid/Prod.lean @@ -40,7 +40,7 @@ instance [CanonicallyOrderedCommMonoid α] [CanonicallyOrderedCommMonoid β] : CanonicallyOrderedCommMonoid (α × β) := { (inferInstance : OrderedCommMonoid _), (inferInstance : OrderBot _), (inferInstance : ExistsMulOfLE _) with - le_self_mul := fun _ _ ↦ ⟨le_self_mul, le_self_mul⟩ } + le_self_mul := fun _ _ ↦ le_def.mpr ⟨le_self_mul, le_self_mul⟩ } namespace Lex diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean index d6509bd4ccb64..f33502550e3da 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Basic.lean @@ -1289,7 +1289,7 @@ theorem Contravariant.MulLECancellable [Mul α] [LE α] [ContravariantClass α MulLECancellable a := fun _ _ => le_of_mul_le_mul_left' -@[to_additive] +@[to_additive (attr := simp)] theorem mulLECancellable_one [Monoid α] [LE α] : MulLECancellable (1 : α) := fun a b => by simpa only [one_mul] using id @@ -1350,4 +1350,20 @@ protected theorem mul_le_iff_le_one_left [MulOneClass α] [i : @Std.Commutative [CovariantClass α α (· * ·) (· ≤ ·)] {a b : α} (ha : MulLECancellable a) : b * a ≤ a ↔ b ≤ 1 := by rw [i.comm, ha.mul_le_iff_le_one_right] +@[to_additive] lemma mul [Semigroup α] {a b : α} (ha : MulLECancellable a) + (hb : MulLECancellable b) : MulLECancellable (a * b) := + fun c d hcd ↦ hb <| ha <| by rwa [← mul_assoc, ← mul_assoc] + +@[to_additive] lemma of_mul_right [Semigroup α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b : α} + (h : MulLECancellable (a * b)) : MulLECancellable b := + fun c d hcd ↦ h <| by rw [mul_assoc, mul_assoc]; exact mul_le_mul_left' hcd _ + +@[to_additive] lemma of_mul_left [CommSemigroup α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b : α} + (h : MulLECancellable (a * b)) : MulLECancellable a := (mul_comm a b ▸ h).of_mul_right + end MulLECancellable + +@[to_additive (attr := simp)] +lemma mulLECancellable_mul [LE α] [CommSemigroup α] [CovariantClass α α (· * ·) (· ≤ ·)] {a b : α} : + MulLECancellable (a * b) ↔ MulLECancellable a ∧ MulLECancellable b := + ⟨fun h ↦ ⟨h.of_mul_left, h.of_mul_right⟩, fun h ↦ h.1.mul h.2⟩ diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean index c6b6740ff867f..6418be782db5c 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Defs.lean @@ -328,7 +328,7 @@ theorem Group.mulRightReflectLT_of_mulRightStrictMono [Group N] [LT N] section Trans -variable [IsTrans N r] (m n : M) {a b c d : N} +variable [IsTrans N r] (m : M) {a b c : N} -- Lemmas with 3 elements. theorem act_rel_of_rel_of_act_rel (ab : r a b) (rl : r (μ m b) c) : r (μ m a) c := @@ -361,7 +361,7 @@ theorem rel_of_act_rel_act (m : M) {a b : N} (ab : r (μ m a) (μ m b)) : r a b section Trans -variable [IsTrans N r] (m n : M) {a b c d : N} +variable [IsTrans N r] (m : M) {a b c : N} -- Lemmas with 3 elements. theorem act_rel_of_act_rel_of_rel_act_rel (ab : r (μ m a) b) (rl : r (μ m b) (μ m c)) : diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean index 11972efe4bd7d..eb892cfeda6b8 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/Pow.lean @@ -26,7 +26,7 @@ variable [Preorder M] namespace Left -variable [CovariantClass M M (· * ·) (· ≤ ·)] {a b : M} +variable [CovariantClass M M (· * ·) (· ≤ ·)] {a : M} @[to_additive Left.nsmul_nonneg] theorem one_le_pow_of_le (ha : 1 ≤ a) : ∀ n : ℕ, 1 ≤ a ^ n @@ -58,7 +58,7 @@ end Left section Left -variable [CovariantClass M M (· * ·) (· ≤ ·)] {x : M} +variable [CovariantClass M M (· * ·) (· ≤ ·)] @[to_additive nsmul_left_monotone] theorem pow_right_monotone {a : M} (ha : 1 ≤ a) : Monotone fun n : ℕ ↦ a ^ n := @@ -281,39 +281,3 @@ theorem one_le_zpow {x : G} (H : 1 ≤ x) {n : ℤ} (hn : 0 ≤ n) : 1 ≤ x ^ n apply one_le_pow_of_one_le' H end DivInvMonoid - -/-! -### Deprecated lemmas - -Those lemmas have been deprecated on 2023-12-23. --/ - -@[deprecated (since := "2023-12-23")] alias pow_le_pow_of_le_left' := pow_le_pow_left' -@[deprecated (since := "2023-12-23")] alias nsmul_le_nsmul_of_le_right := nsmul_le_nsmul_right -@[deprecated (since := "2023-12-23")] alias pow_lt_pow' := pow_lt_pow_right' -@[deprecated (since := "2023-12-23")] alias nsmul_lt_nsmul := nsmul_lt_nsmul_left -@[deprecated (since := "2023-12-23")] alias pow_strictMono_left := pow_right_strictMono' -@[deprecated (since := "2023-12-23")] alias nsmul_strictMono_right := nsmul_left_strictMono -@[deprecated (since := "2023-12-23")] alias StrictMono.pow_right' := StrictMono.pow_const -@[deprecated (since := "2023-12-23")] alias StrictMono.nsmul_left := StrictMono.const_nsmul -@[deprecated (since := "2023-12-23")] alias pow_strictMono_right' := pow_left_strictMono -@[deprecated (since := "2023-12-23")] alias nsmul_strictMono_left := nsmul_right_strictMono -@[deprecated (since := "2023-12-23")] alias Monotone.pow_right := Monotone.pow_const -@[deprecated (since := "2023-12-23")] alias Monotone.nsmul_left := Monotone.const_nsmul -@[deprecated (since := "2023-12-23")] alias lt_of_pow_lt_pow' := lt_of_pow_lt_pow_left' -@[deprecated (since := "2023-12-23")] alias lt_of_nsmul_lt_nsmul := lt_of_nsmul_lt_nsmul_right -@[deprecated (since := "2023-12-23")] alias pow_le_pow' := pow_le_pow_right' -@[deprecated (since := "2023-12-23")] alias nsmul_le_nsmul := nsmul_le_nsmul_left -@[deprecated (since := "2023-12-23")] alias pow_le_pow_of_le_one' := pow_le_pow_right_of_le_one' - -@[deprecated (since := "2023-12-23")] -alias nsmul_le_nsmul_of_nonpos := nsmul_le_nsmul_left_of_nonpos - -@[deprecated (since := "2023-12-23")] alias le_of_pow_le_pow' := le_of_pow_le_pow_left' -@[deprecated (since := "2023-12-23")] alias le_of_nsmul_le_nsmul := le_of_nsmul_le_nsmul_right -@[deprecated (since := "2023-12-23")] alias pow_le_pow_iff' := pow_le_pow_iff_right' -@[deprecated (since := "2023-12-23")] alias nsmul_le_nsmul_iff := nsmul_le_nsmul_iff_left -@[deprecated (since := "2023-12-23")] alias pow_lt_pow_iff' := pow_lt_pow_iff_right' -@[deprecated (since := "2023-12-23")] alias nsmul_lt_nsmul_iff := nsmul_lt_nsmul_iff_left -@[deprecated (since := "2023-12-23")] alias pow_mono_right := pow_left_mono -@[deprecated (since := "2023-12-23")] alias nsmul_mono_left := nsmul_right_mono diff --git a/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean b/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean index 7d7bdb4f2ff25..0b75be72f5aaf 100644 --- a/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean +++ b/Mathlib/Algebra/Order/Monoid/Unbundled/WithTop.lean @@ -80,7 +80,7 @@ end One section Add -variable [Add α] {a b c d : WithTop α} {x y : α} +variable [Add α] {a b c d : WithTop α} {x : α} instance add : Add (WithTop α) := ⟨Option.map₂ (· + ·)⟩ diff --git a/Mathlib/Algebra/Order/Monovary.lean b/Mathlib/Algebra/Order/Monovary.lean index f742a97bcf60e..e085b565b3140 100644 --- a/Mathlib/Algebra/Order/Monovary.lean +++ b/Mathlib/Algebra/Order/Monovary.lean @@ -238,19 +238,19 @@ variable [LinearOrderedSemifield α] [LinearOrderedSemifield β] {s : Set ι} {f @[simp] lemma monovaryOn_inv_left₀ (hf : ∀ i ∈ s, 0 < f i) : MonovaryOn f⁻¹ g s ↔ AntivaryOn f g s := - forall₅_congr fun _i hi _j hj _ ↦ inv_le_inv (hf _ hi) (hf _ hj) + forall₅_congr fun _i hi _j hj _ ↦ inv_le_inv₀ (hf _ hi) (hf _ hj) @[simp] lemma antivaryOn_inv_left₀ (hf : ∀ i ∈ s, 0 < f i) : AntivaryOn f⁻¹ g s ↔ MonovaryOn f g s := - forall₅_congr fun _i hi _j hj _ ↦ inv_le_inv (hf _ hj) (hf _ hi) + forall₅_congr fun _i hi _j hj _ ↦ inv_le_inv₀ (hf _ hj) (hf _ hi) @[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 @@ -260,16 +260,16 @@ lemma antivaryOn_inv₀ (hf : ∀ i ∈ s, 0 < f i) (hg : ∀ i ∈ s, 0 < g i) rw [antivaryOn_inv_left₀ hf, monovaryOn_inv_right₀ hg] @[simp] lemma monovary_inv_left₀ (hf : StrongLT 0 f) : Monovary f⁻¹ g ↔ Antivary f g := - forall₃_congr fun _i _j _ ↦ inv_le_inv (hf _) (hf _) + forall₃_congr fun _i _j _ ↦ inv_le_inv₀ (hf _) (hf _) @[simp] lemma antivary_inv_left₀ (hf : StrongLT 0 f) : Antivary f⁻¹ g ↔ Monovary f g := - forall₃_congr fun _i _j _ ↦ inv_le_inv (hf _) (hf _) + 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] diff --git a/Mathlib/Algebra/Order/Pi.lean b/Mathlib/Algebra/Order/Pi.lean index be50955c5d5ae..9710857e2382b 100644 --- a/Mathlib/Algebra/Order/Pi.lean +++ b/Mathlib/Algebra/Order/Pi.lean @@ -128,6 +128,25 @@ variable [One γ] [LE γ] {f : α → β} {g : α → γ} {e : β → γ} end extend end Function + +namespace Pi +variable {ι : Type*} {α : ι → Type*} [DecidableEq ι] [∀ i, One (α i)] [∀ i, Preorder (α i)] {i : ι} + {a b : α i} + +@[to_additive (attr := simp)] +lemma mulSingle_le_mulSingle : mulSingle i a ≤ mulSingle i b ↔ a ≤ b := by + simp [mulSingle, update_le_update_iff] + +@[to_additive (attr := gcongr)] alias ⟨_, GCongr.mulSingle_mono⟩ := mulSingle_le_mulSingle + +@[to_additive (attr := simp) single_nonneg] +lemma one_le_mulSingle : 1 ≤ mulSingle i a ↔ 1 ≤ a := by simp [mulSingle] + +@[to_additive (attr := simp)] +lemma mulSingle_le_one : mulSingle i a ≤ 1 ↔ a ≤ 1 := by simp [mulSingle] + +end Pi + -- Porting note: Tactic code not ported yet -- namespace Tactic diff --git a/Mathlib/Algebra/Order/Pointwise.lean b/Mathlib/Algebra/Order/Pointwise.lean deleted file mode 100644 index 5a6d4539414dd..0000000000000 --- a/Mathlib/Algebra/Order/Pointwise.lean +++ /dev/null @@ -1,250 +0,0 @@ -/- -Copyright (c) 2021 Alex J. Best. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Alex J. Best, Yaël Dillies --/ -import Mathlib.Algebra.Bounds -import Mathlib.Algebra.Order.Field.Basic -- Porting note: `LinearOrderedField`, etc -import Mathlib.Algebra.SMulWithZero - -/-! -# Pointwise operations on ordered algebraic objects - -This file contains lemmas about the effect of pointwise operations on sets with an order structure. - -## TODO - -`sSup (s • t) = sSup s • sSup t` and `sInf (s • t) = sInf s • sInf t` hold as well but -`CovariantClass` is currently not polymorphic enough to state it. --/ - - -open Function Set - -open Pointwise - -variable {α : Type*} - --- Porting note: Swapped the place of `CompleteLattice` and `ConditionallyCompleteLattice` --- due to simpNF problem between `sSup_xx` `csSup_xx`. - -section CompleteLattice - -variable [CompleteLattice α] - -section One - -variable [One α] - -@[to_additive (attr := simp)] -theorem sSup_one : sSup (1 : Set α) = 1 := - sSup_singleton - -@[to_additive (attr := simp)] -theorem sInf_one : sInf (1 : Set α) = 1 := - sInf_singleton - -end One - -section Group - -variable [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - (s t : Set α) - -@[to_additive] -theorem sSup_inv (s : Set α) : sSup s⁻¹ = (sInf s)⁻¹ := by - rw [← image_inv, sSup_image] - exact ((OrderIso.inv α).map_sInf _).symm - -@[to_additive] -theorem sInf_inv (s : Set α) : sInf s⁻¹ = (sSup s)⁻¹ := by - rw [← image_inv, sInf_image] - exact ((OrderIso.inv α).map_sSup _).symm - -@[to_additive] -theorem sSup_mul : sSup (s * t) = sSup s * sSup t := - (sSup_image2_eq_sSup_sSup fun _ => (OrderIso.mulRight _).to_galoisConnection) fun _ => - (OrderIso.mulLeft _).to_galoisConnection - -@[to_additive] -theorem sInf_mul : sInf (s * t) = sInf s * sInf t := - (sInf_image2_eq_sInf_sInf fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) fun _ => - (OrderIso.mulLeft _).symm.to_galoisConnection - -@[to_additive] -theorem sSup_div : sSup (s / t) = sSup s / sInf t := by simp_rw [div_eq_mul_inv, sSup_mul, sSup_inv] - -@[to_additive] -theorem sInf_div : sInf (s / t) = sInf s / sSup t := by simp_rw [div_eq_mul_inv, sInf_mul, sInf_inv] - -end Group - -end CompleteLattice - -section ConditionallyCompleteLattice - -variable [ConditionallyCompleteLattice α] - -section One - -variable [One α] - -@[to_additive (attr := simp)] -theorem csSup_one : sSup (1 : Set α) = 1 := - csSup_singleton _ - -@[to_additive (attr := simp)] -theorem csInf_one : sInf (1 : Set α) = 1 := - csInf_singleton _ - -end One - -section Group - -variable [Group α] [CovariantClass α α (· * ·) (· ≤ ·)] [CovariantClass α α (swap (· * ·)) (· ≤ ·)] - {s t : Set α} - -@[to_additive] -theorem csSup_inv (hs₀ : s.Nonempty) (hs₁ : BddBelow s) : sSup s⁻¹ = (sInf s)⁻¹ := by - rw [← image_inv] - exact ((OrderIso.inv α).map_csInf' hs₀ hs₁).symm - -@[to_additive] -theorem csInf_inv (hs₀ : s.Nonempty) (hs₁ : BddAbove s) : sInf s⁻¹ = (sSup s)⁻¹ := by - rw [← image_inv] - exact ((OrderIso.inv α).map_csSup' hs₀ hs₁).symm - -@[to_additive] -theorem csSup_mul (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : - sSup (s * t) = sSup s * sSup t := - csSup_image2_eq_csSup_csSup (fun _ => (OrderIso.mulRight _).to_galoisConnection) - (fun _ => (OrderIso.mulLeft _).to_galoisConnection) hs₀ hs₁ ht₀ ht₁ - -@[to_additive] -theorem csInf_mul (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : - sInf (s * t) = sInf s * sInf t := - csInf_image2_eq_csInf_csInf (fun _ => (OrderIso.mulRight _).symm.to_galoisConnection) - (fun _ => (OrderIso.mulLeft _).symm.to_galoisConnection) hs₀ hs₁ ht₀ ht₁ - -@[to_additive] -theorem csSup_div (hs₀ : s.Nonempty) (hs₁ : BddAbove s) (ht₀ : t.Nonempty) (ht₁ : BddBelow t) : - sSup (s / t) = sSup s / sInf t := by - rw [div_eq_mul_inv, csSup_mul hs₀ hs₁ ht₀.inv ht₁.inv, csSup_inv ht₀ ht₁, div_eq_mul_inv] - -@[to_additive] -theorem csInf_div (hs₀ : s.Nonempty) (hs₁ : BddBelow s) (ht₀ : t.Nonempty) (ht₁ : BddAbove t) : - sInf (s / t) = sInf s / sSup t := by - rw [div_eq_mul_inv, csInf_mul hs₀ hs₁ ht₀.inv ht₁.inv, csInf_inv ht₀ ht₁, div_eq_mul_inv] - -end Group - -end ConditionallyCompleteLattice - -namespace LinearOrderedField - -variable {K : Type*} [LinearOrderedField K] {a b r : K} (hr : 0 < r) -include hr - -open Set - -theorem smul_Ioo : r • Ioo a b = Ioo (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioo] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_lt_mul_left hr).mpr a_h_left_left - · exact (mul_lt_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Icc : r • Icc a b = Icc (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Icc] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_le_mul_left hr).mpr a_h_left_left - · exact (mul_le_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ico : r • Ico a b = Ico (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ico] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_le_mul_left hr).mpr a_h_left_left - · exact (mul_lt_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(le_div_iff₀' hr).mpr a_left, (div_lt_iff' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ioc : r • Ioc a b = Ioc (r • a) (r • b) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioc] - constructor - · rintro ⟨a, ⟨a_h_left_left, a_h_left_right⟩, rfl⟩ - constructor - · exact (mul_lt_mul_left hr).mpr a_h_left_left - · exact (mul_le_mul_left hr).mpr a_h_left_right - · rintro ⟨a_left, a_right⟩ - use x / r - refine ⟨⟨(lt_div_iff' hr).mpr a_left, (div_le_iff₀' hr).mpr a_right⟩, ?_⟩ - rw [mul_div_cancel₀ _ (ne_of_gt hr)] - -theorem smul_Ioi : r • Ioi a = Ioi (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioi] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_lt_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (lt_div_iff' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Iio : r • Iio a = Iio (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Iio] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_lt_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (div_lt_iff' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Ici : r • Ici a = Ici (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Ioi] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_le_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (le_div_iff₀' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -theorem smul_Iic : r • Iic a = Iic (r • a) := by - ext x - simp only [mem_smul_set, smul_eq_mul, mem_Iio] - constructor - · rintro ⟨a_w, a_h_left, rfl⟩ - exact (mul_le_mul_left hr).mpr a_h_left - · rintro h - use x / r - constructor - · exact (div_le_iff₀' hr).mpr h - · exact mul_div_cancel₀ _ (ne_of_gt hr) - -end LinearOrderedField diff --git a/Mathlib/Algebra/Order/Positive/Field.lean b/Mathlib/Algebra/Order/Positive/Field.lean index 3a053adc33a18..5d1fc0b381760 100644 --- a/Mathlib/Algebra/Order/Positive/Field.lean +++ b/Mathlib/Algebra/Order/Positive/Field.lean @@ -25,7 +25,7 @@ theorem coe_inv (x : { x : K // 0 < x }) : ↑x⁻¹ = (x⁻¹ : K) := rfl instance : Pow { x : K // 0 < x } ℤ := - ⟨fun x n => ⟨(x : K) ^ n, zpow_pos_of_pos x.2 _⟩⟩ + ⟨fun x n => ⟨(x : K) ^ n, zpow_pos x.2 _⟩⟩ @[simp] theorem coe_zpow (x : { x : K // 0 < x }) (n : ℤ) : ↑(x ^ n) = (x : K) ^ n := diff --git a/Mathlib/Algebra/Order/Rearrangement.lean b/Mathlib/Algebra/Order/Rearrangement.lean index f032d3104e240..f69acca4d99d3 100644 --- a/Mathlib/Algebra/Order/Rearrangement.lean +++ b/Mathlib/Algebra/Order/Rearrangement.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mantas Bakšys -/ import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.Order.Group.Instances import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Data.Prod.Lex @@ -41,23 +40,30 @@ convenience. The case for `Monotone`/`Antitone` pairs of functions over a `LinearOrder` is not deduced in this file because it is easily deducible from the `Monovary` API. + +## TODO + +Add equality cases for when the permute function is injective. This comes from the following fact: +If `Monovary f g`, `Injective g` and `σ` is a permutation, then `Monovary f (g ∘ σ) ↔ σ = 1`. -/ open Equiv Equiv.Perm Finset Function OrderDual -variable {ι α β : Type*} +variable {ι α β : Type*} [LinearOrderedSemiring α] [ExistsAddOfLE α] + [LinearOrderedCancelAddCommMonoid β] [Module α β] /-! ### Scalar multiplication versions -/ - section SMul -variable [LinearOrderedRing α] [LinearOrderedAddCommGroup β] [Module α β] [OrderedSMul α β] - {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} +/-! #### Weak rearrangement inequality -/ + +section weak_inequality +variable [PosSMulMono α β] {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} /-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when -`f` and `g` monovary together. Stated by permuting the entries of `g`. -/ +`f` and `g` monovary together on `s`. Stated by permuting the entries of `g`. -/ theorem MonovaryOn.sum_smul_comp_perm_le_sum_smul (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g (σ i) ≤ ∑ i ∈ s, f i • g i := by classical @@ -106,9 +112,62 @@ theorem MonovaryOn.sum_smul_comp_perm_le_sum_smul (hfg : MonovaryOn f g s) rintro rfl exact has hx.2 +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when +`f` and `g` antivary together on `s`. Stated by permuting the entries of `g`. -/ +theorem AntivaryOn.sum_smul_le_sum_smul_comp_perm (hfg : AntivaryOn f g s) + (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i ≤ ∑ i ∈ s, f i • g (σ i) := + hfg.dual_right.sum_smul_comp_perm_le_sum_smul hσ + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when +`f` and `g` monovary together on `s`. Stated by permuting the entries of `f`. -/ +theorem MonovaryOn.sum_comp_perm_smul_le_sum_smul (hfg : MonovaryOn f g s) + (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) • g i ≤ ∑ i ∈ s, f i • g i := by + convert hfg.sum_smul_comp_perm_le_sum_smul + (show { x | σ⁻¹ x ≠ x } ⊆ s by simp only [set_support_inv_eq, hσ]) using 1 + exact σ.sum_comp' s (fun i j ↦ f i • g j) hσ + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when +`f` and `g` antivary together on `s`. Stated by permuting the entries of `f`. -/ +theorem AntivaryOn.sum_smul_le_sum_comp_perm_smul (hfg : AntivaryOn f g s) + (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i ≤ ∑ i ∈ s, f (σ i) • g i := + hfg.dual_right.sum_comp_perm_smul_le_sum_smul hσ + +variable [Fintype ι] + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when +`f` and `g` monovary together. Stated by permuting the entries of `g`. -/ +theorem Monovary.sum_smul_comp_perm_le_sum_smul (hfg : Monovary f g) : + ∑ i, f i • g (σ i) ≤ ∑ i, f i • g i := + (hfg.monovaryOn _).sum_smul_comp_perm_le_sum_smul fun _ _ ↦ mem_univ _ + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when +`f` and `g` antivary together. Stated by permuting the entries of `g`. -/ +theorem Antivary.sum_smul_le_sum_smul_comp_perm (hfg : Antivary f g) : + ∑ i, f i • g i ≤ ∑ i, f i • g (σ i) := + (hfg.antivaryOn _).sum_smul_le_sum_smul_comp_perm fun _ _ ↦ mem_univ _ + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when +`f` and `g` monovary together. Stated by permuting the entries of `f`. -/ +theorem Monovary.sum_comp_perm_smul_le_sum_smul (hfg : Monovary f g) : + ∑ i, f (σ i) • g i ≤ ∑ i, f i • g i := + (hfg.monovaryOn _).sum_comp_perm_smul_le_sum_smul fun _ _ ↦ mem_univ _ + +/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when +`f` and `g` antivary together. Stated by permuting the entries of `f`. -/ +theorem Antivary.sum_smul_le_sum_comp_perm_smul (hfg : Antivary f g) : + ∑ i, f i • g i ≤ ∑ i, f (σ i) • g i := + (hfg.antivaryOn _).sum_smul_le_sum_comp_perm_smul fun _ _ ↦ mem_univ _ + +end weak_inequality + +/-! #### Equality case of the rearrangement inequality -/ + +section equality_case +variable [PosSMulStrictMono α β] {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} + /-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which monovary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` monovary -together. Stated by permuting the entries of `g`. -/ +`g`, which monovary together on `s`, is unchanged by a permutation if and only if `f` and `g ∘ σ` +monovary together on `s`. Stated by permuting the entries of `g`. -/ theorem MonovaryOn.sum_smul_comp_perm_eq_sum_smul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g (σ i) = ∑ i ∈ s, f i • g i ↔ MonovaryOn f (g ∘ σ) s := by @@ -134,26 +193,17 @@ theorem MonovaryOn.sum_smul_comp_perm_eq_sum_smul_iff (hfg : MonovaryOn f g s) · convert h.sum_smul_comp_perm_le_sum_smul ((set_support_inv_eq _).subset.trans hσ) using 1 simp_rw [Function.comp_apply, apply_inv_self] -/-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of -`f` and `g`, which monovary together, is strictly decreased by a permutation if and only if -`f` and `g ∘ σ` do not monovary together. Stated by permuting the entries of `g`. -/ -theorem MonovaryOn.sum_smul_comp_perm_lt_sum_smul_iff (hfg : MonovaryOn f g s) +/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and +`g`, which antivary together on `s`, is unchanged by a permutation if and only if `f` and `g ∘ σ` +antivary together on `s`. Stated by permuting the entries of `g`. -/ +theorem AntivaryOn.sum_smul_comp_perm_eq_sum_smul_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : - ∑ i ∈ s, f i • g (σ i) < ∑ i ∈ s, f i • g i ↔ ¬MonovaryOn f (g ∘ σ) s := by - simp [← hfg.sum_smul_comp_perm_eq_sum_smul_iff hσ, lt_iff_le_and_ne, - hfg.sum_smul_comp_perm_le_sum_smul hσ] - -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when -`f` and `g` monovary together. Stated by permuting the entries of `f`. -/ -theorem MonovaryOn.sum_comp_perm_smul_le_sum_smul (hfg : MonovaryOn f g s) - (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) • g i ≤ ∑ i ∈ s, f i • g i := by - convert hfg.sum_smul_comp_perm_le_sum_smul - (show { x | σ⁻¹ x ≠ x } ⊆ s by simp only [set_support_inv_eq, hσ]) using 1 - exact σ.sum_comp' s (fun i j ↦ f i • g j) hσ + ∑ i ∈ s, f i • g (σ i) = ∑ i ∈ s, f i • g i ↔ AntivaryOn f (g ∘ σ) s := + (hfg.dual_right.sum_smul_comp_perm_eq_sum_smul_iff hσ).trans monovaryOn_toDual_right /-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which monovary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` monovary -together. Stated by permuting the entries of `f`. -/ +`g`, which monovary together on `s`, is unchanged by a permutation if and only if `f ∘ σ` and `g` +monovary together on `s`. Stated by permuting the entries of `f`. -/ theorem MonovaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) • g i = ∑ i ∈ s, f i • g i ↔ MonovaryOn (f ∘ σ) g s := by @@ -171,63 +221,93 @@ theorem MonovaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : MonovaryOn f g s) · rw [σ.symm.eq_preimage_iff_image_eq] exact Set.image_perm hσinv -/-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of -`f` and `g`, which monovary together, is strictly decreased by a permutation if and only if -`f ∘ σ` and `g` do not monovary together. Stated by permuting the entries of `f`. -/ -theorem MonovaryOn.sum_comp_perm_smul_lt_sum_smul_iff (hfg : MonovaryOn f g s) +/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and +`g`, which antivary together on `s`, is unchanged by a permutation if and only if `f ∘ σ` and `g` +antivary together on `s`. Stated by permuting the entries of `f`. -/ +theorem AntivaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : - ∑ i ∈ s, f (σ i) • g i < ∑ i ∈ s, f i • g i ↔ ¬MonovaryOn (f ∘ σ) g s := by - simp [← hfg.sum_comp_perm_smul_eq_sum_smul_iff hσ, lt_iff_le_and_ne, - hfg.sum_comp_perm_smul_le_sum_smul hσ] + ∑ i ∈ s, f (σ i) • g i = ∑ i ∈ s, f i • g i ↔ AntivaryOn (f ∘ σ) g s := + (hfg.dual_right.sum_comp_perm_smul_eq_sum_smul_iff hσ).trans monovaryOn_toDual_right -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when -`f` and `g` antivary together. Stated by permuting the entries of `g`. -/ -theorem AntivaryOn.sum_smul_le_sum_smul_comp_perm (hfg : AntivaryOn f g s) - (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i ≤ ∑ i ∈ s, f i • g (σ i) := - hfg.dual_right.sum_smul_comp_perm_le_sum_smul hσ +@[deprecated (since := "2024-06-25")] +alias AntivaryOn.sum_smul_eq_sum_comp_perm_smul_iff := AntivaryOn.sum_comp_perm_smul_eq_sum_smul_iff + +variable [Fintype ι] + +/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and +`g`, which monovary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` monovary +together. Stated by permuting the entries of `g`. -/ +theorem Monovary.sum_smul_comp_perm_eq_sum_smul_iff (hfg : Monovary f g) : + ∑ i, f i • g (σ i) = ∑ i, f i • g i ↔ Monovary f (g ∘ σ) := by + simp [(hfg.monovaryOn _).sum_smul_comp_perm_eq_sum_smul_iff fun _ _ ↦ mem_univ _] + +/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and +`g`, which monovary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` monovary +together. Stated by permuting the entries of `g`. -/ +theorem Monovary.sum_comp_perm_smul_eq_sum_smul_iff (hfg : Monovary f g) : + ∑ i, f (σ i) • g i = ∑ i, f i • g i ↔ Monovary (f ∘ σ) g := by + simp [(hfg.monovaryOn _).sum_comp_perm_smul_eq_sum_smul_iff fun _ _ ↦ mem_univ _] /-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g`, which antivary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` antivary together. Stated by permuting the entries of `g`. -/ -theorem AntivaryOn.sum_smul_comp_perm_eq_sum_smul_iff (hfg : AntivaryOn f g s) - (hσ : {x | σ x ≠ x} ⊆ s) : - ∑ i ∈ s, f i • g (σ i) = ∑ i ∈ s, f i • g i ↔ AntivaryOn f (g ∘ σ) s := - (hfg.dual_right.sum_smul_comp_perm_eq_sum_smul_iff hσ).trans monovaryOn_toDual_right +theorem Antivary.sum_smul_comp_perm_eq_sum_smul_iff (hfg : Antivary f g) : + ∑ i, f i • g (σ i) = ∑ i, f i • g i ↔ Antivary f (g ∘ σ) := by + simp [(hfg.antivaryOn _).sum_smul_comp_perm_eq_sum_smul_iff fun _ _ ↦ mem_univ _] @[deprecated (since := "2024-06-25")] -alias AntivaryOn.sum_smul_eq_sum_smul_comp_perm_iff := AntivaryOn.sum_smul_comp_perm_eq_sum_smul_iff +alias Antivary.sum_smul_eq_sum_smul_comp_perm_iff := Antivary.sum_smul_comp_perm_eq_sum_smul_iff + +/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and +`g`, which antivary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` antivary +together. Stated by permuting the entries of `f`. -/ +theorem Antivary.sum_comp_perm_smul_eq_sum_smul_iff (hfg : Antivary f g) : + ∑ i, f (σ i) • g i = ∑ i, f i • g i ↔ Antivary (f ∘ σ) g := by + simp [(hfg.antivaryOn _).sum_comp_perm_smul_eq_sum_smul_iff fun _ _ ↦ mem_univ _] + +@[deprecated (since := "2024-06-25")] +alias Antivary.sum_smul_eq_sum_comp_perm_smul_iff := Antivary.sum_comp_perm_smul_eq_sum_smul_iff + +end equality_case + +/-! #### Strict rearrangement inequality -/ + +section strict_inequality +variable [PosSMulStrictMono α β] {s : Finset ι} {σ : Perm ι} {f : ι → α} {g : ι → β} /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of -`f` and `g`, which antivary together, is strictly decreased by a permutation if and only if -`f` and `g ∘ σ` do not antivary together. Stated by permuting the entries of `g`. -/ +`f` and `g`, which monovary together on `s`, is strictly decreased by a permutation if and only if +`f` and `g ∘ σ` do not monovary together on `s`. Stated by permuting the entries of `g`. -/ +theorem MonovaryOn.sum_smul_comp_perm_lt_sum_smul_iff (hfg : MonovaryOn f g s) + (hσ : {x | σ x ≠ x} ⊆ s) : + ∑ i ∈ s, f i • g (σ i) < ∑ i ∈ s, f i • g i ↔ ¬MonovaryOn f (g ∘ σ) s := by + simp [← hfg.sum_smul_comp_perm_eq_sum_smul_iff hσ, lt_iff_le_and_ne, + hfg.sum_smul_comp_perm_le_sum_smul hσ] + +/-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of +`f` and `g`, which antivary together on `s`, is strictly decreased by a permutation if and only if +`f` and `g ∘ σ` do not antivary together on `s`. Stated by permuting the entries of `g`. -/ theorem AntivaryOn.sum_smul_lt_sum_smul_comp_perm_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i < ∑ i ∈ s, f i • g (σ i) ↔ ¬AntivaryOn f (g ∘ σ) s := by simp [← hfg.sum_smul_comp_perm_eq_sum_smul_iff hσ, lt_iff_le_and_ne, eq_comm, hfg.sum_smul_le_sum_smul_comp_perm hσ] -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when -`f` and `g` antivary together. Stated by permuting the entries of `f`. -/ -theorem AntivaryOn.sum_smul_le_sum_comp_perm_smul (hfg : AntivaryOn f g s) - (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i ≤ ∑ i ∈ s, f (σ i) • g i := by - convert hfg.sum_smul_le_sum_smul_comp_perm - (show { x | σ⁻¹ x ≠ x } ⊆ s by simp only [set_support_inv_eq, hσ]) using 1 - exact σ.sum_comp' s (fun i j ↦ f i • g j) hσ - -/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which antivary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` antivary -together. Stated by permuting the entries of `f`. -/ -theorem AntivaryOn.sum_comp_perm_smul_eq_sum_smul_iff (hfg : AntivaryOn f g s) +/-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of +`f` and `g`, which monovary together on `s`, is strictly decreased by a permutation if and only if +`f ∘ σ` and `g` do not monovary together on `s`. Stated by permuting the entries of `f`. -/ +theorem MonovaryOn.sum_comp_perm_smul_lt_sum_smul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : - ∑ i ∈ s, f (σ i) • g i = ∑ i ∈ s, f i • g i ↔ AntivaryOn (f ∘ σ) g s := - (hfg.dual_right.sum_comp_perm_smul_eq_sum_smul_iff hσ).trans monovaryOn_toDual_right + ∑ i ∈ s, f (σ i) • g i < ∑ i ∈ s, f i • g i ↔ ¬MonovaryOn (f ∘ σ) g s := by + simp [← hfg.sum_comp_perm_smul_eq_sum_smul_iff hσ, lt_iff_le_and_ne, + hfg.sum_comp_perm_smul_le_sum_smul hσ] @[deprecated (since := "2024-06-25")] -alias AntivaryOn.sum_smul_eq_sum_comp_perm_smul_iff := AntivaryOn.sum_comp_perm_smul_eq_sum_smul_iff +alias AntivaryOn.sum_smul_eq_sum_smul_comp_perm_iff := AntivaryOn.sum_smul_comp_perm_eq_sum_smul_iff /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of -`f` and `g`, which antivary together, is strictly decreased by a permutation if and only if -`f ∘ σ` and `g` do not antivary together. Stated by permuting the entries of `f`. -/ +`f` and `g`, which antivary together on `s`, is strictly decreased by a permutation if and only if +`f ∘ σ` and `g` do not antivary together on `s`. Stated by permuting the entries of `f`. -/ theorem AntivaryOn.sum_smul_lt_sum_comp_perm_smul_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g i < ∑ i ∈ s, f (σ i) • g i ↔ ¬AntivaryOn (f ∘ σ) g s := by @@ -236,19 +316,6 @@ theorem AntivaryOn.sum_smul_lt_sum_comp_perm_smul_iff (hfg : AntivaryOn f g s) variable [Fintype ι] -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when -`f` and `g` monovary together. Stated by permuting the entries of `g`. -/ -theorem Monovary.sum_smul_comp_perm_le_sum_smul (hfg : Monovary f g) : - ∑ i, f i • g (σ i) ≤ ∑ i, f i • g i := - (hfg.monovaryOn _).sum_smul_comp_perm_le_sum_smul fun _ _ ↦ mem_univ _ - -/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which monovary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` monovary -together. Stated by permuting the entries of `g`. -/ -theorem Monovary.sum_smul_comp_perm_eq_sum_smul_iff (hfg : Monovary f g) : - ∑ i, f i • g (σ i) = ∑ i, f i • g i ↔ Monovary f (g ∘ σ) := by - simp [(hfg.monovaryOn _).sum_smul_comp_perm_eq_sum_smul_iff fun _ _ ↦ mem_univ _] - /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g`, which monovary together, is strictly decreased by a permutation if and only if `f` and `g ∘ σ` do not monovary together. Stated by permuting the entries of `g`. -/ @@ -256,19 +323,6 @@ theorem Monovary.sum_smul_comp_perm_lt_sum_smul_iff (hfg : Monovary f g) : ∑ i, f i • g (σ i) < ∑ i, f i • g i ↔ ¬Monovary f (g ∘ σ) := by simp [(hfg.monovaryOn _).sum_smul_comp_perm_lt_sum_smul_iff fun _ _ ↦ mem_univ _] -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is maximized when -`f` and `g` monovary together. Stated by permuting the entries of `f`. -/ -theorem Monovary.sum_comp_perm_smul_le_sum_smul (hfg : Monovary f g) : - ∑ i, f (σ i) • g i ≤ ∑ i, f i • g i := - (hfg.monovaryOn _).sum_comp_perm_smul_le_sum_smul fun _ _ ↦ mem_univ _ - -/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which monovary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` monovary -together. Stated by permuting the entries of `g`. -/ -theorem Monovary.sum_comp_perm_smul_eq_sum_smul_iff (hfg : Monovary f g) : - ∑ i, f (σ i) • g i = ∑ i, f i • g i ↔ Monovary (f ∘ σ) g := by - simp [(hfg.monovaryOn _).sum_comp_perm_smul_eq_sum_smul_iff fun _ _ ↦ mem_univ _] - /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g`, which monovary together, is strictly decreased by a permutation if and only if `f` and `g ∘ σ` do not monovary together. Stated by permuting the entries of `g`. -/ @@ -276,22 +330,6 @@ theorem Monovary.sum_comp_perm_smul_lt_sum_smul_iff (hfg : Monovary f g) : ∑ i, f (σ i) • g i < ∑ i, f i • g i ↔ ¬Monovary (f ∘ σ) g := by simp [(hfg.monovaryOn _).sum_comp_perm_smul_lt_sum_smul_iff fun _ _ ↦ mem_univ _] -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when -`f` and `g` antivary together. Stated by permuting the entries of `g`. -/ -theorem Antivary.sum_smul_le_sum_smul_comp_perm (hfg : Antivary f g) : - ∑ i, f i • g i ≤ ∑ i, f i • g (σ i) := - (hfg.antivaryOn _).sum_smul_le_sum_smul_comp_perm fun _ _ ↦ mem_univ _ - -/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which antivary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` antivary -together. Stated by permuting the entries of `g`. -/ -theorem Antivary.sum_smul_comp_perm_eq_sum_smul_iff (hfg : Antivary f g) : - ∑ i, f i • g (σ i) = ∑ i, f i • g i ↔ Antivary f (g ∘ σ) := by - simp [(hfg.antivaryOn _).sum_smul_comp_perm_eq_sum_smul_iff fun _ _ ↦ mem_univ _] - -@[deprecated (since := "2024-06-25")] -alias Antivary.sum_smul_eq_sum_smul_comp_perm_iff := Antivary.sum_smul_comp_perm_eq_sum_smul_iff - /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g`, which antivary together, is strictly decreased by a permutation if and only if `f` and `g ∘ σ` do not antivary together. Stated by permuting the entries of `g`. -/ @@ -299,22 +337,6 @@ theorem Antivary.sum_smul_lt_sum_smul_comp_perm_iff (hfg : Antivary f g) : ∑ i, f i • g i < ∑ i, f i • g (σ i) ↔ ¬Antivary f (g ∘ σ) := by simp [(hfg.antivaryOn _).sum_smul_lt_sum_smul_comp_perm_iff fun _ _ ↦ mem_univ _] -/-- **Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g` is minimized when -`f` and `g` antivary together. Stated by permuting the entries of `f`. -/ -theorem Antivary.sum_smul_le_sum_comp_perm_smul (hfg : Antivary f g) : - ∑ i, f i • g i ≤ ∑ i, f (σ i) • g i := - (hfg.antivaryOn _).sum_smul_le_sum_comp_perm_smul fun _ _ ↦ mem_univ _ - -/-- **Equality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and -`g`, which antivary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` antivary -together. Stated by permuting the entries of `f`. -/ -theorem Antivary.sum_comp_perm_smul_eq_sum_smul_iff (hfg : Antivary f g) : - ∑ i, f (σ i) • g i = ∑ i, f i • g i ↔ Antivary (f ∘ σ) g := by - simp [(hfg.antivaryOn _).sum_comp_perm_smul_eq_sum_smul_iff fun _ _ ↦ mem_univ _] - -@[deprecated (since := "2024-06-25")] -alias Antivary.sum_smul_eq_sum_comp_perm_smul_iff := Antivary.sum_comp_perm_smul_eq_sum_smul_iff - /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of `f` and `g`, which antivary together, is strictly decreased by a permutation if and only if `f ∘ σ` and `g` do not antivary together. Stated by permuting the entries of `f`. -/ @@ -322,6 +344,7 @@ theorem Antivary.sum_smul_lt_sum_comp_perm_smul_iff (hfg : Antivary f g) : ∑ i, f i • g i < ∑ i, f (σ i) • g i ↔ ¬Antivary (f ∘ σ) g := by simp [(hfg.antivaryOn _).sum_smul_lt_sum_comp_perm_smul_iff fun _ _ ↦ mem_univ _] +end strict_inequality end SMul /-! @@ -330,87 +353,84 @@ end SMul Special cases of the above when scalar multiplication is actually multiplication. -/ - section Mul - - -variable [LinearOrderedRing α] {s : Finset ι} {σ : Perm ι} {f g : ι → α} +variable {s : Finset ι} {σ : Perm ι} {f g : ι → α} /-- **Rearrangement Inequality**: Pointwise multiplication of `f` and `g` is maximized when `f` and -`g` monovary together. Stated by permuting the entries of `g`. -/ -theorem MonovaryOn.sum_mul_comp_perm_le_sum_mul (hfg : MonovaryOn f g s) - (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g (σ i) ≤ ∑ i ∈ s, f i * g i := +`g` monovary together on `s`. Stated by permuting the entries of `g`. -/ +theorem MonovaryOn.sum_mul_comp_perm_le_sum_mul (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : + ∑ i ∈ s, f i * g (σ i) ≤ ∑ i ∈ s, f i * g i := hfg.sum_smul_comp_perm_le_sum_smul hσ /-- **Equality case of the Rearrangement Inequality**: Pointwise multiplication of `f` and `g`, -which monovary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` monovary -together. Stated by permuting the entries of `g`. -/ +which monovary together on `s`, is unchanged by a permutation if and only if `f` and `g ∘ σ` +monovary together on `s`. Stated by permuting the entries of `g`. -/ theorem MonovaryOn.sum_mul_comp_perm_eq_sum_mul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g (σ i) = ∑ i ∈ s, f i * g i ↔ MonovaryOn f (g ∘ σ) s := hfg.sum_smul_comp_perm_eq_sum_smul_iff hσ /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise scalar multiplication of -`f` and `g`, which monovary together, is strictly decreased by a permutation if and only if -`f` and `g ∘ σ` do not monovary together. Stated by permuting the entries of `g`. -/ +`f` and `g`, which monovary together on `s`, is strictly decreased by a permutation if and only if +`f` and `g ∘ σ` do not monovary together on `s`. Stated by permuting the entries of `g`. -/ theorem MonovaryOn.sum_mul_comp_perm_lt_sum_mul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i • g (σ i) < ∑ i ∈ s, f i • g i ↔ ¬MonovaryOn f (g ∘ σ) s := hfg.sum_smul_comp_perm_lt_sum_smul_iff hσ /-- **Rearrangement Inequality**: Pointwise multiplication of `f` and `g` is maximized when `f` and -`g` monovary together. Stated by permuting the entries of `f`. -/ +`g` monovary together on `s`. Stated by permuting the entries of `f`. -/ theorem MonovaryOn.sum_comp_perm_mul_le_sum_mul (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) * g i ≤ ∑ i ∈ s, f i * g i := hfg.sum_comp_perm_smul_le_sum_smul hσ /-- **Equality case of the Rearrangement Inequality**: Pointwise multiplication of `f` and `g`, -which monovary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` monovary -together. Stated by permuting the entries of `f`. -/ +which monovary together on `s`, is unchanged by a permutation if and only if `f ∘ σ` and `g` +monovary together on `s`. Stated by permuting the entries of `f`. -/ theorem MonovaryOn.sum_comp_perm_mul_eq_sum_mul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) * g i = ∑ i ∈ s, f i * g i ↔ MonovaryOn (f ∘ σ) g s := hfg.sum_comp_perm_smul_eq_sum_smul_iff hσ /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise multiplication of -`f` and `g`, which monovary together, is strictly decreased by a permutation if and only if -`f ∘ σ` and `g` do not monovary together. Stated by permuting the entries of `f`. -/ +`f` and `g`, which monovary together on `s`, is strictly decreased by a permutation if and only if +`f ∘ σ` and `g` do not monovary together on `s`. Stated by permuting the entries of `f`. -/ theorem MonovaryOn.sum_comp_perm_mul_lt_sum_mul_iff (hfg : MonovaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) * g i < ∑ i ∈ s, f i * g i ↔ ¬MonovaryOn (f ∘ σ) g s := hfg.sum_comp_perm_smul_lt_sum_smul_iff hσ /-- **Rearrangement Inequality**: Pointwise multiplication of `f` and `g` is minimized when `f` and -`g` antivary together. Stated by permuting the entries of `g`. -/ +`g` antivary together on `s`. Stated by permuting the entries of `g`. -/ theorem AntivaryOn.sum_mul_le_sum_mul_comp_perm (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g i ≤ ∑ i ∈ s, f i * g (σ i) := hfg.sum_smul_le_sum_smul_comp_perm hσ /-- **Equality case of the Rearrangement Inequality**: Pointwise multiplication of `f` and `g`, -which antivary together, is unchanged by a permutation if and only if `f` and `g ∘ σ` antivary -together. Stated by permuting the entries of `g`. -/ +which antivary together on `s`, is unchanged by a permutation if and only if `f` and `g ∘ σ` +antivary together on `s`. Stated by permuting the entries of `g`. -/ theorem AntivaryOn.sum_mul_eq_sum_mul_comp_perm_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g (σ i) = ∑ i ∈ s, f i * g i ↔ AntivaryOn f (g ∘ σ) s := hfg.sum_smul_comp_perm_eq_sum_smul_iff hσ /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise multiplication of -`f` and `g`, which antivary together, is strictly decreased by a permutation if and only if -`f` and `g ∘ σ` do not antivary together. Stated by permuting the entries of `g`. -/ +`f` and `g`, which antivary together on `s`, is strictly decreased by a permutation if and only if +`f` and `g ∘ σ` do not antivary together on `s`. Stated by permuting the entries of `g`. -/ theorem AntivaryOn.sum_mul_lt_sum_mul_comp_perm_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g i < ∑ i ∈ s, f i * g (σ i) ↔ ¬AntivaryOn f (g ∘ σ) s := hfg.sum_smul_lt_sum_smul_comp_perm_iff hσ /-- **Rearrangement Inequality**: Pointwise multiplication of `f` and `g` is minimized when `f` and -`g` antivary together. Stated by permuting the entries of `f`. -/ +`g` antivary together on `s`. Stated by permuting the entries of `f`. -/ theorem AntivaryOn.sum_mul_le_sum_comp_perm_mul (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g i ≤ ∑ i ∈ s, f (σ i) * g i := hfg.sum_smul_le_sum_comp_perm_smul hσ /-- **Equality case of the Rearrangement Inequality**: Pointwise multiplication of `f` and `g`, -which antivary together, is unchanged by a permutation if and only if `f ∘ σ` and `g` antivary -together. Stated by permuting the entries of `f`. -/ +which antivary together on `s`, is unchanged by a permutation if and only if `f ∘ σ` and `g` +antivary together on `s`. Stated by permuting the entries of `f`. -/ theorem AntivaryOn.sum_comp_perm_mul_eq_sum_mul_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f (σ i) * g i = ∑ i ∈ s, f i * g i ↔ AntivaryOn (f ∘ σ) g s := @@ -420,8 +440,8 @@ theorem AntivaryOn.sum_comp_perm_mul_eq_sum_mul_iff (hfg : AntivaryOn f g s) alias AntivaryOn.sum_mul_eq_sum_comp_perm_mul_iff := AntivaryOn.sum_comp_perm_mul_eq_sum_mul_iff /-- **Strict inequality case of the Rearrangement Inequality**: Pointwise multiplication of -`f` and `g`, which antivary together, is strictly decreased by a permutation if and only if -`f ∘ σ` and `g` do not antivary together. Stated by permuting the entries of `f`. -/ +`f` and `g`, which antivary together on `s`, is strictly decreased by a permutation if and only if +`f ∘ σ` and `g` do not antivary together on `s`. Stated by permuting the entries of `f`. -/ theorem AntivaryOn.sum_mul_lt_sum_comp_perm_mul_iff (hfg : AntivaryOn f g s) (hσ : {x | σ x ≠ x} ⊆ s) : ∑ i ∈ s, f i * g i < ∑ i ∈ s, f (σ i) * g i ↔ ¬AntivaryOn (f ∘ σ) g s := diff --git a/Mathlib/Algebra/Order/Ring/Basic.lean b/Mathlib/Algebra/Order/Ring/Basic.lean index 0d45fc5b2b588..5e64f73cc40ea 100644 --- a/Mathlib/Algebra/Order/Ring/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Basic.lean @@ -37,10 +37,6 @@ section OrderedSemiring variable [OrderedSemiring R] {a b x y : R} {n m : ℕ} -theorem zero_pow_le_one : ∀ n : ℕ, (0 : R) ^ n ≤ 1 - | 0 => (pow_zero _).le - | n + 1 => by rw [zero_pow n.succ_ne_zero]; exact zero_le_one - theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y ^ n ≤ (x + y) ^ n := by rcases Nat.exists_eq_add_one_of_ne_zero hn with ⟨k, rfl⟩ induction k with @@ -60,40 +56,21 @@ theorem pow_add_pow_le (hx : 0 ≤ x) (hy : 0 ≤ y) (hn : n ≠ 0) : x ^ n + y rw [pow_succ' _ n] exact mul_le_mul_of_nonneg_left (ih (Nat.succ_ne_zero k)) h2 -@[bound] -theorem pow_le_one : ∀ n : ℕ, 0 ≤ a → a ≤ 1 → a ^ n ≤ 1 - | 0, _, _ => (pow_zero a).le - | n + 1, h₀, h₁ => (pow_succ a n).le.trans (mul_le_one (pow_le_one n h₀ h₁) h₀ h₁) - -theorem pow_lt_one (h₀ : 0 ≤ a) (h₁ : a < 1) : ∀ {n : ℕ}, n ≠ 0 → a ^ n < 1 - | 0, h => (h rfl).elim - | n + 1, _ => by - rw [pow_succ'] - exact mul_lt_one_of_nonneg_of_lt_one_left h₀ h₁ (pow_le_one _ h₀ h₁.le) - -@[bound] -theorem one_le_pow_of_one_le (H : 1 ≤ a) : ∀ n : ℕ, 1 ≤ a ^ n - | 0 => by rw [pow_zero] - | n + 1 => by - rw [pow_succ'] - simpa only [mul_one] using - mul_le_mul H (one_le_pow_of_one_le H n) zero_le_one (le_trans zero_le_one H) - -theorem pow_right_mono (h : 1 ≤ a) : Monotone (a ^ ·) := - monotone_nat_of_le_succ fun n => by - rw [pow_succ'] - exact le_mul_of_one_le_left (pow_nonneg (zero_le_one.trans h) _) h - -@[gcongr] -theorem pow_le_pow_right (ha : 1 ≤ a) (h : n ≤ m) : a ^ n ≤ a ^ m := pow_right_mono ha h +attribute [bound] pow_le_one₀ one_le_pow₀ -theorem le_self_pow (ha : 1 ≤ a) (h : m ≠ 0) : a ≤ a ^ m := by - simpa only [pow_one] using pow_le_pow_right ha <| Nat.pos_iff_ne_zero.2 h +@[deprecated (since := "2024-09-28")] alias mul_le_one := mul_le_one₀ +@[deprecated (since := "2024-09-28")] alias pow_le_one := pow_le_one₀ +@[deprecated (since := "2024-09-28")] alias pow_lt_one := pow_lt_one₀ +@[deprecated (since := "2024-09-28")] alias one_le_pow_of_one_le := one_le_pow₀ +@[deprecated (since := "2024-09-28")] alias one_lt_pow := one_lt_pow₀ +@[deprecated (since := "2024-10-04")] alias pow_right_mono := pow_right_mono₀ +@[deprecated (since := "2024-10-04")] alias pow_le_pow_right := pow_le_pow_right₀ +@[deprecated (since := "2024-10-04")] alias le_self_pow := le_self_pow₀ /-- The `bound` tactic can't handle `m ≠ 0` goals yet, so we express as `0 < m` -/ @[bound] lemma Bound.le_self_pow_of_pos {m : ℕ} (ha : 1 ≤ a) (h : 0 < m) : a ≤ a ^ m := - le_self_pow ha h.ne' + le_self_pow₀ ha h.ne' @[mono, gcongr, bound] theorem pow_le_pow_left {a b : R} (ha : 0 ≤ a) (hab : a ≤ b) : ∀ n, a ^ n ≤ b ^ n @@ -101,12 +78,6 @@ theorem pow_le_pow_left {a b : R} (ha : 0 ≤ a) (hab : a ≤ b) : ∀ n, a ^ n | n + 1 => by simpa only [pow_succ'] using mul_le_mul hab (pow_le_pow_left ha hab _) (pow_nonneg ha _) (ha.trans hab) -theorem one_lt_pow (ha : 1 < a) : ∀ {n : ℕ} (_ : n ≠ 0), 1 < a ^ n - | 0, h => (h rfl).elim - | n + 1, _ => by - rw [pow_succ'] - exact one_lt_mul_of_lt_of_le ha (one_le_pow_of_one_le ha.le _) - 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) _) @@ -117,7 +88,7 @@ lemma pow_add_pow_le' (ha : 0 ≤ a) (hb : 0 ≤ b) : a ^ n + b ^ n ≤ 2 * (a + lemma Bound.pow_le_pow_right_of_le_one_or_one_le (h : 1 ≤ a ∧ n ≤ m ∨ 0 ≤ a ∧ a ≤ 1 ∧ m ≤ n) : a ^ n ≤ a ^ m := by rcases h with ⟨a1, nm⟩ | ⟨a0, a1, mn⟩ - · exact pow_le_pow_right a1 nm + · exact pow_right_mono₀ a1 nm · exact pow_le_pow_of_le_one a0 a1 mn end OrderedSemiring @@ -361,36 +332,3 @@ 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 end LinearOrderedSemiring - -/-! -### Deprecated lemmas - -Those lemmas have been deprecated on 2023-12-23. --/ - -@[deprecated (since := "2023-12-23")] alias pow_mono := pow_right_mono -@[deprecated (since := "2023-12-23")] alias pow_le_pow := pow_le_pow_right -@[deprecated (since := "2023-12-23")] alias pow_le_pow_of_le_left := pow_le_pow_left -@[deprecated (since := "2023-12-23")] alias pow_lt_pow_of_lt_left := pow_lt_pow_left -@[deprecated (since := "2023-12-23")] alias strictMonoOn_pow := pow_left_strictMonoOn -@[deprecated (since := "2023-12-23")] alias pow_strictMono_right := pow_right_strictMono -@[deprecated (since := "2023-12-23")] alias pow_lt_pow := pow_lt_pow_right -@[deprecated (since := "2023-12-23")] alias pow_lt_pow_iff := pow_lt_pow_iff_right -@[deprecated (since := "2023-12-23")] alias pow_le_pow_iff := pow_le_pow_iff_right -@[deprecated (since := "2023-12-23")] alias self_lt_pow := lt_self_pow -@[deprecated (since := "2023-12-23")] alias strictAnti_pow := pow_right_strictAnti - -@[deprecated (since := "2023-12-23")] -alias pow_lt_pow_iff_of_lt_one := pow_lt_pow_iff_right_of_lt_one - -@[deprecated (since := "2023-12-23")] alias pow_lt_pow_of_lt_one := pow_lt_pow_right_of_lt_one -@[deprecated (since := "2023-12-23")] alias lt_of_pow_lt_pow := lt_of_pow_lt_pow_left -@[deprecated (since := "2023-12-23")] alias le_of_pow_le_pow := le_of_pow_le_pow_left -@[deprecated (since := "2023-12-23")] alias self_le_pow := le_self_pow -@[deprecated (since := "2023-12-23")] alias Nat.pow_lt_pow_of_lt_right := pow_lt_pow_right - -@[deprecated (since := "2023-12-23")] -protected alias Nat.pow_right_strictMono := pow_right_strictMono - -@[deprecated (since := "2023-12-23")] alias Nat.pow_le_iff_le_right := pow_le_pow_iff_right -@[deprecated (since := "2023-12-23")] alias Nat.pow_lt_iff_lt_right := pow_lt_pow_iff_right diff --git a/Mathlib/Algebra/Order/Ring/Cone.lean b/Mathlib/Algebra/Order/Ring/Cone.lean index 4ddd18e2f67d0..71c21076f0093 100644 --- a/Mathlib/Algebra/Order/Ring/Cone.lean +++ b/Mathlib/Algebra/Order/Ring/Cone.lean @@ -19,7 +19,7 @@ cones in rings and the corresponding ordered rings. -/ /-- `RingConeClass S R` says that `S` is a type of cones in `R`. -/ -class RingConeClass (S R : Type*) [Ring R] [SetLike S R] +class RingConeClass (S : Type*) (R : outParam Type*) [Ring R] [SetLike S R] extends AddGroupConeClass S R, SubsemiringClass S R : Prop /-- A (positive) cone in a ring is a subsemiring that diff --git a/Mathlib/Algebra/Order/Ring/Defs.lean b/Mathlib/Algebra/Order/Ring/Defs.lean index 7e1dda2f4617c..2a1301cc48fc2 100644 --- a/Mathlib/Algebra/Order/Ring/Defs.lean +++ b/Mathlib/Algebra/Order/Ring/Defs.lean @@ -222,6 +222,22 @@ instance (priority := 100) OrderedRing.toOrderedSemiring : OrderedSemiring α := mul_le_mul_of_nonneg_right := fun a b c h hc => by simpa only [sub_mul, sub_nonneg] using OrderedRing.mul_nonneg _ _ (sub_nonneg.2 h) hc } +lemma one_add_le_one_sub_mul_one_add (h : a + b + b * c ≤ c) : 1 + a ≤ (1 - b) * (1 + c) := by + rw [one_sub_mul, mul_one_add, le_sub_iff_add_le, add_assoc, ← add_assoc a] + gcongr + +lemma one_add_le_one_add_mul_one_sub (h : a + c + b * c ≤ b) : 1 + a ≤ (1 + b) * (1 - c) := by + rw [mul_one_sub, one_add_mul, le_sub_iff_add_le, add_assoc, ← add_assoc a] + gcongr + +lemma one_sub_le_one_sub_mul_one_add (h : b + b * c ≤ a + c) : 1 - a ≤ (1 - b) * (1 + c) := by + rw [one_sub_mul, mul_one_add, sub_le_sub_iff, add_assoc, add_comm c] + gcongr + +lemma one_sub_le_one_add_mul_one_sub (h : c + b * c ≤ a + b) : 1 - a ≤ (1 + b) * (1 - c) := by + rw [mul_one_sub, one_add_mul, sub_le_sub_iff, add_assoc, add_comm b] + gcongr + end OrderedRing section OrderedCommRing diff --git a/Mathlib/Algebra/Order/Ring/Opposite.lean b/Mathlib/Algebra/Order/Ring/Opposite.lean new file mode 100644 index 0000000000000..c945c5ec82242 --- /dev/null +++ b/Mathlib/Algebra/Order/Ring/Opposite.lean @@ -0,0 +1,50 @@ +/- +Copyright (c) 2024 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.Opposite +import Mathlib.Algebra.Order.Ring.Defs +import Mathlib.Algebra.Ring.Opposite + +/-! +# Ordered ring instances for `MulOpposite`/`AddOpposite` + +This files transfers ordered (semi)ring instances from `α` to `αᵐᵒᵖ` and `αᵃᵒᵖ`. +-/ + +variable {α : Type*} + +namespace MulOpposite + +instance [OrderedSemiring α] : OrderedSemiring αᵐᵒᵖ where + __ := instSemiring + __ := instOrderedAddCommMonoid + zero_le_one := zero_le_one (α := α) + mul_le_mul_of_nonneg_left _ _ _ := mul_le_mul_of_nonneg_right (α := α) + mul_le_mul_of_nonneg_right _ _ _ := mul_le_mul_of_nonneg_left (α := α) + +instance [OrderedRing α] : OrderedRing αᵐᵒᵖ where + __ := instRing + __ := instOrderedAddCommGroup + __ := instOrderedSemiring + mul_nonneg _a _b ha hb := mul_nonneg (α := α) hb ha + +end MulOpposite + +namespace AddOpposite + +instance [OrderedSemiring α] : OrderedSemiring αᵃᵒᵖ where + __ := instSemiring + __ := instOrderedAddCommMonoid + zero_le_one := zero_le_one (α := α) + mul_le_mul_of_nonneg_left _ _ _ := mul_le_mul_of_nonneg_left (α := α) + mul_le_mul_of_nonneg_right _ _ _ := mul_le_mul_of_nonneg_right (α := α) + +instance [OrderedRing α] : OrderedRing αᵐᵒᵖ where + __ := instRing + __ := instOrderedAddCommGroup + __ := instOrderedSemiring + mul_nonneg _a _b := mul_nonneg (α := α) + +end AddOpposite diff --git a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean index 68c19b0c396c3..ea150bfb7d6fe 100644 --- a/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean +++ b/Mathlib/Algebra/Order/Ring/Unbundled/Basic.lean @@ -813,10 +813,4 @@ lemma mul_self_le_mul_self_of_le_of_neg_le mul_le_mul h₂ h₂ (neg_nonneg.2 h) <| (neg_nonneg.2 h).trans h₂ end LinearOrderedRing - -@[deprecated (since := "2023-12-23")] alias zero_le_mul_left := mul_nonneg_iff_of_pos_left -@[deprecated (since := "2023-12-23")] alias zero_le_mul_right := mul_nonneg_iff_of_pos_right -@[deprecated (since := "2023-12-23")] alias zero_lt_mul_left := mul_pos_iff_of_pos_left -@[deprecated (since := "2023-12-23")] alias zero_lt_mul_right := mul_pos_iff_of_pos_right - end OrderedCommRing diff --git a/Mathlib/Algebra/Order/Sub/Defs.lean b/Mathlib/Algebra/Order/Sub/Defs.lean index 08e4b08db1ebc..9966239cd270f 100644 --- a/Mathlib/Algebra/Order/Sub/Defs.lean +++ b/Mathlib/Algebra/Order/Sub/Defs.lean @@ -41,7 +41,7 @@ TODO: generalize `Nat.le_of_le_of_sub_le_sub_right`, `Nat.sub_le_sub_right_iff`, -/ -variable {α β : Type*} +variable {α : Type*} /-- `OrderedSub α` means that `α` has a subtraction characterized by `a - b ≤ c ↔ a ≤ c + b`. In other words, `a - b` is the least `c` such that `a ≤ b + c`. @@ -60,7 +60,7 @@ theorem tsub_le_iff_right [LE α] [Add α] [Sub α] [OrderedSub α] {a b c : α} a - b ≤ c ↔ a ≤ c + b := OrderedSub.tsub_le_iff_right a b c -variable [Preorder α] [Add α] [Sub α] [OrderedSub α] {a b c d : α} +variable [Preorder α] [Add α] [Sub α] [OrderedSub α] {a b : α} /-- See `add_tsub_cancel_right` for the equality if `ContravariantClass α α (+) (≤)`. -/ theorem add_tsub_le_right : a + b - b ≤ a := @@ -210,7 +210,7 @@ end Contra end AddCommSemigroup -variable [AddCommMonoid α] [Sub α] [OrderedSub α] {a b c d : α} +variable [AddCommMonoid α] [Sub α] [OrderedSub α] {a b : α} theorem tsub_nonpos : a - b ≤ 0 ↔ a ≤ b := by rw [tsub_le_iff_left, add_zero] @@ -243,17 +243,39 @@ theorem tsub_right_comm : a - b - c = a - c - b := by namespace AddLECancellable +/-- See `AddLECancellable.tsub_eq_of_eq_add'` for a version assuming that `a = c + b` itself is +cancellable rather than `b`. -/ protected theorem tsub_eq_of_eq_add (hb : AddLECancellable b) (h : a = c + b) : a - b = c := le_antisymm (tsub_le_iff_right.mpr h.le) <| by rw [h] exact hb.le_add_tsub +/-- Weaker version of `AddLECancellable.tsub_eq_of_eq_add` assuming that `a = c + b` itself is +cancellable rather than `b`. -/ +protected lemma tsub_eq_of_eq_add' [CovariantClass α α (· + ·) (· ≤ ·)] (ha : AddLECancellable a) + (h : a = c + b) : a - b = c := (h ▸ ha).of_add_right.tsub_eq_of_eq_add h + +/-- See `AddLECancellable.eq_tsub_of_add_eq'` for a version assuming that `b = a + c` itself is +cancellable rather than `c`. -/ protected theorem eq_tsub_of_add_eq (hc : AddLECancellable c) (h : a + c = b) : a = b - c := (hc.tsub_eq_of_eq_add h.symm).symm +/-- Weaker version of `AddLECancellable.eq_tsub_of_add_eq` assuming that `b = a + c` itself is +cancellable rather than `c`. -/ +protected lemma eq_tsub_of_add_eq' [CovariantClass α α (· + ·) (· ≤ ·)] (hb : AddLECancellable b) + (h : a + c = b) : a = b - c := (hb.tsub_eq_of_eq_add' h.symm).symm + +/-- See `AddLECancellable.tsub_eq_of_eq_add_rev'` for a version assuming that `a = b + c` itself is +cancellable rather than `b`. -/ protected theorem tsub_eq_of_eq_add_rev (hb : AddLECancellable b) (h : a = b + c) : a - b = c := hb.tsub_eq_of_eq_add <| by rw [add_comm, h] +/-- Weaker version of `AddLECancellable.tsub_eq_of_eq_add_rev` assuming that `a = b + c` itself is +cancellable rather than `b`. -/ +protected lemma tsub_eq_of_eq_add_rev' [CovariantClass α α (· + ·) (· ≤ ·)] + (ha : AddLECancellable a) (h : a = b + c) : a - b = c := + ha.tsub_eq_of_eq_add' <| by rw [add_comm, h] + @[simp] protected theorem add_tsub_cancel_right (hb : AddLECancellable b) : a + b - b = a := hb.tsub_eq_of_eq_add <| by rw [add_comm] @@ -353,7 +375,7 @@ end OrderedAddCommSemigroup section LinearOrder -variable {a b c d : α} [LinearOrder α] [AddCommSemigroup α] [Sub α] [OrderedSub α] +variable {a b c : α} [LinearOrder α] [AddCommSemigroup α] [Sub α] [OrderedSub α] /-- See `lt_of_tsub_lt_tsub_right_of_le` for a weaker statement in a partial order. -/ theorem lt_of_tsub_lt_tsub_right (h : a - c < b - c) : a < b := diff --git a/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean b/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean index 2bf9585fa56a6..fedfe17b0c39c 100644 --- a/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean +++ b/Mathlib/Algebra/Order/Sub/Unbundled/Hom.lean @@ -16,7 +16,7 @@ variable {α β : Type*} section Add -variable [Preorder α] [Add α] [Sub α] [OrderedSub α] {a b c d : α} +variable [Preorder α] [Add α] [Sub α] [OrderedSub α] theorem AddHom.le_map_tsub [Preorder β] [Add β] [Sub β] [OrderedSub β] (f : AddHom α β) (hf : Monotone f) (a b : α) : f a - f b ≤ f (a - b) := by @@ -49,7 +49,7 @@ theorem OrderIso.map_tsub {M N : Type*} [Preorder M] [Add M] [Sub M] [OrderedSub section Preorder variable [Preorder α] -variable [AddCommMonoid α] [Sub α] [OrderedSub α] {a b c d : α} +variable [AddCommMonoid α] [Sub α] [OrderedSub α] theorem AddMonoidHom.le_map_tsub [Preorder β] [AddCommMonoid β] [Sub β] [OrderedSub β] (f : α →+ β) (hf : Monotone f) (a b : α) : f a - f b ≤ f (a - b) := diff --git a/Mathlib/Algebra/Order/ZeroLEOne.lean b/Mathlib/Algebra/Order/ZeroLEOne.lean index ecd0e356d73ad..538c8f6985b42 100644 --- a/Mathlib/Algebra/Order/ZeroLEOne.lean +++ b/Mathlib/Algebra/Order/ZeroLEOne.lean @@ -4,7 +4,6 @@ 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.Order.Basic -import Mathlib.Algebra.NeZero /-! # Typeclass expressing `0 ≤ 1`. diff --git a/Mathlib/Algebra/Polynomial/AlgebraMap.lean b/Mathlib/Algebra/Polynomial/AlgebraMap.lean index 5928ff633fda6..29c855d09a69b 100644 --- a/Mathlib/Algebra/Polynomial/AlgebraMap.lean +++ b/Mathlib/Algebra/Polynomial/AlgebraMap.lean @@ -527,7 +527,7 @@ theorem eval_mul_X_sub_C {p : R[X]} (r : R) : (p * (X - C r)).eval r = 0 := by simp [coeff_monomial] theorem not_isUnit_X_sub_C [Nontrivial R] (r : R) : ¬IsUnit (X - C r) := - fun ⟨⟨_, g, _hfg, hgf⟩, rfl⟩ => zero_ne_one' R <| by erw [← eval_mul_X_sub_C, hgf, eval_one] + fun ⟨⟨_, g, _hfg, hgf⟩, rfl⟩ => zero_ne_one' R <| by rw [← eval_mul_X_sub_C, hgf, eval_one] end Ring diff --git a/Mathlib/Algebra/Polynomial/BigOperators.lean b/Mathlib/Algebra/Polynomial/BigOperators.lean index 32db3b30a3a97..cef12c507490a 100644 --- a/Mathlib/Algebra/Polynomial/BigOperators.lean +++ b/Mathlib/Algebra/Polynomial/BigOperators.lean @@ -68,7 +68,7 @@ theorem degree_list_sum_le (l : List S[X]) : degree l.sum ≤ (l.map natDegree). rw [← List.foldr_max_of_ne_nil] · congr contrapose! h - rw [List.map_eq_nil] at h + rw [List.map_eq_nil_iff] at h simp [h] theorem natDegree_list_prod_le (l : List S[X]) : natDegree l.prod ≤ (l.map natDegree).sum := by diff --git a/Mathlib/Algebra/Polynomial/Degree/CardPowDegree.lean b/Mathlib/Algebra/Polynomial/Degree/CardPowDegree.lean index 1a1dd67ce6467..8b5296df327a3 100644 --- a/Mathlib/Algebra/Polynomial/Degree/CardPowDegree.lean +++ b/Mathlib/Algebra/Polynomial/Degree/CardPowDegree.lean @@ -50,7 +50,7 @@ noncomputable def cardPowDegree : AbsoluteValue Fq[X] ℤ := · rfl exact pow_nonneg (Int.ofNat_zero_le _) _ eq_zero' := fun p => - ite_eq_left_iff.trans <| + ite_eq_left_iff.trans ⟨fun h => by contrapose! h exact ⟨h, (pow_pos _).ne'⟩, absurd⟩ @@ -61,7 +61,7 @@ noncomputable def cardPowDegree : AbsoluteValue Fq[X] ℤ := · simp only [hpq, hp, hq, eq_self_iff_true, if_true, if_false] exact add_nonneg (pow_pos _).le (pow_pos _).le simp only [hpq, hp, hq, if_false] - refine le_trans (pow_le_pow_right (by omega) (Polynomial.natDegree_add_le _ _)) ?_ + refine le_trans (pow_right_mono₀ (by omega) (Polynomial.natDegree_add_le _ _)) ?_ refine le_trans (le_max_iff.mpr ?_) (max_le_add_of_nonneg (pow_nonneg (by omega) _) (pow_nonneg (by omega) _)) diff --git a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean index 1d9ab3832d4fb..3a3fe3f22832f 100644 --- a/Mathlib/Algebra/Polynomial/Degree/Definitions.lean +++ b/Mathlib/Algebra/Polynomial/Degree/Definitions.lean @@ -237,6 +237,12 @@ theorem natDegree_natCast (n : ℕ) : natDegree (n : R[X]) = 0 := by @[deprecated (since := "2024-04-17")] alias natDegree_nat_cast := natDegree_natCast +-- See note [no_index around OfNat.ofNat] +@[simp] +theorem natDegree_ofNat (n : ℕ) [Nat.AtLeastTwo n] : + natDegree (no_index (OfNat.ofNat n : R[X])) = 0 := + natDegree_natCast _ + theorem degree_natCast_le (n : ℕ) : degree (n : R[X]) ≤ 0 := degree_le_of_natDegree_le (by simp) @[deprecated (since := "2024-04-17")] diff --git a/Mathlib/Algebra/Polynomial/Derivative.lean b/Mathlib/Algebra/Polynomial/Derivative.lean index b2767e3897214..9f22f0fa03689 100644 --- a/Mathlib/Algebra/Polynomial/Derivative.lean +++ b/Mathlib/Algebra/Polynomial/Derivative.lean @@ -422,7 +422,7 @@ theorem iterate_derivative_X_pow_eq_natCast_mul (n k : ℕ) : derivative^[k] (X ^ n : R[X]) = ↑(Nat.descFactorial n k : R[X]) * X ^ (n - k) := by induction k with | zero => - erw [Function.iterate_zero_apply, tsub_zero, Nat.descFactorial_zero, Nat.cast_one, one_mul] + rw [Function.iterate_zero_apply, tsub_zero, Nat.descFactorial_zero, Nat.cast_one, one_mul] | succ k ih => rw [Function.iterate_succ_apply', ih, derivative_natCast_mul, derivative_X_pow, C_eq_natCast, Nat.descFactorial_succ, Nat.sub_sub, Nat.cast_mul] diff --git a/Mathlib/Algebra/Polynomial/Expand.lean b/Mathlib/Algebra/Polynomial/Expand.lean index e1db94a64141b..ae212d4a08496 100644 --- a/Mathlib/Algebra/Polynomial/Expand.lean +++ b/Mathlib/Algebra/Polynomial/Expand.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.RingTheory.Polynomial.Basic -import Mathlib.RingTheory.LocalRing.RingHom.Basic /-! # Expand a polynomial by a factor of p, so `∑ aₙ xⁿ` becomes `∑ aₙ xⁿᵖ`. @@ -269,9 +268,8 @@ section IsDomain variable (R : Type u) [CommRing R] [IsDomain R] -theorem isLocalRingHom_expand {p : ℕ} (hp : 0 < p) : - IsLocalRingHom (↑(expand R p) : R[X] →+* R[X]) := by - refine ⟨fun f hf1 => ?_⟩; norm_cast at hf1 +theorem isLocalRingHom_expand {p : ℕ} (hp : 0 < p) : IsLocalRingHom (expand R p) := by + refine ⟨fun f hf1 => ?_⟩ have hf2 := eq_C_of_degree_eq_zero (degree_eq_zero_of_isUnit hf1) rw [coeff_expand hp, if_pos (dvd_zero _), p.zero_div] at hf2 rw [hf2, isUnit_C] at hf1; rw [expand_eq_C hp] at hf2; rwa [hf2, isUnit_C] @@ -281,7 +279,7 @@ variable {R} theorem of_irreducible_expand {p : ℕ} (hp : p ≠ 0) {f : R[X]} (hf : Irreducible (expand R p f)) : Irreducible f := let _ := isLocalRingHom_expand R hp.bot_lt - of_irreducible_map (↑(expand R p)) hf + hf.of_map theorem of_irreducible_expand_pow {p : ℕ} (hp : p ≠ 0) {f : R[X]} {n : ℕ} : Irreducible (expand R (p ^ n) f) → Irreducible f := diff --git a/Mathlib/Algebra/Polynomial/FieldDivision.lean b/Mathlib/Algebra/Polynomial/FieldDivision.lean index 8f5cad434faf7..06134da2f5675 100644 --- a/Mathlib/Algebra/Polynomial/FieldDivision.lean +++ b/Mathlib/Algebra/Polynomial/FieldDivision.lean @@ -382,6 +382,21 @@ theorem map_mod [Field k] (f : R →+* k) : (p % q).map f = p.map f % q.map f := · rw [mod_def, mod_def, leadingCoeff_map f, ← map_inv₀ f, ← map_C f, ← Polynomial.map_mul f, map_modByMonic f (monic_mul_leadingCoeff_inv hq0)] +lemma natDegree_mod_lt [Field k] (p : k[X]) {q : k[X]} (hq : q.natDegree ≠ 0) : + (p % q).natDegree < q.natDegree := by + have hq' : q.leadingCoeff ≠ 0 := by + rw [leadingCoeff_ne_zero] + contrapose! hq + simp [hq] + rw [mod_def] + refine (natDegree_modByMonic_lt p ?_ ?_).trans_le ?_ + · refine monic_mul_C_of_leadingCoeff_mul_eq_one ?_ + rw [mul_inv_eq_one₀ hq'] + · contrapose! hq + rw [← natDegree_mul_C_eq_of_mul_eq_one ((inv_mul_eq_one₀ hq').mpr rfl)] + simp [hq] + · exact natDegree_mul_C_le q q.leadingCoeff⁻¹ + section open EuclideanDomain diff --git a/Mathlib/Algebra/Polynomial/Induction.lean b/Mathlib/Algebra/Polynomial/Induction.lean index 4ba0e2bf397db..a4fc244b867ab 100644 --- a/Mathlib/Algebra/Polynomial/Induction.lean +++ b/Mathlib/Algebra/Polynomial/Induction.lean @@ -26,12 +26,11 @@ open Polynomial universe u v w x y z -variable {R : Type u} {S : Type v} {T : Type w} {ι : Type x} {k : Type y} {A : Type z} {a b : R} - {m n : ℕ} +variable {R : Type u} section Semiring -variable [Semiring R] {p q r : R[X]} +variable [Semiring R] @[elab_as_elim] protected theorem induction_on {M : R[X] → Prop} (p : R[X]) (h_C : ∀ a, M (C a)) diff --git a/Mathlib/Algebra/Polynomial/Module/AEval.lean b/Mathlib/Algebra/Polynomial/Module/AEval.lean index daa261800b354..17b934cb8564e 100644 --- a/Mathlib/Algebra/Polynomial/Module/AEval.lean +++ b/Mathlib/Algebra/Polynomial/Module/AEval.lean @@ -46,7 +46,8 @@ instance instAddCommMonoid : AddCommMonoid <| AEval R M a := inferInstanceAs (Ad instance instModuleOrig : Module R <| AEval R M a := inferInstanceAs (Module R M) -instance instFiniteOrig [Finite R M] : Finite R <| AEval R M a := inferInstanceAs (Finite R M) +instance instFiniteOrig [Module.Finite R M] : Module.Finite R <| AEval R M a := + ‹Module.Finite R M› instance instModulePolynomial : Module R[X] <| AEval R M a := compHom M (aeval a).toRingHom @@ -79,7 +80,7 @@ instance instIsScalarTowerOrigPolynomial : IsScalarTower R R[X] <| AEval R M a w apply (of R M a).symm.injective 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 := +instance instFinitePolynomial [Module.Finite R M] : Module.Finite R[X] <| AEval R M a := Finite.of_restrictScalars_finite R _ _ /-- Construct an `R[X]`-linear map out of `AEval R M a` from a `R`-linear map out of `M`. -/ @@ -193,6 +194,6 @@ lemma AEval'.X_smul_of (m : M) : (X : R[X]) • AEval'.of φ m = AEval'.of φ ( lemma AEval'.of_symm_X_smul (m : AEval' φ) : (AEval'.of φ).symm ((X : R[X]) • m) = φ ((AEval'.of φ).symm m) := AEval.of_symm_X_smul _ _ -instance [Finite R M] : Finite R[X] <| AEval' φ := inferInstance +instance [Module.Finite R M] : Module.Finite R[X] <| AEval' φ := inferInstance end Module diff --git a/Mathlib/Algebra/Polynomial/Module/Basic.lean b/Mathlib/Algebra/Polynomial/Module/Basic.lean index c5e69f5e9a19f..43595606fd85c 100644 --- a/Mathlib/Algebra/Polynomial/Module/Basic.lean +++ b/Mathlib/Algebra/Polynomial/Module/Basic.lean @@ -276,8 +276,7 @@ theorem eval_smul (p : R[X]) (q : PolynomialModule R M) (r : R) : intro i m induction p using Polynomial.induction_on' with | h_add _ _ e₁ e₂ => rw [add_smul, map_add, Polynomial.eval_add, e₁, e₂, add_smul] - | h_monomial => rw [monomial_smul_single, eval_single, Polynomial.eval_monomial, eval_single, - smul_comm, ← smul_smul, pow_add, mul_smul] + | h_monomial => simp only [monomial_smul_single, Polynomial.eval_monomial, eval_single]; module @[simp] theorem eval_map (f : M →ₗ[R] M') (q : PolynomialModule R M) (r : R) : @@ -287,7 +286,8 @@ theorem eval_map (f : M →ₗ[R] M') (q : PolynomialModule R M) (r : R) : · intro f g e₁ e₂ simp_rw [map_add, e₁, e₂] · intro i m - rw [map_single, eval_single, eval_single, f.map_smul, ← map_pow, algebraMap_smul] + simp only [map_single, eval_single, f.map_smul] + module @[simp] theorem eval_map' (f : M →ₗ[R] M) (q : PolynomialModule R M) (r : R) : @@ -312,8 +312,7 @@ noncomputable def comp (p : R[X]) : PolynomialModule R M →ₗ[R] PolynomialMod LinearMap.comp ((eval p).restrictScalars R) (map R[X] (lsingle R 0)) theorem comp_single (p : R[X]) (i : ℕ) (m : M) : comp p (single R i m) = p ^ i • single R 0 m := by - rw [comp_apply] - erw [map_single, eval_single] + rw [comp_apply, map_single, eval_single] rfl theorem comp_eval (p : R[X]) (q : PolynomialModule R M) (r : R) : @@ -324,8 +323,8 @@ theorem comp_eval (p : R[X]) (q : PolynomialModule R M) (r : R) : · intro _ _ e₁ e₂ simp_rw [map_add, e₁, e₂] · intro i m - rw [LinearMap.comp_apply, comp_single, eval_single, eval_smul, eval_single, pow_zero, one_smul, - Polynomial.eval_pow] + rw [LinearMap.comp_apply, comp_single, eval_single, eval_smul, eval_single, eval_pow] + module theorem comp_smul (p p' : R[X]) (q : PolynomialModule R M) : comp p (p' • q) = p'.comp p • comp p q := by diff --git a/Mathlib/Algebra/Polynomial/RingDivision.lean b/Mathlib/Algebra/Polynomial/RingDivision.lean index ab1ca1c76d94d..87a240f259415 100644 --- a/Mathlib/Algebra/Polynomial/RingDivision.lean +++ b/Mathlib/Algebra/Polynomial/RingDivision.lean @@ -548,6 +548,26 @@ theorem rootMultiplicity_mul' {p q : R[X]} {x : R} theorem Monic.comp_X_sub_C {p : R[X]} (hp : p.Monic) (r : R) : (p.comp (X - C r)).Monic := by simpa using hp.comp_X_add_C (-r) +@[simp] +theorem comp_neg_X_leadingCoeff_eq (p : R[X]) : + (p.comp (-X)).leadingCoeff = (-1) ^ p.natDegree * p.leadingCoeff := by + nontriviality R + by_cases h : p = 0 + · simp [h] + rw [Polynomial.leadingCoeff, natDegree_comp_eq_of_mul_ne_zero, coeff_comp_degree_mul_degree] <;> + simp [mul_comm, h] + +theorem Monic.neg_one_pow_natDegree_mul_comp_neg_X {p : R[X]} (hp : p.Monic) : + ((-1) ^ p.natDegree * p.comp (-X)).Monic := by + simp only [Monic] + calc + ((-1) ^ p.natDegree * p.comp (-X)).leadingCoeff = + (p.comp (-X) * C ((-1) ^ p.natDegree)).leadingCoeff := by + simp [mul_comm] + _ = 1 := by + apply monic_mul_C_of_leadingCoeff_mul_eq_one + simp [← pow_add, hp] + variable [IsDomain R] {p q : R[X]} @[simp] diff --git a/Mathlib/Algebra/Polynomial/Smeval.lean b/Mathlib/Algebra/Polynomial/Smeval.lean index 2eb2eecb587a6..d24a7089bfc93 100644 --- a/Mathlib/Algebra/Polynomial/Smeval.lean +++ b/Mathlib/Algebra/Polynomial/Smeval.lean @@ -180,7 +180,7 @@ the defining structures independently. For non-associative power-associative al octonions), we replace the `[Semiring S]` with `[NonAssocSemiring S] [Pow S ℕ] [NatPowAssoc S]`. -/ -variable (R : Type*) [Semiring R] {p : R[X]} (r : R) (p q : R[X]) {S : Type*} +variable (R : Type*) [Semiring R] (r : R) (p q : R[X]) {S : Type*} [NonAssocSemiring S] [Module R S] [Pow S ℕ] (x : S) theorem smeval_C_mul : (C r * p).smeval x = r • p.smeval x := by diff --git a/Mathlib/Algebra/Polynomial/Splits.lean b/Mathlib/Algebra/Polynomial/Splits.lean index 955c85eca5bf7..3b0f053ebb0ea 100644 --- a/Mathlib/Algebra/Polynomial/Splits.lean +++ b/Mathlib/Algebra/Polynomial/Splits.lean @@ -437,7 +437,7 @@ theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} rw [eval_multiset_prod_X_sub_C_derivative hr] /-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/ -theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic) +theorem prod_roots_eq_coeff_zero_of_monic_of_splits {P : K[X]} (hmo : P.Monic) (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP] rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map] @@ -449,6 +449,9 @@ theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic) rw [neg_eq_neg_one_mul] simp only [splits_iff_card_roots.1 hP, neg_mul, one_mul, Multiset.prod_map_neg] +@[deprecated (since := "2024-10-01")] +alias prod_roots_eq_coeff_zero_of_monic_of_split := prod_roots_eq_coeff_zero_of_monic_of_splits + /-- If `P` is a monic polynomial that splits, then `P.nextCoeff` equals the sum of the roots. -/ theorem sum_roots_eq_nextCoeff_of_monic_of_split {P : K[X]} (hmo : P.Monic) (hP : P.Splits (RingHom.id K)) : P.nextCoeff = -P.roots.sum := by diff --git a/Mathlib/Algebra/Polynomial/Taylor.lean b/Mathlib/Algebra/Polynomial/Taylor.lean index 6f9f0e82544ef..4a89d16c0bea7 100644 --- a/Mathlib/Algebra/Polynomial/Taylor.lean +++ b/Mathlib/Algebra/Polynomial/Taylor.lean @@ -125,4 +125,11 @@ theorem sum_taylor_eq {R} [CommRing R] (f : R[X]) (r : R) : rw [← comp_eq_sum_left, sub_eq_add_neg, ← C_neg, ← taylor_apply, taylor_taylor, neg_add_cancel, taylor_zero] +theorem eval_add_of_sq_eq_zero {A} [CommSemiring A] (p : Polynomial A) (x y : A) (hy : y ^ 2 = 0) : + p.eval (x + y) = p.eval x + p.derivative.eval x * y := by + rw [add_comm, ← Polynomial.taylor_eval, + Polynomial.eval_eq_sum_range' ((Nat.lt_succ_self _).trans (Nat.lt_succ_self _)), + Finset.sum_range_succ', Finset.sum_range_succ'] + simp [pow_succ, mul_assoc, ← pow_two, hy, add_comm (eval x p)] + end Polynomial diff --git a/Mathlib/Algebra/QuadraticDiscriminant.lean b/Mathlib/Algebra/QuadraticDiscriminant.lean index 9b17712e3ffaf..157ac8292a0db 100644 --- a/Mathlib/Algebra/QuadraticDiscriminant.lean +++ b/Mathlib/Algebra/QuadraticDiscriminant.lean @@ -15,7 +15,7 @@ This file defines the discriminant of a quadratic and gives the solution to a qu ## Main definition -- `discrim a b c`: the discriminant of a quadratic `a * x * x + b * x + c` is `b * b - 4 * a * c`. +- `discrim a b c`: the discriminant of a quadratic `a * (x * x) + b * x + c` is `b * b - 4 * a * c`. ## Main statements @@ -48,7 +48,7 @@ def discrim [Ring R] (a b c : R) : R := variable [CommRing R] {a b c : R} -lemma discrim_eq_sq_of_quadratic_eq_zero {x : R} (h : a * x * x + b * x + c = 0) : +lemma discrim_eq_sq_of_quadratic_eq_zero {x : R} (h : a * (x * x) + b * x + c = 0) : discrim a b c = (2 * a * x + b) ^ 2 := by rw [discrim] linear_combination -4 * a * h @@ -57,7 +57,7 @@ lemma discrim_eq_sq_of_quadratic_eq_zero {x : R} (h : a * x * x + b * x + c = 0) -/ theorem quadratic_eq_zero_iff_discrim_eq_sq [NeZero (2 : R)] [NoZeroDivisors R] (ha : a ≠ 0) (x : R) : - a * x * x + b * x + c = 0 ↔ discrim a b c = (2 * a * x + b) ^ 2 := by + a * (x * x) + b * x + c = 0 ↔ discrim a b c = (2 * a * x + b) ^ 2 := by refine ⟨discrim_eq_sq_of_quadratic_eq_zero, fun h ↦ ?_⟩ rw [discrim] at h have ha : 2 * 2 * a ≠ 0 := mul_ne_zero (mul_ne_zero (NeZero.ne _) (NeZero.ne _)) ha @@ -66,7 +66,7 @@ theorem quadratic_eq_zero_iff_discrim_eq_sq [NeZero (2 : R)] [NoZeroDivisors R] /-- A quadratic has no root if its discriminant has no square root. -/ theorem quadratic_ne_zero_of_discrim_ne_sq (h : ∀ s : R, discrim a b c ≠ s^2) (x : R) : - a * x * x + b * x + c ≠ 0 := + a * (x * x) + b * x + c ≠ 0 := mt discrim_eq_sq_of_quadratic_eq_zero (h _) end Ring @@ -77,7 +77,7 @@ variable {K : Type*} [Field K] [NeZero (2 : K)] {a b c x : K} /-- Roots of a quadratic equation. -/ theorem quadratic_eq_zero_iff (ha : a ≠ 0) {s : K} (h : discrim a b c = s * s) (x : K) : - a * x * x + b * x + c = 0 ↔ x = (-b + s) / (2 * a) ∨ x = (-b - s) / (2 * a) := by + a * (x * x) + b * x + c = 0 ↔ x = (-b + s) / (2 * a) ∨ x = (-b - s) / (2 * a) := by rw [quadratic_eq_zero_iff_discrim_eq_sq ha, h, sq, mul_self_eq_mul_self_iff] field_simp apply or_congr @@ -86,7 +86,7 @@ theorem quadratic_eq_zero_iff (ha : a ≠ 0) {s : K} (h : discrim a b c = s * s) /-- A quadratic has roots if its discriminant has square roots -/ theorem exists_quadratic_eq_zero (ha : a ≠ 0) (h : ∃ s, discrim a b c = s * s) : - ∃ x, a * x * x + b * x + c = 0 := by + ∃ x, a * (x * x) + b * x + c = 0 := by rcases h with ⟨s, hs⟩ use (-b + s) / (2 * a) rw [quadratic_eq_zero_iff ha hs] @@ -94,7 +94,7 @@ theorem exists_quadratic_eq_zero (ha : a ≠ 0) (h : ∃ s, discrim a b c = s * /-- Root of a quadratic when its discriminant equals zero -/ theorem quadratic_eq_zero_iff_of_discrim_eq_zero (ha : a ≠ 0) (h : discrim a b c = 0) (x : K) : - a * x * x + b * x + c = 0 ↔ x = -b / (2 * a) := by + a * (x * x) + b * x + c = 0 ↔ x = -b / (2 * a) := by have : discrim a b c = 0 * 0 := by rw [h, mul_zero] rw [quadratic_eq_zero_iff ha this, add_zero, sub_zero, or_self_iff] @@ -105,7 +105,7 @@ section LinearOrderedField variable {K : Type*} [LinearOrderedField K] {a b c : K} /-- If a polynomial of degree 2 is always nonnegative, then its discriminant is nonpositive -/ -theorem discrim_le_zero (h : ∀ x : K, 0 ≤ a * x * x + b * x + c) : discrim a b c ≤ 0 := by +theorem discrim_le_zero (h : ∀ x : K, 0 ≤ a * (x * x) + b * x + c) : discrim a b c ≤ 0 := by rw [discrim, sq] obtain ha | rfl | ha : a < 0 ∨ a = 0 ∨ 0 < a := lt_trichotomy a 0 -- if a < 0 @@ -114,7 +114,7 @@ theorem discrim_le_zero (h : ∀ x : K, 0 ≤ a * x * x + b * x + c) : discrim a ((tendsto_atBot_add_const_right _ b (tendsto_id.const_mul_atTop_of_neg ha)).atBot_mul_atTop tendsto_id) rcases (this.eventually (eventually_lt_atBot 0)).exists with ⟨x, hx⟩ - exact False.elim ((h x).not_lt <| by rwa [← add_mul]) + exact False.elim ((h x).not_lt <| by rwa [← mul_assoc, ← add_mul]) -- if a = 0 · rcases eq_or_ne b 0 with (rfl | hb) · simp @@ -127,22 +127,22 @@ theorem discrim_le_zero (h : ∀ x : K, 0 ≤ a * x * x + b * x + c) : discrim a field_simp ring -lemma discrim_le_zero_of_nonpos (h : ∀ x : K, a * x * x + b * x + c ≤ 0) : discrim a b c ≤ 0 := +lemma discrim_le_zero_of_nonpos (h : ∀ x : K, a * (x * x) + b * x + c ≤ 0) : discrim a b c ≤ 0 := discrim_neg a b c ▸ discrim_le_zero <| by simpa only [neg_mul, ← neg_add, neg_nonneg] /-- If a polynomial of degree 2 is always positive, then its discriminant is negative, at least when the coefficient of the quadratic term is nonzero. -/ -theorem discrim_lt_zero (ha : a ≠ 0) (h : ∀ x : K, 0 < a * x * x + b * x + c) : +theorem discrim_lt_zero (ha : a ≠ 0) (h : ∀ x : K, 0 < a * (x * x) + b * x + c) : discrim a b c < 0 := by - have : ∀ x : K, 0 ≤ a * x * x + b * x + c := fun x => le_of_lt (h x) + have : ∀ x : K, 0 ≤ a * (x * x) + b * x + c := fun x => le_of_lt (h x) refine lt_of_le_of_ne (discrim_le_zero this) fun h' ↦ ?_ have := h (-b / (2 * a)) have : a * (-b / (2 * a)) * (-b / (2 * a)) + b * (-b / (2 * a)) + c = 0 := by - rw [quadratic_eq_zero_iff_of_discrim_eq_zero ha h' (-b / (2 * a))] + rw [mul_assoc, quadratic_eq_zero_iff_of_discrim_eq_zero ha h' (-b / (2 * a))] linarith -lemma discrim_lt_zero_of_neg (ha : a ≠ 0) (h : ∀ x : K, a * x * x + b * x + c < 0) : +lemma discrim_lt_zero_of_neg (ha : a ≠ 0) (h : ∀ x : K, a * (x * x) + b * x + c < 0) : discrim a b c < 0 := discrim_neg a b c ▸ discrim_lt_zero (neg_ne_zero.2 ha) <| by simpa only [neg_mul, ← neg_add, neg_pos] diff --git a/Mathlib/Algebra/Quandle.lean b/Mathlib/Algebra/Quandle.lean index a3921e4072e72..f037884dabe10 100644 --- a/Mathlib/Algebra/Quandle.lean +++ b/Mathlib/Algebra/Quandle.lean @@ -100,9 +100,9 @@ class Shelf (α : Type u) where A *unital shelf* is a shelf equipped with an element `1` such that, for all elements `x`, we have both `x ◃ 1` and `1 ◃ x` equal `x`. -/ -class UnitalShelf (α : Type u) extends Shelf α, One α := -(one_act : ∀ a : α, act 1 a = a) -(act_one : ∀ a : α, act a 1 = a) +class UnitalShelf (α : Type u) extends Shelf α, One α where + one_act : ∀ a : α, act 1 a = a + act_one : ∀ a : α, act a 1 = a /-- The type of homomorphisms between shelves. This is also the notion of rack and quandle homomorphisms. diff --git a/Mathlib/Algebra/Quaternion.lean b/Mathlib/Algebra/Quaternion.lean index a063ebfdef089..05c61e0d4e530 100644 --- a/Mathlib/Algebra/Quaternion.lean +++ b/Mathlib/Algebra/Quaternion.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Algebra.Equiv import Mathlib.LinearAlgebra.Dimension.StrongRankCondition import Mathlib.LinearAlgebra.FreeModule.Basic import Mathlib.LinearAlgebra.FreeModule.Finite.Basic -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic /-! # Quaternions @@ -569,8 +569,8 @@ theorem rank_eq_four [StrongRankCondition R] : Module.rank R ℍ[R,c₁,c₂] = rw [rank_eq_card_basis (basisOneIJK c₁ c₂), Fintype.card_fin] norm_num -theorem finrank_eq_four [StrongRankCondition R] : FiniteDimensional.finrank R ℍ[R,c₁,c₂] = 4 := by - rw [FiniteDimensional.finrank, rank_eq_four, Cardinal.toNat_ofNat] +theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R,c₁,c₂] = 4 := by + rw [Module.finrank, rank_eq_four, Cardinal.toNat_ofNat] /-- There is a natural equivalence when swapping the coefficients of a quaternion algebra. -/ @[simps] @@ -1024,7 +1024,7 @@ instance : Module.Free R ℍ[R] := inferInstanceAs <| Module.Free R ℍ[R,-1,-1] theorem rank_eq_four [StrongRankCondition R] : Module.rank R ℍ[R] = 4 := QuaternionAlgebra.rank_eq_four _ _ -theorem finrank_eq_four [StrongRankCondition R] : FiniteDimensional.finrank R ℍ[R] = 4 := +theorem finrank_eq_four [StrongRankCondition R] : Module.finrank R ℍ[R] = 4 := QuaternionAlgebra.finrank_eq_four _ _ @[simp] theorem star_re : (star a).re = a.re := rfl diff --git a/Mathlib/Algebra/Ring/Action/Basic.lean b/Mathlib/Algebra/Ring/Action/Basic.lean index 25558ac78f579..8466b8daf17c7 100644 --- a/Mathlib/Algebra/Ring/Action/Basic.lean +++ b/Mathlib/Algebra/Ring/Action/Basic.lean @@ -42,11 +42,12 @@ class MulSemiringAction (M : Type u) (R : Type v) [Monoid M] [Semiring R] extend section Semiring -variable (M N G : Type*) [Monoid M] [Monoid N] [Group G] -variable (A R S F : Type v) [AddMonoid A] [Semiring R] [CommSemiring S] +variable (M N : Type*) [Monoid M] [Monoid N] +variable (R : Type v) [Semiring R] -- note we could not use `extends` since these typeclasses are made with `old_structure_cmd` -instance (priority := 100) MulSemiringAction.toMulDistribMulAction [h : MulSemiringAction M R] : +instance (priority := 100) MulSemiringAction.toMulDistribMulAction + (M R) {_ : Monoid M} {_ : Semiring R} [h : MulSemiringAction M R] : MulDistribMulAction M R := { h with } @@ -92,8 +93,6 @@ end section SimpLemmas -variable {M G A R F} - attribute [simp] smul_one smul_mul' smul_zero smul_add end SimpLemmas diff --git a/Mathlib/Algebra/Ring/Basic.lean b/Mathlib/Algebra/Ring/Basic.lean index 4ae5170c85619..fd10db100aadd 100644 --- a/Mathlib/Algebra/Ring/Basic.lean +++ b/Mathlib/Algebra/Ring/Basic.lean @@ -40,13 +40,6 @@ def mulRight [Distrib R] (r : R) : AddHom R R where end AddHom -section AddHomClass - -variable {α β F : Type*} [NonAssocSemiring α] [NonAssocSemiring β] - [FunLike F α β] [AddHomClass F α β] - -end AddHomClass - namespace AddMonoidHom /-- Left multiplication by an element of a (semi)ring is an `AddMonoidHom` -/ @@ -105,7 +98,7 @@ end HasDistribNeg section NonUnitalCommRing -variable {α : Type*} [NonUnitalCommRing α] {a b c : α} +variable {α : Type*} [NonUnitalCommRing α] attribute [local simp] add_assoc add_comm add_left_comm mul_comm diff --git a/Mathlib/Algebra/Ring/CentroidHom.lean b/Mathlib/Algebra/Ring/CentroidHom.lean index 25857d52638e5..37a70431efb16 100644 --- a/Mathlib/Algebra/Ring/CentroidHom.lean +++ b/Mathlib/Algebra/Ring/CentroidHom.lean @@ -61,8 +61,8 @@ attribute [nolint docBlame] CentroidHom.toAddMonoidHom /-- `CentroidHomClass F α` states that `F` is a type of centroid homomorphisms. You should extend this class when you extend `CentroidHom`. -/ -class CentroidHomClass (F α : Type*) [NonUnitalNonAssocSemiring α] [FunLike F α α] extends - AddMonoidHomClass F α α : Prop where +class CentroidHomClass (F : Type*) (α : outParam Type*) + [NonUnitalNonAssocSemiring α] [FunLike F α α] extends AddMonoidHomClass F α α : Prop where /-- Commutativity of centroid homomorphims with left multiplication. -/ map_mul_left (f : F) (a b : α) : f (a * b) = a * f b /-- Commutativity of centroid homomorphims with right multiplication. -/ diff --git a/Mathlib/Algebra/Ring/Commute.lean b/Mathlib/Algebra/Ring/Commute.lean index 6793e2df1e30d..27887a07dc5bb 100644 --- a/Mathlib/Algebra/Ring/Commute.lean +++ b/Mathlib/Algebra/Ring/Commute.lean @@ -21,9 +21,9 @@ For the definitions of semirings and rings see `Mathlib.Algebra.Ring.Defs`. -/ -universe u v w x +universe u -variable {α : Type u} {β : Type v} {γ : Type w} {R : Type x} +variable {R : Type u} open Function @@ -75,7 +75,7 @@ end section -variable [MulOneClass R] [HasDistribNeg R] {a : R} +variable [MulOneClass R] [HasDistribNeg R] -- Porting note (#10618): no longer needs to be `@[simp]` since `simp` can prove it. -- @[simp] @@ -147,7 +147,7 @@ alias neg_one_pow_two := neg_one_sq end HasDistribNeg section Ring -variable [Ring R] {a b : R} {n : ℕ} +variable [Ring R] {a : R} {n : ℕ} @[simp] lemma neg_one_pow_mul_eq_zero_iff : (-1) ^ n * a = 0 ↔ a = 0 := by rcases neg_one_pow_eq_or R n with h | h <;> simp [h] diff --git a/Mathlib/Algebra/Ring/Defs.lean b/Mathlib/Algebra/Ring/Defs.lean index 7c35751123577..8ff6a13b2f8f9 100644 --- a/Mathlib/Algebra/Ring/Defs.lean +++ b/Mathlib/Algebra/Ring/Defs.lean @@ -45,9 +45,9 @@ assert_not_exists DivisionMonoid.toDivInvOneMonoid assert_not_exists mul_rotate -universe u v w x +universe u v -variable {α : Type u} {β : Type v} {γ : Type w} {R : Type x} +variable {α : Type u} {R : Type v} open Function @@ -250,7 +250,7 @@ instance (priority := 100) CommSemiring.toCommMonoidWithZero [CommSemiring α] : section CommSemiring -variable [CommSemiring α] {a b c : α} +variable [CommSemiring α] theorem add_mul_self_eq (a b : α) : (a + b) * (a + b) = a * a + 2 * a * b + b * b := by simp only [two_mul, add_mul, mul_add, add_assoc, mul_comm b] @@ -371,7 +371,7 @@ end NonAssocRing section Ring -variable [Ring α] {a b c d e : α} +variable [Ring α] -- A (unital, associative) ring is a not-necessarily-unital ring -- see Note [lower instance priority] diff --git a/Mathlib/Algebra/Ring/Equiv.lean b/Mathlib/Algebra/Ring/Equiv.lean index 1f0c32faab5ea..51c833ecb1d78 100644 --- a/Mathlib/Algebra/Ring/Equiv.lean +++ b/Mathlib/Algebra/Ring/Equiv.lean @@ -5,7 +5,6 @@ Authors: Johannes Hölzl, Callum Sutton, Yury Kudryashov -/ import Mathlib.Algebra.Group.Prod import Mathlib.Algebra.Group.Opposite -import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Algebra.GroupWithZero.InjSurj import Mathlib.Algebra.Ring.Hom.Defs import Mathlib.Logic.Equiv.Set @@ -409,7 +408,7 @@ end Opposite section NonUnitalSemiring -variable [NonUnitalNonAssocSemiring R] [NonUnitalNonAssocSemiring S] (f : R ≃+* S) (x y : R) +variable [NonUnitalNonAssocSemiring R] [NonUnitalNonAssocSemiring S] (f : R ≃+* S) (x : R) /-- A ring isomorphism sends zero to zero. -/ protected theorem map_zero : f 0 = 0 := @@ -533,7 +532,7 @@ end NonUnitalSemiring section Semiring -variable [NonAssocSemiring R] [NonAssocSemiring S] (f : R ≃+* S) (x y : R) +variable [NonAssocSemiring R] [NonAssocSemiring S] (f : R ≃+* S) (x : R) /-- A ring isomorphism sends one to one. -/ protected theorem map_one : f 1 = 1 := @@ -604,7 +603,7 @@ end NonUnitalRing section Ring -variable [NonAssocRing R] [NonAssocRing S] (f : R ≃+* S) (x y : R) +variable [NonAssocRing R] [NonAssocRing S] (f : R ≃+* S) -- Porting note (#10618): `simp` can now prove that, so we remove the `@[simp]` tag theorem map_neg_one : f (-1) = -1 := @@ -805,9 +804,6 @@ protected theorem map_pow (f : R ≃+* S) (a) : ∀ n : ℕ, f (a ^ n) = f a ^ n end GroupPower -protected theorem isUnit_iff (f : R ≃+* S) {a} : IsUnit (f a) ↔ IsUnit a := - MulEquiv.map_isUnit_iff f - end RingEquiv namespace MulEquiv @@ -844,6 +840,33 @@ theorem symm_trans_self (e : R ≃+* S) : e.symm.trans e = RingEquiv.refl S := end RingEquiv +namespace RingEquiv + +variable [NonAssocSemiring R] [NonAssocSemiring S] + +/-- If a ring homomorphism has an inverse, it is a ring isomorphism. -/ +@[simps] +def ofRingHom (f : R →+* S) (g : S →+* R) (h₁ : f.comp g = RingHom.id S) + (h₂ : g.comp f = RingHom.id R) : R ≃+* S := + { f with + toFun := f + invFun := g + left_inv := RingHom.ext_iff.1 h₂ + right_inv := RingHom.ext_iff.1 h₁ } + +theorem coe_ringHom_ofRingHom (f : R →+* S) (g : S →+* R) (h₁ h₂) : ofRingHom f g h₁ h₂ = f := + rfl + +@[simp] +theorem ofRingHom_coe_ringHom (f : R ≃+* S) (g : S →+* R) (h₁ h₂) : ofRingHom (↑f) g h₁ h₂ = f := + ext fun _ ↦ rfl + +theorem ofRingHom_symm (f : R →+* S) (g : S →+* R) (h₁ h₂) : + (ofRingHom f g h₁ h₂).symm = ofRingHom g f h₂ h₁ := + rfl + +end RingEquiv + namespace MulEquiv /-- If two rings are isomorphic, and the second doesn't have zero divisors, diff --git a/Mathlib/Algebra/Ring/Hom/Defs.lean b/Mathlib/Algebra/Ring/Hom/Defs.lean index 6ffa90e13d5da..86672a2bb1c98 100644 --- a/Mathlib/Algebra/Ring/Hom/Defs.lean +++ b/Mathlib/Algebra/Ring/Hom/Defs.lean @@ -153,7 +153,6 @@ end coe section variable [NonUnitalNonAssocSemiring α] [NonUnitalNonAssocSemiring β] -variable (f : α →ₙ+* β) {x y : α} @[ext] theorem ext ⦃f g : α →ₙ+* β⦄ : (∀ x, f x = g x) → f = g := @@ -225,7 +224,6 @@ theorem coe_comp (g : β →ₙ+* γ) (f : α →ₙ+* β) : ⇑(g.comp f) = g @[simp] theorem comp_apply (g : β →ₙ+* γ) (f : α →ₙ+* β) (x : α) : g.comp f x = g (f x) := rfl -variable (g : β →ₙ+* γ) (f : α →ₙ+* β) @[simp] theorem coe_comp_addMonoidHom (g : β →ₙ+* γ) (f : α →ₙ+* β) : @@ -441,7 +439,7 @@ end coe section -variable {_ : NonAssocSemiring α} {_ : NonAssocSemiring β} (f : α →+* β) {x y : α} +variable {_ : NonAssocSemiring α} {_ : NonAssocSemiring β} (f : α →+* β) protected theorem congr_fun {f g : α →+* β} (h : f = g) (x : α) : f x = g x := DFunLike.congr_fun h x diff --git a/Mathlib/Algebra/Ring/Idempotents.lean b/Mathlib/Algebra/Ring/Idempotents.lean index 415b47517507d..80a2c2e0be568 100644 --- a/Mathlib/Algebra/Ring/Idempotents.lean +++ b/Mathlib/Algebra/Ring/Idempotents.lean @@ -5,6 +5,7 @@ Authors: Christopher Hoskin -/ import Mathlib.Algebra.Group.Basic import Mathlib.Algebra.Group.Commute.Defs +import Mathlib.Algebra.Group.Hom.Defs import Mathlib.Algebra.Ring.Defs import Mathlib.Data.Subtype import Mathlib.Order.Notation @@ -49,6 +50,10 @@ theorem mul_of_commute {p q : S} (h : Commute p q) (h₁ : IsIdempotentElem p) (h₂ : IsIdempotentElem q) : IsIdempotentElem (p * q) := by rw [IsIdempotentElem, mul_assoc, ← mul_assoc q, ← h.eq, mul_assoc p, h₂.eq, ← mul_assoc, h₁.eq] +lemma mul {M} [CommSemigroup M] {e₁ e₂ : M} + (he₁ : IsIdempotentElem e₁) (he₂ : IsIdempotentElem e₂) : IsIdempotentElem (e₁ * e₂) := + he₁.mul_of_commute (.all e₁ e₂) he₂ + theorem zero : IsIdempotentElem (0 : M₀) := mul_zero _ @@ -83,6 +88,10 @@ theorem iff_eq_zero_or_one {p : G₀} : IsIdempotentElem p ↔ p = 0 ∨ p = 1 : h.elim (fun hp => hp.symm ▸ zero) fun hp => hp.symm ▸ one exact mul_left_cancel₀ hp (h.trans (mul_one p).symm) +lemma map {M N F} [Mul M] [Mul N] [FunLike F M N] [MulHomClass F M N] {e : M} + (he : IsIdempotentElem e) (f : F) : IsIdempotentElem (f e) := by + rw [IsIdempotentElem, ← map_mul, he.eq] + /-! ### Instances on `Subtype IsIdempotentElem` -/ diff --git a/Mathlib/Algebra/Ring/InjSurj.lean b/Mathlib/Algebra/Ring/InjSurj.lean index a16aaee0516ab..adfe2cb5d8a38 100644 --- a/Mathlib/Algebra/Ring/InjSurj.lean +++ b/Mathlib/Algebra/Ring/InjSurj.lean @@ -46,8 +46,8 @@ protected abbrev hasDistribNeg (f : β → α) (hf : Injective f) [Mul α] [HasD (neg : ∀ a, f (-a) = -f a) (mul : ∀ a b, f (a * b) = f a * f b) : HasDistribNeg β := { hf.involutiveNeg _ neg, ‹Mul β› with - neg_mul := fun x y => hf <| by erw [neg, mul, neg, neg_mul, mul], - mul_neg := fun x y => hf <| by erw [neg, mul, neg, mul_neg, mul] } + neg_mul := fun x y => hf <| by rw [neg, mul, neg, neg_mul, mul], + mul_neg := fun x y => hf <| by rw [neg, mul, neg, mul_neg, mul] } /-- Pullback a `NonUnitalNonAssocSemiring` instance along an injective function. -/ -- See note [reducible non-instances] @@ -226,8 +226,8 @@ preserves `-` and `*` from a type which has distributive negation. -/ protected abbrev hasDistribNeg [Mul α] [HasDistribNeg α] (neg : ∀ a, f (-a) = -f a) (mul : ∀ a b, f (a * b) = f a * f b) : HasDistribNeg β := { hf.involutiveNeg _ neg, ‹Mul β› with - neg_mul := hf.forall₂.2 fun x y => by erw [← neg, ← mul, neg_mul, neg, mul] - mul_neg := hf.forall₂.2 fun x y => by erw [← neg, ← mul, mul_neg, neg, mul] } + neg_mul := hf.forall₂.2 fun x y => by rw [← neg, ← mul, neg_mul, neg, mul] + mul_neg := hf.forall₂.2 fun x y => by rw [← neg, ← mul, mul_neg, neg, mul] } /-- Pushforward a `NonUnitalNonAssocSemiring` instance along a surjective function. See note [reducible non-instances]. -/ diff --git a/Mathlib/Algebra/Ring/Int.lean b/Mathlib/Algebra/Ring/Int.lean index 8848a57ffc4d7..8fb0dd29430dc 100644 --- a/Mathlib/Algebra/Ring/Int.lean +++ b/Mathlib/Algebra/Ring/Int.lean @@ -97,6 +97,8 @@ lemma odd_iff : Odd n ↔ n % 2 = 1 where lemma not_odd_iff : ¬Odd n ↔ n % 2 = 0 := by rw [odd_iff, emod_two_ne_one] +@[simp] lemma not_odd_zero : ¬Odd (0 : ℤ) := not_odd_iff.mpr rfl + @[simp] lemma not_odd_iff_even : ¬Odd n ↔ Even n := by rw [not_odd_iff, even_iff] @[simp] lemma not_even_iff_odd : ¬Even n ↔ Odd n := by rw [not_even_iff, odd_iff] diff --git a/Mathlib/Algebra/Ring/Parity.lean b/Mathlib/Algebra/Ring/Parity.lean index 8d540524abfb4..9205b9aeff65a 100644 --- a/Mathlib/Algebra/Ring/Parity.lean +++ b/Mathlib/Algebra/Ring/Parity.lean @@ -214,6 +214,8 @@ lemma not_odd_iff : ¬Odd n ↔ n % 2 = 0 := by rw [odd_iff, mod_two_ne_one] @[simp] lemma not_odd_iff_even : ¬Odd n ↔ Even n := by rw [not_odd_iff, even_iff] @[simp] lemma not_even_iff_odd : ¬Even n ↔ Odd n := by rw [not_even_iff, odd_iff] +@[simp] lemma not_odd_zero : ¬Odd 0 := not_odd_iff.mpr rfl + @[deprecated not_odd_iff_even (since := "2024-08-21")] lemma even_iff_not_odd : Even n ↔ ¬Odd n := by rw [not_odd_iff, even_iff] diff --git a/Mathlib/Algebra/Ring/Pointwise/Set.lean b/Mathlib/Algebra/Ring/Pointwise/Set.lean index 4da48ed12ad44..5ec371a33579c 100644 --- a/Mathlib/Algebra/Ring/Pointwise/Set.lean +++ b/Mathlib/Algebra/Ring/Pointwise/Set.lean @@ -3,7 +3,7 @@ Copyright (c) 2019 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Floris van Doorn -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Ring.Defs /-! @@ -32,8 +32,7 @@ protected noncomputable def hasDistribNeg [Mul α] [HasDistribNeg α] : HasDistr neg_mul _ _ := by simp_rw [← image_neg]; exact image2_image_left_comm neg_mul mul_neg _ _ := by simp_rw [← image_neg]; exact image_image2_right_comm mul_neg -scoped[Pointwise] - attribute [instance] Set.divisionCommMonoid Set.subtractionCommMonoid Set.hasDistribNeg +scoped[Pointwise] attribute [instance] Set.hasDistribNeg section Distrib variable [Distrib α] (s t u : Set α) diff --git a/Mathlib/Algebra/Ring/Semiconj.lean b/Mathlib/Algebra/Ring/Semiconj.lean index 7ca35cfbf5af9..8b20e68a71a06 100644 --- a/Mathlib/Algebra/Ring/Semiconj.lean +++ b/Mathlib/Algebra/Ring/Semiconj.lean @@ -19,9 +19,9 @@ For the definitions of semirings and rings see `Mathlib.Algebra.Ring.Defs`. -/ -universe u v w x +universe u -variable {α : Type u} {β : Type v} {γ : Type w} {R : Type x} +variable {R : Type u} open Function @@ -59,7 +59,7 @@ end section -variable [MulOneClass R] [HasDistribNeg R] {a x y : R} +variable [MulOneClass R] [HasDistribNeg R] -- Porting note: `simpNF` told me to remove `simp` attribute theorem neg_one_right (a : R) : SemiconjBy a (-1) (-1) := diff --git a/Mathlib/Algebra/Ring/Subring/Basic.lean b/Mathlib/Algebra/Ring/Subring/Basic.lean index dece9ec6923b9..4d2d0317d2fcf 100644 --- a/Mathlib/Algebra/Ring/Subring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subring/Basic.lean @@ -72,7 +72,7 @@ section SubringClass /-- `SubringClass S R` states that `S` is a type of subsets `s ⊆ R` that are both a multiplicative submonoid and an additive subgroup. -/ -class SubringClass (S : Type*) (R : Type u) [Ring R] [SetLike S R] extends +class SubringClass (S : Type*) (R : outParam (Type u)) [Ring R] [SetLike S R] extends SubsemiringClass S R, NegMemClass S R : Prop -- See note [lower instance priority] diff --git a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean index 03dc4ba71c416..3fd3c93c9cef4 100644 --- a/Mathlib/Algebra/Ring/Subsemiring/Basic.lean +++ b/Mathlib/Algebra/Ring/Subsemiring/Basic.lean @@ -27,7 +27,7 @@ section AddSubmonoidWithOneClass /-- `AddSubmonoidWithOneClass S R` says `S` is a type of subsets `s ≤ R` that contain `0`, `1`, and are closed under `(+)` -/ -class AddSubmonoidWithOneClass (S R : Type*) [AddMonoidWithOne R] +class AddSubmonoidWithOneClass (S : Type*) (R : outParam Type*) [AddMonoidWithOne R] [SetLike S R] extends AddSubmonoidClass S R, OneMemClass S R : Prop variable {S R : Type*} [AddMonoidWithOne R] [SetLike S R] (s : S) @@ -59,12 +59,12 @@ section SubsemiringClass /-- `SubsemiringClass S R` states that `S` is a type of subsets `s ⊆ R` that are both a multiplicative and an additive submonoid. -/ -class SubsemiringClass (S : Type*) (R : Type u) [NonAssocSemiring R] +class SubsemiringClass (S : Type*) (R : outParam (Type u)) [NonAssocSemiring R] [SetLike S R] extends SubmonoidClass S R, AddSubmonoidClass S R : Prop -- See note [lower instance priority] instance (priority := 100) SubsemiringClass.addSubmonoidWithOneClass (S : Type*) - (R : Type u) [NonAssocSemiring R] [SetLike S R] [h : SubsemiringClass S R] : + (R : Type u) {_ : NonAssocSemiring R} [SetLike S R] [h : SubsemiringClass S R] : AddSubmonoidWithOneClass S R := { h with } @@ -791,7 +791,7 @@ theorem mem_closure_iff_exists_list {R} [Semiring R] {s : Set R} {x} : ⟨[t], List.forall_mem_singleton.2 ht1, by rw [List.map_singleton, List.sum_singleton, ht2]⟩ Submonoid.closure_induction hx - (fun x hx => ⟨[x], List.forall_mem_singleton.2 hx, one_mul x⟩) + (fun x hx => ⟨[x], List.forall_mem_singleton.2 hx, List.prod_singleton⟩) ⟨[], List.forall_mem_nil _, rfl⟩ fun x y ⟨t, ht1, ht2⟩ ⟨u, hu1, hu2⟩ => ⟨t ++ u, List.forall_mem_append.2 ⟨ht1, hu1⟩, by rw [List.prod_append, ht2, hu2]⟩) ⟨[], List.forall_mem_nil _, rfl⟩ fun x y ⟨L, HL1, HL2⟩ ⟨M, HM1, HM2⟩ => diff --git a/Mathlib/Algebra/Ring/SumsOfSquares.lean b/Mathlib/Algebra/Ring/SumsOfSquares.lean index 1eb9bb77744cf..6abec158dd334 100644 --- a/Mathlib/Algebra/Ring/SumsOfSquares.lean +++ b/Mathlib/Algebra/Ring/SumsOfSquares.lean @@ -3,9 +3,8 @@ Copyright (c) 2024 Florent Schaffhauser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Florent Schaffhauser -/ -import Mathlib.Algebra.Ring.Defs +import Mathlib.Algebra.BigOperators.Group.Finset import Mathlib.Algebra.Group.Submonoid.Basic -import Mathlib.Algebra.Group.Even import Mathlib.Algebra.Order.Ring.Defs /-! @@ -61,6 +60,15 @@ theorem IsSumSq.add [AddMonoid R] {S1 S2 : R} (p1 : IsSumSq S1) @[deprecated (since := "2024-08-09")] alias isSumSq.add := IsSumSq.add +/-- A finite sum of squares is a sum of squares. -/ +theorem isSumSq_sum_mul_self {ι : Type*} [AddCommMonoid R] (s : Finset ι) (f : ι → R) : + IsSumSq (∑ i ∈ s, f i * f i) := by + induction s using Finset.cons_induction with + | empty => + simpa only [Finset.sum_empty] using IsSumSq.zero + | cons i s his h => + exact (Finset.sum_cons (β := R) his) ▸ IsSumSq.sq_add (f i) (∑ i ∈ s, f i * f i) h + variable (R) in /-- In an additive monoid with multiplication `R`, the type `sumSqIn R` is the submonoid of sums of diff --git a/Mathlib/Algebra/Ring/Units.lean b/Mathlib/Algebra/Ring/Units.lean index fbcb29f67829f..619def14cb01a 100644 --- a/Mathlib/Algebra/Ring/Units.lean +++ b/Mathlib/Algebra/Ring/Units.lean @@ -15,7 +15,7 @@ import Mathlib.Algebra.Ring.Hom.Defs universe u v w x -variable {α : Type u} {β : Type v} {γ : Type w} {R : Type x} +variable {α : Type u} {β : Type v} {R : Type x} open Function @@ -23,7 +23,7 @@ namespace Units section HasDistribNeg -variable [Monoid α] [HasDistribNeg α] {a b : α} +variable [Monoid α] [HasDistribNeg α] /-- Each element of the group of units of a ring has an additive inverse. -/ instance : Neg αˣ := @@ -49,7 +49,7 @@ end HasDistribNeg section Ring -variable [Ring α] {a b : α} +variable [Ring α] -- Needs to have higher simp priority than divp_add_divp. 1000 is the default priority. @[field_simps 1010] diff --git a/Mathlib/Algebra/SMulWithZero.lean b/Mathlib/Algebra/SMulWithZero.lean index ae84ec92e750d..b897e154bd18f 100644 --- a/Mathlib/Algebra/SMulWithZero.lean +++ b/Mathlib/Algebra/SMulWithZero.lean @@ -126,7 +126,8 @@ class MulActionWithZero extends MulAction R M where zero_smul : ∀ m : M, (0 : R) • m = 0 -- see Note [lower instance priority] -instance (priority := 100) MulActionWithZero.toSMulWithZero [m : MulActionWithZero R M] : +instance (priority := 100) MulActionWithZero.toSMulWithZero + (R M) {_ : MonoidWithZero R} {_ : Zero M} [m : MulActionWithZero R M] : SMulWithZero R M := { m with } diff --git a/Mathlib/Algebra/Star/Conjneg.lean b/Mathlib/Algebra/Star/Conjneg.lean index 1fb96695c6371..9b9c3b54defe4 100644 --- a/Mathlib/Algebra/Star/Conjneg.lean +++ b/Mathlib/Algebra/Star/Conjneg.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.BigOperators.Pi -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Star.Pi /-! diff --git a/Mathlib/Algebra/Star/Free.lean b/Mathlib/Algebra/Star/Free.lean index eefbd4ba0c208..b29ed2137d81e 100644 --- a/Mathlib/Algebra/Star/Free.lean +++ b/Mathlib/Algebra/Star/Free.lean @@ -48,7 +48,7 @@ instance : StarRing (FreeAlgebra R X) where unfold Star.star simp only [Function.comp_apply] let y := lift R (X := X) (MulOpposite.op ∘ ι R) - apply induction (C := fun x ↦ (y (y x).unop).unop = x) _ _ _ _ x + refine induction (C := fun x ↦ (y (y x).unop).unop = x) _ _ ?_ ?_ ?_ ?_ x · intros simp only [AlgHom.commutes, MulOpposite.algebraMap_apply, MulOpposite.unop_op] · intros diff --git a/Mathlib/Algebra/Star/Module.lean b/Mathlib/Algebra/Star/Module.lean index b062492e6acbd..214d513fed01a 100644 --- a/Mathlib/Algebra/Star/Module.lean +++ b/Mathlib/Algebra/Star/Module.lean @@ -75,11 +75,43 @@ theorem star_ratCast_smul [DivisionRing R] [AddCommGroup M] [Module R M] [StarAd @[deprecated (since := "2024-04-17")] alias star_rat_cast_smul := star_ratCast_smul -@[simp] -theorem star_rat_smul {R : Type*} [AddCommGroup R] [StarAddMonoid R] [Module ℚ R] (x : R) (n : ℚ) : - star (n • x) = n • star x := +/-! +Per the naming convention, these two lemmas call `(q • ·)` `nnrat_smul` and `rat_smul` respectively, +rather than `nnqsmul` and `qsmul` because the latter are reserved to the actions coming from +`DivisionSemiring` and `DivisionRing`. We provide aliases with `nnqsmul` and `qsmul` for +discoverability. +-/ + +/-- Note that this lemma holds for an arbitrary `ℚ≥0`-action, rather than merely one coming from a +`DivisionSemiring`. We keep both the `nnqsmul` and `nnrat_smul` naming conventions for +discoverability. See `star_nnqsmul`. -/ +@[simp high] +lemma star_nnrat_smul [AddCommMonoid R] [StarAddMonoid R] [Module ℚ≥0 R] (q : ℚ≥0) (x : R) : + star (q • x) = q • star x := map_nnrat_smul (starAddEquiv : R ≃+ R) _ _ + +/-- Note that this lemma holds for an arbitrary `ℚ`-action, rather than merely one coming from a +`DivisionRing`. We keep both the `qsmul` and `rat_smul` naming conventions for discoverability. +See `star_qsmul`. -/ +@[simp high] lemma star_rat_smul [AddCommGroup R] [StarAddMonoid R] [Module ℚ R] (q : ℚ) (x : R) : + star (q • x) = q • star x := map_rat_smul (starAddEquiv : R ≃+ R) _ _ +/-- Note that this lemma holds for an arbitrary `ℚ≥0`-action, rather than merely one coming from a +`DivisionSemiring`. We keep both the `nnqsmul` and `nnrat_smul` naming conventions for +discoverability. See `star_nnrat_smul`. -/ +alias star_nnqsmul := star_nnrat_smul + +/-- Note that this lemma holds for an arbitrary `ℚ`-action, rather than merely one coming from a +`DivisionRing`. We keep both the `qsmul` and `rat_smul` naming conventions for +discoverability. See `star_rat_smul`. -/ +alias star_qsmul := star_rat_smul + +instance StarAddMonoid.toStarModuleNNRat [AddCommMonoid R] [Module ℚ≥0 R] [StarAddMonoid R] : + StarModule ℚ≥0 R where star_smul := star_nnrat_smul + +instance StarAddMonoid.toStarModuleRat [AddCommGroup R] [Module ℚ R] [StarAddMonoid R] : + StarModule ℚ R where star_smul := star_rat_smul + end SMulLemmas /-- If `A` is a module over a commutative `R` with compatible actions, @@ -184,8 +216,8 @@ def StarModule.decomposeProdAdjoint : A ≃ₗ[R] selfAdjoint A × skewAdjoint A refine LinearEquiv.ofLinear ((selfAdjointPart R).prod (skewAdjointPart R)) (LinearMap.coprod ((selfAdjoint.submodule R A).subtype) (skewAdjoint.submodule R A).subtype) ?_ (LinearMap.ext <| StarModule.selfAdjointPart_add_skewAdjointPart R) - -- Note: with #6965 `Submodule.coeSubtype` doesn't fire in `dsimp` or `simp` - ext x <;> dsimp <;> erw [Submodule.coeSubtype, Submodule.coeSubtype] <;> simp + -- Note: with #6965 `Submodule.coe_subtype` doesn't fire in `dsimp` or `simp` + ext x <;> dsimp <;> erw [Submodule.coe_subtype, Submodule.coe_subtype] <;> simp end SelfSkewAdjoint diff --git a/Mathlib/Algebra/Star/Pointwise.lean b/Mathlib/Algebra/Star/Pointwise.lean index 58c6df130b0b7..6c37067eee6ab 100644 --- a/Mathlib/Algebra/Star/Pointwise.lean +++ b/Mathlib/Algebra/Star/Pointwise.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Jireh Loreaux. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Star.Basic import Mathlib.Data.Set.Finite diff --git a/Mathlib/Algebra/TrivSqZeroExt.lean b/Mathlib/Algebra/TrivSqZeroExt.lean index 0e976107f9917..c40ab975c18d7 100644 --- a/Mathlib/Algebra/TrivSqZeroExt.lean +++ b/Mathlib/Algebra/TrivSqZeroExt.lean @@ -147,6 +147,12 @@ theorem snd_comp_inr [Zero R] : snd ∘ (inr : M → tsze R M) = id := end +theorem fst_surjective [Nonempty M] : Function.Surjective (fst : tsze R M → R) := + Prod.fst_surjective + +theorem snd_surjective [Nonempty R] : Function.Surjective (snd : tsze R M → M) := + Prod.snd_surjective + theorem inl_injective [Zero M] : Function.Injective (inl : R → tsze R M) := Function.LeftInverse.injective <| fst_inl _ @@ -226,6 +232,16 @@ instance module [Semiring S] [AddCommMonoid R] [AddCommMonoid M] [Module S R] [M Module S (tsze R M) := Prod.instModule +/-- The trivial square-zero extension is nontrivial if it is over a nontrivial ring. -/ +instance instNontrivial_of_left {R M : Type*} [Nontrivial R] [Nonempty M] : + Nontrivial (TrivSqZeroExt R M) := + fst_surjective.nontrivial + +/-- The trivial square-zero extension is nontrivial if it is over a nontrivial module. -/ +instance instNontrivial_of_right {R M : Type*} [Nonempty R] [Nontrivial M] : + Nontrivial (TrivSqZeroExt R M) := + snd_surjective.nontrivial + @[simp] theorem fst_zero [Zero R] [Zero M] : (0 : tsze R M).fst = 0 := rfl @@ -690,7 +706,9 @@ section Inv variable {R : Type u} {M : Type v} variable [Neg M] [Inv R] [SMul Rᵐᵒᵖ M] [SMul R M] -/-- Inversion of the trivial-square-zero extension, sending $r + m$ to $r^{-1} - r^{-1}mr^{-1}$. -/ +/-- Inversion of the trivial-square-zero extension, sending $r + m$ to $r^{-1} - r^{-1}mr^{-1}$. + +Strictly this is only a _two_-sided inverse when the left and right actions associate. -/ instance instInv : Inv (tsze R M) := ⟨fun b => (b.1⁻¹, -(b.1⁻¹ •> b.2 <• b.1⁻¹))⟩ @@ -702,6 +720,75 @@ instance instInv : Inv (tsze R M) := end Inv +/-! This section is heavily inspired by analogous results about matrices. -/ +section Invertible +variable {R : Type u} {M : Type v} +variable [AddCommGroup M] [Semiring R] [Module Rᵐᵒᵖ M] [Module R M] + +/-- `x.fst : R` is invertible when `x : tzre R M` is. -/ +abbrev invertibleFstOfInvertible (x : tsze R M) [Invertible x] : Invertible x.fst where + invOf := (⅟x).fst + invOf_mul_self := by rw [← fst_mul, invOf_mul_self, fst_one] + mul_invOf_self := by rw [← fst_mul, mul_invOf_self, fst_one] + +theorem fst_invOf (x : tsze R M) [Invertible x] [Invertible x.fst] : (⅟x).fst = ⅟(x.fst) := by + letI := invertibleFstOfInvertible x + convert (rfl : _ = ⅟ x.fst) + +theorem mul_left_eq_one (r : R) (x : tsze R M) (h : r * x.fst = 1) : + (inl r + inr (-((r •> x.snd) <• r))) * x = 1 := by + ext <;> dsimp + · rw [add_zero, h] + · rw [add_zero, zero_add, smul_neg, op_smul_op_smul, h, op_one, one_smul, + add_neg_cancel] + +theorem mul_right_eq_one (x : tsze R M) (r : R) (h : x.fst * r = 1) : + x * (inl r + inr (-(r •> (x.snd <• r)))) = 1 := by + ext <;> dsimp + · rw [add_zero, h] + · rw [add_zero, zero_add, smul_neg, smul_smul, h, one_smul, neg_add_cancel] + +variable [SMulCommClass R Rᵐᵒᵖ M] + +/-- `x : tzre R M` is invertible when `x.fst : R` is. -/ +abbrev invertibleOfInvertibleFst (x : tsze R M) [Invertible x.fst] : Invertible x where + invOf := (⅟x.fst, -(⅟x.fst •> x.snd <• ⅟x.fst)) + invOf_mul_self := by + convert mul_left_eq_one _ _ (invOf_mul_self x.fst) + ext <;> simp + mul_invOf_self := by + convert mul_right_eq_one _ _ (mul_invOf_self x.fst) + ext <;> simp [smul_comm] + +theorem snd_invOf (x : tsze R M) [Invertible x] [Invertible x.fst] : + (⅟x).snd = -(⅟x.fst •> x.snd <• ⅟x.fst) := by + letI := invertibleOfInvertibleFst x + convert congr_arg (TrivSqZeroExt.snd (R := R) (M := M)) (_ : _ = ⅟ x) + convert rfl + +/-- Together `TrivSqZeroExt.detInvertibleOfInvertible` and `TrivSqZeroExt.invertibleOfDetInvertible` +form an equivalence, although both sides of the equiv are subsingleton anyway. -/ +@[simps] +def invertibleEquivInvertibleFst (x : tsze R M) : Invertible x ≃ Invertible x.fst where + toFun _ := invertibleFstOfInvertible x + invFun _ := invertibleOfInvertibleFst x + left_inv _ := Subsingleton.elim _ _ + right_inv _ := Subsingleton.elim _ _ + +/-- When lowered to a prop, `Matrix.invertibleEquivInvertibleFst` forms an `iff`. -/ +theorem isUnit_iff_isUnit_fst {x : tsze R M} : IsUnit x ↔ IsUnit x.fst := by + simp only [← nonempty_invertible_iff_isUnit, (invertibleEquivInvertibleFst x).nonempty_congr] + +@[simp] +theorem isUnit_inl_iff {r : R} : IsUnit (inl r : tsze R M) ↔ IsUnit r := by + rw [isUnit_iff_isUnit_fst, fst_inl] + +@[simp] +theorem isUnit_inr_iff {m : M} : IsUnit (inr m : tsze R M) ↔ Subsingleton R := by + simp_rw [isUnit_iff_isUnit_fst, fst_inr, isUnit_zero_iff, subsingleton_iff_zero_eq_one] + +end Invertible + section DivisionSemiring variable {R : Type u} {M : Type v} variable [DivisionSemiring R] [AddCommGroup M] [Module Rᵐᵒᵖ M] [Module R M] @@ -727,18 +814,19 @@ protected theorem inv_one : (1 : tsze R M)⁻¹ = (1 : tsze R M) := by rw [← inl_one, TrivSqZeroExt.inv_inl, inv_one] protected theorem inv_mul_cancel {x : tsze R M} (hx : fst x ≠ 0) : x⁻¹ * x = 1 := by - ext - · rw [fst_mul, fst_inv, inv_mul_cancel₀ hx, fst_one] - · rw [snd_mul, snd_inv, snd_one, smul_neg, op_smul_op_smul, inv_mul_cancel₀ hx, op_one, one_smul, - fst_inv, add_neg_cancel] + convert mul_left_eq_one _ _ (_root_.inv_mul_cancel₀ hx) using 2 + ext <;> simp variable [SMulCommClass R Rᵐᵒᵖ M] +@[simp] theorem invOf_eq_inv (x : tsze R M) [Invertible x] : ⅟x = x⁻¹ := by + letI := invertibleFstOfInvertible x + ext <;> simp [fst_invOf, snd_invOf] + protected theorem mul_inv_cancel {x : tsze R M} (hx : fst x ≠ 0) : x * x⁻¹ = 1 := by - ext - · rw [fst_mul, fst_inv, fst_one, mul_inv_cancel₀ hx] - · rw [snd_mul, snd_inv, snd_one, smul_neg, smul_comm, smul_smul, mul_inv_cancel₀ hx, one_smul, - fst_inv, neg_add_cancel] + have : Invertible x.fst := Units.invertible (.mk0 _ hx) + have := invertibleOfInvertibleFst x + rw [← invOf_eq_inv, mul_invOf_self] protected theorem mul_inv_rev (a b : tsze R M) : (a * b)⁻¹ = b⁻¹ * a⁻¹ := by @@ -763,6 +851,10 @@ protected theorem inv_inv {x : tsze R M} (hx : fst x ≠ 0) : x⁻¹⁻¹ = x := rw [fst_inv] apply inv_ne_zero hx +@[simp] +theorem isUnit_inv_iff {x : tsze R M} : IsUnit x⁻¹ ↔ IsUnit x := by + simp_rw [isUnit_iff_isUnit_fst, fst_inv, isUnit_iff_ne_zero, ne_eq, inv_eq_zero] + end DivisionSemiring section DivisionRing diff --git a/Mathlib/AlgebraicGeometry/AffineScheme.lean b/Mathlib/AlgebraicGeometry/AffineScheme.lean index 56989b5600798..fbc5e7b02e459 100644 --- a/Mathlib/AlgebraicGeometry/AffineScheme.lean +++ b/Mathlib/AlgebraicGeometry/AffineScheme.lean @@ -8,6 +8,7 @@ import Mathlib.AlgebraicGeometry.Restrict import Mathlib.AlgebraicGeometry.Cover.Open import Mathlib.CategoryTheory.Limits.Opposites import Mathlib.RingTheory.Localization.InvSubmonoid +import Mathlib.RingTheory.RingHom.Surjective /-! # Affine schemes @@ -52,24 +53,26 @@ deriving Category /-- A Scheme is affine if the canonical map `X ⟶ Spec Γ(X)` is an isomorphism. -/ class IsAffine (X : Scheme) : Prop where - affine : IsIso (ΓSpec.adjunction.unit.app X) + affine : IsIso X.toSpecΓ attribute [instance] IsAffine.affine +instance (X : Scheme.{u}) [IsAffine X] : IsIso (ΓSpec.adjunction.unit.app X) := @IsAffine.affine X _ + /-- The canonical isomorphism `X ≅ Spec Γ(X)` for an affine scheme. -/ @[simps! (config := .lemmasOnly) hom] def Scheme.isoSpec (X : Scheme) [IsAffine X] : X ≅ Spec Γ(X, ⊤) := - asIso (ΓSpec.adjunction.unit.app X) + asIso X.toSpecΓ @[reassoc] theorem Scheme.isoSpec_hom_naturality {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) : X.isoSpec.hom ≫ Spec.map (f.app ⊤) = f ≫ Y.isoSpec.hom := by - simp only [isoSpec, asIso_hom, ΓSpec.adjunction_unit_naturality] + simp only [isoSpec, asIso_hom, Scheme.toSpecΓ_naturality] @[reassoc] theorem Scheme.isoSpec_inv_naturality {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Y) : Spec.map (f.app ⊤) ≫ Y.isoSpec.inv = X.isoSpec.inv ≫ f := by - rw [Iso.eq_inv_comp, isoSpec, asIso_hom, ← ΓSpec.adjunction_unit_naturality_assoc, isoSpec, + rw [Iso.eq_inv_comp, isoSpec, asIso_hom, ← Scheme.toSpecΓ_naturality_assoc, isoSpec, asIso_inv, IsIso.hom_inv_id, Category.comp_id] /-- Construct an affine scheme from a scheme and the information that it is affine. @@ -111,6 +114,25 @@ def arrowIsoSpecΓOfIsAffine {X Y : Scheme} [IsAffine X] [IsAffine Y] (f : X ⟶ Arrow.mk f ≅ Arrow.mk (Spec.map (Scheme.Γ.map f.op)) := Arrow.isoMk X.isoSpec Y.isoSpec (ΓSpec.adjunction.unit_naturality _) +/-- If `f : A ⟶ B` is a ring homomorphism, the corresponding arrow is isomorphic +to the arrow of the morphism induced on global sections by the map on prime spectra. -/ +def arrowIsoΓSpecOfIsAffine {A B : CommRingCat} (f : A ⟶ B) : + Arrow.mk f ≅ Arrow.mk ((Spec.map f).app ⊤) := + Arrow.isoMk (Scheme.ΓSpecIso _).symm (Scheme.ΓSpecIso _).symm + (Scheme.ΓSpecIso_inv_naturality f).symm + +theorem Scheme.isoSpec_Spec (R : CommRingCat.{u}) : + (Spec R).isoSpec = Scheme.Spec.mapIso (Scheme.ΓSpecIso R).op := + Iso.ext (SpecMap_ΓSpecIso_hom R).symm + +@[simp] theorem Scheme.isoSpec_Spec_hom (R : CommRingCat.{u}) : + (Spec R).isoSpec.hom = Spec.map (Scheme.ΓSpecIso R).hom := + (SpecMap_ΓSpecIso_hom R).symm + +@[simp] theorem Scheme.isoSpec_Spec_inv (R : CommRingCat.{u}) : + (Spec R).isoSpec.inv = Spec.map (Scheme.ΓSpecIso R).inv := + congr($(isoSpec_Spec R).inv) + namespace AffineScheme /-- The `Spec` functor into the category of affine schemes. -/ @@ -228,7 +250,7 @@ theorem iSup_affineOpens_eq_top (X : Scheme) : ⨆ i : X.affineOpens, (i : X.Ope theorem Scheme.map_PrimeSpectrum_basicOpen_of_affine (X : Scheme) [IsAffine X] (f : Scheme.Γ.obj (op X)) : X.isoSpec.hom ⁻¹ᵁ PrimeSpectrum.basicOpen f = X.basicOpen f := - ΓSpec.adjunction_unit_map_basicOpen _ _ + Scheme.toSpecΓ_preimage_basicOpen _ _ theorem isBasis_basicOpen (X : Scheme) [IsAffine X] : Opens.IsBasis (Set.range (X.basicOpen : Γ(X, ⊤) → X.Opens)) := by @@ -240,32 +262,69 @@ theorem isBasis_basicOpen (X : Scheme) [IsAffine X] : constructor · rintro ⟨_, ⟨x, rfl⟩, rfl⟩ refine ⟨_, ⟨_, ⟨x, rfl⟩, rfl⟩, ?_⟩ - exact congr_arg Opens.carrier (ΓSpec.adjunction_unit_map_basicOpen _ _) + exact congr_arg Opens.carrier (Scheme.toSpecΓ_preimage_basicOpen _ _) · rintro ⟨_, ⟨_, ⟨x, rfl⟩, rfl⟩, rfl⟩ refine ⟨_, ⟨x, rfl⟩, ?_⟩ - exact congr_arg Opens.carrier (ΓSpec.adjunction_unit_map_basicOpen _ _).symm + exact congr_arg Opens.carrier (Scheme.toSpecΓ_preimage_basicOpen _ _).symm namespace IsAffineOpen variable {X Y : Scheme.{u}} {U : X.Opens} (hU : IsAffineOpen U) (f : Γ(X, U)) +attribute [-simp] eqToHom_op in +/-- The isomorphism `U ≅ Spec Γ(X, U)` for an affine `U`. -/ +@[simps! (config := .lemmasOnly) hom inv] +def isoSpec : + ↑U ≅ Spec Γ(X, U) := + haveI : IsAffine U := hU + U.toScheme.isoSpec ≪≫ Scheme.Spec.mapIso + (X.presheaf.mapIso (eqToIso U.openEmbedding_obj_top).op).op + +open LocalRing in +lemma isoSpec_hom_val_base_apply (x : U) : + hU.isoSpec.hom.1.base x = (Spec.map (X.presheaf.germ _ x x.2)).val.base (closedPoint _) := by + dsimp [IsAffineOpen.isoSpec_hom, Scheme.isoSpec_hom, Scheme.toSpecΓ_val_base] + rw [← Scheme.comp_val_base_apply, ← Spec.map_comp, + (Iso.eq_comp_inv _).mpr (Scheme.Opens.germ_stalkIso_hom U (V := ⊤) x trivial), + X.presheaf.germ_res_assoc, Spec.map_comp, Scheme.comp_val_base_apply] + congr 1 + have := isLocalRingHom_of_isIso (U.stalkIso x).inv + exact LocalRing.comap_closedPoint (U.stalkIso x).inv + +lemma isoSpec_inv_app_top : + hU.isoSpec.inv.app ⊤ = U.topIso.hom ≫ (Scheme.ΓSpecIso Γ(X, U)).inv := by + simp only [Scheme.Opens.toScheme_presheaf_obj, isoSpec_inv, Scheme.isoSpec, asIso_inv, + Scheme.comp_coeBase, Opens.map_comp_obj, Opens.map_top, Scheme.comp_app, Scheme.inv_app_top, + Scheme.Opens.topIso_hom, Scheme.ΓSpecIso_inv_naturality, IsIso.inv_comp_eq] + rw [Scheme.toSpecΓ_app_top] + erw [Iso.hom_inv_id_assoc] + +lemma isoSpec_hom_app_top : + hU.isoSpec.hom.app ⊤ = (Scheme.ΓSpecIso Γ(X, U)).hom ≫ U.topIso.inv := by + have := congr(inv $hU.isoSpec_inv_app_top) + rw [IsIso.inv_comp, IsIso.Iso.inv_inv, IsIso.Iso.inv_hom] at this + have := (Scheme.Γ.map_inv hU.isoSpec.inv.op).trans this + rwa [← op_inv, IsIso.Iso.inv_inv] at this + /-- The open immersion `Spec Γ(X, U) ⟶ X` for an affine `U`. -/ def fromSpec : Spec Γ(X, U) ⟶ X := haveI : IsAffine U := hU - Spec.map (X.presheaf.map (eqToHom U.openEmbedding_obj_top.symm).op) ≫ - U.toScheme.isoSpec.inv ≫ U.ι + hU.isoSpec.inv ≫ U.ι instance isOpenImmersion_fromSpec : IsOpenImmersion hU.fromSpec := by delta fromSpec infer_instance +@[reassoc (attr := simp)] +lemma isoSpec_inv_ι : hU.isoSpec.inv ≫ U.ι = hU.fromSpec := rfl + @[simp] theorem range_fromSpec : Set.range hU.fromSpec.1.base = (U : Set X) := by - delta IsAffineOpen.fromSpec; dsimp - rw [Function.comp_assoc, Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] + delta IsAffineOpen.fromSpec; dsimp [IsAffineOpen.isoSpec_inv] + rw [Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] · exact Subtype.range_coe erw [← coe_comp, ← TopCat.epi_iff_surjective] -- now `erw` after #13170 infer_instance @@ -279,9 +338,37 @@ theorem map_fromSpec {V : X.Opens} (hV : IsAffineOpen V) (f : op U ⟶ op V) : have : IsAffine (X.restrictFunctor.obj U).left := hU haveI : IsAffine _ := hV conv_rhs => - rw [fromSpec, ← X.restrictFunctor_map_ofRestrict f.unop, ← Scheme.isoSpec_inv_naturality_assoc, + rw [fromSpec, ← X.restrictFunctor_map_ofRestrict f.unop, isoSpec_inv, Category.assoc, + ← Scheme.isoSpec_inv_naturality_assoc, ← Spec.map_comp_assoc, Scheme.restrictFunctor_map_app, ← Functor.map_comp] - rw [fromSpec, ← Spec.map_comp_assoc, ← Functor.map_comp] + rw [fromSpec, isoSpec_inv, Category.assoc, ← Spec.map_comp_assoc, ← Functor.map_comp] + rfl + +@[reassoc] +lemma Spec_map_appLE_fromSpec (f : X ⟶ Y) {V : X.Opens} {U : Y.Opens} + (hU : IsAffineOpen U) (hV : IsAffineOpen V) (i : V ≤ f ⁻¹ᵁ U) : + Spec.map (f.appLE U V i) ≫ hU.fromSpec = hV.fromSpec ≫ f := by + have : IsAffine U := hU + simp only [IsAffineOpen.fromSpec, Category.assoc, isoSpec_inv] + rw [← Scheme.restrictFunctor_map_ofRestrict (homOfLE i), Category.assoc, ← morphismRestrict_ι, + ← Category.assoc _ (f ∣_ U) U.ι, ← @Scheme.isoSpec_inv_naturality_assoc, + ← Spec.map_comp_assoc, ← Spec.map_comp_assoc, Scheme.comp_app, morphismRestrict_app, + Scheme.restrictFunctor_map_app, Scheme.Hom.app_eq_appLE, Scheme.Hom.appLE_map, + Scheme.Hom.appLE_map, Scheme.Hom.appLE_map, Scheme.Hom.map_appLE] + +lemma fromSpec_top [IsAffine X] : (isAffineOpen_top X).fromSpec = X.isoSpec.inv := by + rw [fromSpec, isoSpec_inv, Category.assoc, ← @Scheme.isoSpec_inv_naturality, Scheme.Opens.ι_app, + ← Spec.map_comp_assoc, ← X.presheaf.map_comp, ← op_comp, eqToHom_comp_homOfLE, + ← eqToHom_eq_homOfLE rfl, eqToHom_refl, op_id, X.presheaf.map_id, Spec.map_id, Category.id_comp] + +lemma fromSpec_app_of_le (V : X.Opens) (h : U ≤ V) : + hU.fromSpec.app V = X.presheaf.map (homOfLE h).op ≫ + (Scheme.ΓSpecIso Γ(X, U)).inv ≫ (Spec _).presheaf.map (homOfLE le_top).op := by + have : U.ι ⁻¹ᵁ V = ⊤ := eq_top_iff.mpr fun x _ ↦ h x.2 + rw [IsAffineOpen.fromSpec, Scheme.comp_app, Scheme.Opens.ι_app, Scheme.app_eq _ this, + IsAffineOpen.isoSpec_inv_app_top] + simp only [Scheme.Opens.toScheme_presheaf_map, Scheme.Opens.topIso_hom, + Category.assoc, ← X.presheaf.map_comp_assoc] rfl include hU in @@ -352,23 +439,20 @@ theorem fromSpec_preimage_self : rw [Opens.map_coe, Opens.coe_top, ← hU.range_fromSpec, ← Set.image_univ] exact Set.preimage_image_eq _ PresheafedSpace.IsOpenImmersion.base_open.inj -theorem SpecΓIdentity_hom_app_fromSpec : +theorem ΓSpecIso_hom_fromSpec_app : (Scheme.ΓSpecIso Γ(X, U)).hom ≫ hU.fromSpec.app U = (Spec Γ(X, U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by - simp only [fromSpec, Scheme.isoSpec, asIso_inv, Scheme.comp_coeBase, Opens.map_comp_obj, - ΓSpecIso_obj_hom, Scheme.Opens.topIso_inv, Opens.map_top, Functor.id_obj, Functor.comp_obj, - Functor.rightOp_obj, Scheme.Γ_obj, unop_op, Scheme.Spec_obj, Scheme.Opens.topIso_hom, - Scheme.comp_app, Scheme.Opens.ι_app_self, Category.assoc, ← Functor.map_comp_assoc, ← op_comp, - eqToHom_trans, Scheme.Opens.eq_presheaf_map_eqToHom, Scheme.Hom.naturality_assoc, - Scheme.inv_app_top, IsIso.hom_inv_id_assoc] - simp only [eqToHom_op, eqToHom_map, Spec.map_eqToHom, eqToHom_unop, - Scheme.Spec_map_presheaf_map_eqToHom, eqToHom_trans] + simp only [fromSpec, Scheme.comp_coeBase, Opens.map_comp_obj, Scheme.comp_app, + Scheme.Opens.ι_app_self, eqToHom_op, Scheme.app_eq _ U.ι_preimage_self, + Scheme.Opens.toScheme_presheaf_map, eqToHom_unop, eqToHom_map U.ι.opensFunctor, Opens.map_top, + isoSpec_inv_app_top, Scheme.Opens.topIso_hom, Category.assoc, ← Functor.map_comp_assoc, + eqToHom_trans, eqToHom_refl, X.presheaf.map_id, Category.id_comp, Iso.hom_inv_id_assoc] @[elementwise] theorem fromSpec_app_self : hU.fromSpec.app U = (Scheme.ΓSpecIso Γ(X, U)).inv ≫ (Spec Γ(X, U)).presheaf.map (eqToHom hU.fromSpec_preimage_self).op := by - rw [← hU.SpecΓIdentity_hom_app_fromSpec, Iso.inv_hom_id_assoc] + rw [← hU.ΓSpecIso_hom_fromSpec_app, Iso.inv_hom_id_assoc] theorem fromSpec_preimage_basicOpen' : hU.fromSpec ⁻¹ᵁ X.basicOpen f = (Spec Γ(X, U)).basicOpen ((Scheme.ΓSpecIso Γ(X, U)).inv f) := by @@ -523,20 +607,18 @@ theorem _root_.AlgebraicGeometry.exists_basicOpen_le_affine_inter /-- The prime ideal of `𝒪ₓ(U)` corresponding to a point `x : U`. -/ noncomputable def primeIdealOf (x : U) : PrimeSpectrum Γ(X, U) := - ((@Scheme.isoSpec U hU).hom ≫ - Spec.map (X.presheaf.map (eqToHom U.openEmbedding_obj_top).op)).1.base x + hU.isoSpec.hom.1.base x theorem fromSpec_primeIdealOf (x : U) : hU.fromSpec.val.base (hU.primeIdealOf x) = x.1 := by dsimp only [IsAffineOpen.fromSpec, Subtype.coe_mk, IsAffineOpen.primeIdealOf] - -- Porting note: in the porting note of `Scheme.comp_val_base`, it says that `elementwise` is - -- unnecessary, indeed, the linter did not like it, so I just use `elementwise_of%` instead of - -- adding the corresponding lemma in `Scheme.lean` file - erw [← elementwise_of% Scheme.comp_val_base] -- now `erw` after #13170 - simp only [Scheme.Opens.toScheme_presheaf_obj, Category.assoc, ← Spec.map_comp_assoc, - ← Functor.map_comp, ← op_comp, eqToHom_trans, eqToHom_refl, op_id, - CategoryTheory.Functor.map_id, Spec.map_id, Category.id_comp, Iso.hom_inv_id_assoc] - rfl -- `rfl` was not needed before #13170 + rw [← Scheme.comp_val_base_apply, Iso.hom_inv_id_assoc] + rfl + +open LocalRing in +theorem primeIdealOf_eq_map_closedPoint (x : U) : + hU.primeIdealOf x = (Spec.map (X.presheaf.germ _ x x.2)).val.base (closedPoint _) := + hU.isoSpec_hom_val_base_apply _ theorem isLocalization_stalk' (y : PrimeSpectrum Γ(X, U)) (hy : hU.fromSpec.1.base y ∈ U) : @IsLocalization.AtPrime @@ -555,8 +637,8 @@ theorem isLocalization_stalk' (y : PrimeSpectrum Γ(X, U)) (hy : hU.fromSpec.1.b rw [iff_iff_eq] congr 2 rw [RingHom.algebraMap_toAlgebra] - refine (PresheafedSpace.stalkMap_germ hU.fromSpec.1 _ ⟨_, hy⟩).trans ?_ - rw [← Scheme.Hom.app, IsAffineOpen.fromSpec_app_self, Category.assoc, TopCat.Presheaf.germ_res] + refine (Scheme.stalkMap_germ hU.fromSpec _ _ hy).trans ?_ + rw [IsAffineOpen.fromSpec_app_self, Category.assoc, TopCat.Presheaf.germ_res] rfl -- Porting note: I have split this into two lemmas @@ -683,7 +765,7 @@ section ZeroLocus /-- On a locally ringed space `X`, the preimage of the zero locus of the prime spectrum of `Γ(X, ⊤)` under `toΓSpecFun` agrees with the associated zero locus on `X`. -/ lemma Scheme.toΓSpec_preimage_zeroLocus_eq {X : Scheme.{u}} (s : Set Γ(X, ⊤)) : - (ΓSpec.adjunction.unit.app X).val.base ⁻¹' PrimeSpectrum.zeroLocus s = X.zeroLocus s := + X.toSpecΓ.val.base ⁻¹' PrimeSpectrum.zeroLocus s = X.zeroLocus s := LocallyRingedSpace.toΓSpec_preimage_zeroLocus_eq s open ConcreteCategory @@ -712,6 +794,109 @@ lemma Scheme.eq_zeroLocus_of_isClosed_of_isAffine (X : Scheme.{u}) [IsAffine X] end ZeroLocus +section Factorization + +variable {X : Scheme.{u}} {A : CommRingCat} + +/-- If `X ⟶ Spec A` is a morphism of schemes, then `Spec` of `A ⧸ specTargetImage f` +is the scheme-theoretic image of `f`. For this quotient as an object of `CommRingCat` see +`specTargetImage` below. -/ +def specTargetImageIdeal (f : X ⟶ Spec A) : Ideal A := + (RingHom.ker <| (((ΓSpec.adjunction).homEquiv X (op A)).symm f).unop) + +/-- If `X ⟶ Spec A` is a morphism of schemes, then `Spec` of `specTargetImage f` is the +scheme-theoretic image of `f` and `f` factors as +`specTargetImageFactorization f ≫ Spec.map (specTargetImageRingHom f)` +(see `specTargetImageFactorization_comp`). -/ +def specTargetImage (f : X ⟶ Spec A) : CommRingCat := + CommRingCat.of (A ⧸ specTargetImageIdeal f) + +/-- If `f : X ⟶ Spec A` is a morphism of schemes, then `f` factors via +the inclusion of `Spec (specTargetImage f)` into `X`. -/ +def specTargetImageFactorization (f : X ⟶ Spec A) : X ⟶ Spec (specTargetImage f) := + (ΓSpec.adjunction).homEquiv X (op <| specTargetImage f) (Opposite.op (RingHom.kerLift _)) + +/-- If `f : X ⟶ Spec A` is a morphism of schemes, the induced morphism on spectra of +`specTargetImageRingHom f` is the inclusion of the scheme-theoretic image of `f` into `Spec A`. -/ +def specTargetImageRingHom (f : X ⟶ Spec A) : A ⟶ specTargetImage f := + Ideal.Quotient.mk (specTargetImageIdeal f) + +variable (f : X ⟶ Spec A) + +lemma specTargetImageRingHom_surjective : Function.Surjective (specTargetImageRingHom f) := + Ideal.Quotient.mk_surjective + +lemma specTargetImageFactorization_app_injective : + Function.Injective <| (specTargetImageFactorization f).app ⊤ := by + let φ : A ⟶ Γ(X, ⊤) := (((ΓSpec.adjunction).homEquiv X (op A)).symm f).unop + let φ' : specTargetImage f ⟶ Scheme.Γ.obj (op X) := RingHom.kerLift φ + show Function.Injective <| ((ΓSpec.adjunction.homEquiv X _) φ'.op).app ⊤ + rw [ΓSpec_adjunction_homEquiv_eq] + apply (RingHom.kerLift_injective φ).comp + exact ((ConcreteCategory.isIso_iff_bijective (Scheme.ΓSpecIso _).hom).mp inferInstance).injective + +@[reassoc (attr := simp)] +lemma specTargetImageFactorization_comp : + specTargetImageFactorization f ≫ Spec.map (specTargetImageRingHom f) = f := by + let φ : A ⟶ Γ(X, ⊤) := (((ΓSpec.adjunction).homEquiv X (op A)).symm f).unop + let φ' : specTargetImage f ⟶ Scheme.Γ.obj (op X) := RingHom.kerLift φ + apply ((ΓSpec.adjunction).homEquiv X (op A)).symm.injective + apply Opposite.unop_injective + rw [Adjunction.homEquiv_naturality_left_symm, Adjunction.homEquiv_counit] + change (_ ≫ _) ≫ _ = φ + erw [← Spec_Γ_naturality] + rw [Category.assoc] + erw [ΓSpecIso_inv_ΓSpec_adjunction_homEquiv φ'] + ext a + apply RingHom.kerLift_mk + +open RingHom + +variable {Y : Scheme.{u}} [IsAffine Y] (f : X ⟶ Y) + +/-- The scheme-theoretic image of a morphism `f : X ⟶ Y` with affine target. +`f` factors as `affineTargetImageFactorization f ≫ affineTargetImageInclusion f` +(see `affineTargetImageFactorization_comp`). -/ +def affineTargetImage (f : X ⟶ Y) : Scheme.{u} := + Spec <| specTargetImage (f ≫ Y.isoSpec.hom) + +instance : IsAffine (affineTargetImage f) := inferInstanceAs <| IsAffine <| Spec _ + +/-- The inclusion of the scheme-theoretic image of a morphism with affine target. -/ +def affineTargetImageInclusion (f : X ⟶ Y) : affineTargetImage f ⟶ Y := + Spec.map (specTargetImageRingHom (f ≫ Y.isoSpec.hom)) ≫ Y.isoSpec.inv + +lemma affineTargetImageInclusion_app_surjective : + Function.Surjective <| (affineTargetImageInclusion f).app ⊤ := by + simp only [Scheme.comp_coeBase, Opens.map_comp_obj, Opens.map_top, Scheme.comp_app, + CommRingCat.coe_comp, affineTargetImageInclusion] + apply Function.Surjective.comp + · haveI : (toMorphismProperty (fun f ↦ Function.Surjective f)).RespectsIso := by + rw [← toMorphismProperty_respectsIso_iff] + exact surjective_respectsIso + exact (MorphismProperty.arrow_mk_iso_iff + (toMorphismProperty (fun f ↦ Function.Surjective f)) + (arrowIsoΓSpecOfIsAffine (specTargetImageRingHom (f ≫ Y.isoSpec.hom))).symm).mpr <| + specTargetImageRingHom_surjective (f ≫ Y.isoSpec.hom) + · apply Function.Bijective.surjective + apply ConcreteCategory.bijective_of_isIso + +/-- The induced morphism from `X` to the scheme-theoretic image +of a morphism `f : X ⟶ Y` with affine target. -/ +def affineTargetImageFactorization (f : X ⟶ Y) : X ⟶ affineTargetImage f := + specTargetImageFactorization (f ≫ Y.isoSpec.hom) + +lemma affineTargetImageFactorization_app_injective : + Function.Injective <| (affineTargetImageFactorization f).app ⊤ := + specTargetImageFactorization_app_injective (f ≫ Y.isoSpec.hom) + +@[reassoc (attr := simp)] +lemma affineTargetImageFactorization_comp : + affineTargetImageFactorization f ≫ affineTargetImageInclusion f = f := by + simp [affineTargetImageFactorization, affineTargetImageInclusion] + +end Factorization + section Stalks /-- Variant of `AlgebraicGeometry.localRingHom_comp_stalkIso` for `Spec.map`. -/ diff --git a/Mathlib/AlgebraicGeometry/Cover/Open.lean b/Mathlib/AlgebraicGeometry/Cover/Open.lean index 959dc19b68c73..c137272d6c0ce 100644 --- a/Mathlib/AlgebraicGeometry/Cover/Open.lean +++ b/Mathlib/AlgebraicGeometry/Cover/Open.lean @@ -73,7 +73,7 @@ def affineCover (X : Scheme.{u}) : OpenCover X where rw [Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ] · erw [Subtype.range_coe_subtype] exact (X.local_affine x).choose.2 - erw [← TopCat.epi_iff_surjective] -- now `erw` after #13170 + rw [← TopCat.epi_iff_surjective] change Epi ((SheafedSpace.forget _).map (LocallyRingedSpace.forgetToSheafedSpace.map _)) infer_instance @@ -136,7 +136,7 @@ def OpenCover.copy {X : Scheme.{u}} (𝒰 : OpenCover X) (J : Type*) (obj : J rw [e₂, Scheme.comp_val_base, TopCat.coe_comp, Set.range_comp, Set.range_iff_surjective.mpr, Set.image_univ, e₁.rightInverse_symm] · exact 𝒰.covers x - · erw [← TopCat.epi_iff_surjective]; infer_instance -- now `erw` after #13170 + · rw [← TopCat.epi_iff_surjective]; infer_instance -- Porting note: weirdly, even though no input is needed, `inferInstance` does not work -- `PresheafedSpace.IsOpenImmersion.comp` is marked as `instance` IsOpen := fun i => by rw [e₂]; exact PresheafedSpace.IsOpenImmersion.comp _ _ } @@ -503,7 +503,7 @@ theorem affineBasisCover_is_basis (X : Scheme.{u}) : ((X.affineCover.map (X.affineCover.f a)).1.base.continuous_toFun.isOpen_preimage _ hU) with ⟨_, ⟨_, ⟨s, rfl⟩, rfl⟩, hxV, hVU⟩ - refine ⟨_, ⟨⟨_, s⟩, rfl⟩, ?_, ?_⟩ <;> erw [affineBasisCover_map_range] + refine ⟨_, ⟨⟨_, s⟩, rfl⟩, ?_, ?_⟩ <;> rw [affineBasisCover_map_range] · exact ⟨x, hxV, e⟩ · rw [Set.image_subset_iff]; exact hVU diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean index 8e25ace403b09..fc127a34958cc 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Affine.lean @@ -5,6 +5,7 @@ Authors: David Kurniadi Angdinata -/ import Mathlib.Algebra.Polynomial.Bivariate import Mathlib.AlgebraicGeometry.EllipticCurve.Weierstrass +import Mathlib.AlgebraicGeometry.EllipticCurve.VariableChange /-! # Affine coordinates for Weierstrass curves @@ -163,7 +164,6 @@ lemma irreducible_polynomial [IsDomain R] : Irreducible W.polynomial := by iterate 2 rw [degree_add_eq_right_of_degree_lt] <;> simp only [h] <;> decide iterate 2 rw [degree_add_eq_left_of_degree_lt] <;> simp only [h] <;> decide --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma evalEval_polynomial (x y : R) : W.polynomial.evalEval x y = y ^ 2 + W.a₁ * x * y + W.a₃ * y - (x ^ 3 + W.a₂ * x ^ 2 + W.a₄ * x + W.a₆) := by simp only [polynomial] @@ -182,7 +182,6 @@ lemma equation_iff' (x y : R) : W.Equation x y ↔ y ^ 2 + W.a₁ * x * y + W.a₃ * y - (x ^ 3 + W.a₂ * x ^ 2 + W.a₄ * x + W.a₆) = 0 := by rw [Equation, evalEval_polynomial] --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma equation_iff (x y : R) : W.Equation x y ↔ y ^ 2 + W.a₁ * x * y + W.a₃ * y = x ^ 3 + W.a₂ * x ^ 2 + W.a₄ * x + W.a₆ := by rw [equation_iff', sub_eq_zero] @@ -209,7 +208,6 @@ TODO: define this in terms of `Polynomial.derivative`. -/ noncomputable def polynomialX : R[X][Y] := C (C W.a₁) * Y - C (C 3 * X ^ 2 + C (2 * W.a₂) * X + C W.a₄) --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma evalEval_polynomialX (x y : R) : W.polynomialX.evalEval x y = W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄) := by simp only [polynomialX] @@ -225,7 +223,6 @@ TODO: define this in terms of `Polynomial.derivative`. -/ noncomputable def polynomialY : R[X][Y] := C (C 2) * Y + C (C W.a₁ * X + C W.a₃) --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma evalEval_polynomialY (x y : R) : W.polynomialY.evalEval x y = 2 * y + W.a₁ * x + W.a₃ := by simp only [polynomialY] @@ -255,7 +252,6 @@ lemma nonsingular_iff' (x y : R) : W.Nonsingular x y ↔ W.Equation x y ∧ (W.a₁ * y - (3 * x ^ 2 + 2 * W.a₂ * x + W.a₄) ≠ 0 ∨ 2 * y + W.a₁ * x + W.a₃ ≠ 0) := by rw [Nonsingular, equation_iff', evalEval_polynomialX, evalEval_polynomialY] --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma nonsingular_iff (x y : R) : W.Nonsingular x y ↔ W.Equation x y ∧ (W.a₁ * y ≠ 3 * x ^ 2 + 2 * W.a₂ * x + W.a₄ ∨ y ≠ -y - W.a₁ * x - W.a₃) := by rw [nonsingular_iff', sub_ne_zero, ← sub_ne_zero (a := y)] @@ -313,7 +309,6 @@ lemma negY_negY (x y : R) : W.negY x (W.negY x y) = y := by simp only [negY] ring1 --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma eval_negPolynomial (x y : R) : W.negPolynomial.evalEval x y = W.negY x y := by rw [negY, sub_sub, negPolynomial] eval_simp @@ -608,7 +603,6 @@ instance : Inhabited W.Point := instance : Zero W.Point := ⟨zero⟩ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma zero_def : (zero : W.Point) = 0 := rfl @@ -624,7 +618,6 @@ def neg : W.Point → W.Point instance : Neg W.Point := ⟨neg⟩ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma neg_def (P : W.Point) : P.neg = -P := rfl @@ -655,7 +648,6 @@ noncomputable def add : W.Point → W.Point → W.Point noncomputable instance instAddPoint : Add W.Point := ⟨add⟩ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma add_def (P Q : W.Point) : P.add Q = P + Q := rfl diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean index cbb5edf60ed85..d81a89407576b 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Group.lean @@ -213,7 +213,6 @@ section Ring /-! ### Ideals in the coordinate ring over a ring -/ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The class of the element $X - x$ in $R[W]$ for some $x \in R$. -/ noncomputable def XClass (x : R) : W.CoordinateRing := mk W <| C <| X - C x @@ -222,7 +221,6 @@ lemma XClass_ne_zero [Nontrivial R] (x : R) : XClass W x ≠ 0 := AdjoinRoot.mk_ne_zero_of_natDegree_lt W.monic_polynomial (C_ne_zero.mpr <| X_sub_C_ne_zero x) <| by rw [natDegree_polynomial, natDegree_C]; norm_num1 --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The class of the element $Y - y(X)$ in $R[W]$ for some $y(X) \in R[X]$. -/ noncomputable def YClass (y : R[X]) : W.CoordinateRing := mk W <| Y - C y @@ -235,17 +233,14 @@ 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_left, mul_one]⟩ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The ideal $\langle X - x \rangle$ of $R[W]$ for some $x \in R$. -/ noncomputable def XIdeal (x : R) : Ideal W.CoordinateRing := span {XClass W x} --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The ideal $\langle Y - y(X) \rangle$ of $R[W]$ for some $y(X) \in R[X]$. -/ noncomputable def YIdeal (y : R[X]) : Ideal W.CoordinateRing := span {YClass W y} --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The ideal $\langle X - x, Y - y(X) \rangle$ of $R[W]$ for some $x \in R$ and $y(X) \in R[X]$. -/ noncomputable def XYIdeal (x : R) (y : R[X]) : Ideal W.CoordinateRing := span {XClass W x, YClass W y} @@ -387,7 +382,6 @@ lemma XYIdeal_mul_XYIdeal {x₁ x₂ y₁ y₂ : F} (h₁ : W.Equation x₁ y₁ C_simp ring1 --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The non-zero fractional ideal $\langle X - x, Y - y \rangle$ of $F(W)$ for some $x, y \in F$. -/ noncomputable def XYIdeal' {x y : F} (h : W.Nonsingular x y) : (FractionalIdeal W.CoordinateRing⁰ W.FunctionField)ˣ := @@ -518,7 +512,6 @@ noncomputable def toClass : W.Point →+ Additive (ClassGroup W.CoordinateRing) rw [add_of_imp h] exact (CoordinateRing.mk_XYIdeal'_mul_mk_XYIdeal' h₁ h₂ h).symm --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error lemma toClass_zero : toClass (0 : W.Point) = 0 := rfl @@ -545,7 +538,7 @@ lemma toClass_eq_zero (P : W.Point) : toClass P = 0 ↔ P = 0 := by rw [← finrank_quotient_span_eq_natDegree_norm (CoordinateRing.basis W) h0, ← (quotientEquivAlgOfEq F hp).toLinearEquiv.finrank_eq, (CoordinateRing.quotientXYIdealEquiv W h).toLinearEquiv.finrank_eq, - FiniteDimensional.finrank_self] + Module.finrank_self] · exact congr_arg toClass lemma toClass_injective : Function.Injective <| @toClass _ _ W := by diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/NormalForms.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/NormalForms.lean new file mode 100644 index 0000000000000..565f29a05b7f1 --- /dev/null +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/NormalForms.lean @@ -0,0 +1,706 @@ +/- +Copyright (c) 2024 Jz Pan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jz Pan +-/ +import Mathlib.AlgebraicGeometry.EllipticCurve.VariableChange +import Mathlib.Algebra.CharP.Defs + +/-! + +# Some normal forms of elliptic curves + +This file defines some normal forms of Weierstrass equations of elliptic curves. + +## Main definitions and results + +The following normal forms are in [silverman2009], section III.1, page 42. + +- `WeierstrassCurve.IsCharNeTwoNF` is a type class which asserts that a `WeierstrassCurve` is + of form $Y^2 = X^3 + a_2X^2 + a_4X + a_6$. It is the normal form of characteristic ≠ 2. + + If 2 is invertible in the ring (for example, if it is a field of characteristic ≠ 2), + then for any `WeierstrassCurve` there exists a change of variables which will change + it into such normal form (`WeierstrassCurve.exists_variableChange_isCharNeTwoNF`). + See also `WeierstrassCurve.toCharNeTwoNF` and `WeierstrassCurve.toCharNeTwoNF_spec`. + +The following normal forms are in [silverman2009], Appendix A, Proposition 1.1. + +- `WeierstrassCurve.IsShortNF` is a type class which asserts that a `WeierstrassCurve` is + of form $Y^2 = X^3 + a_4X + a_6$. It is the normal form of characteristic ≠ 2 or 3, and + also the normal form of characteristic = 3 and j = 0. + + If 2 and 3 are invertible in the ring (for example, if it is a field of characteristic ≠ 2 or 3), + then for any `WeierstrassCurve` there exists a change of variables which will change + it into such normal form (`WeierstrassCurve.exists_variableChange_isShortNF`). + See also `WeierstrassCurve.toShortNF` and `WeierstrassCurve.toShortNF_spec`. + + If the ring is of characteristic = 3, then for any `WeierstrassCurve` with $b_2 = 0$ (for an + elliptic curve, this is equivalent to j = 0), there exists a change of variables which will + change it into such normal form (see `WeierstrassCurve.toShortNFOfCharThree` + and `WeierstrassCurve.toShortNFOfCharThree_spec`). + +- `WeierstrassCurve.IsCharThreeJNeZeroNF` is a type class which asserts that a `WeierstrassCurve` is + of form $Y^2 = X^3 + a_2X^2 + a_6$. It is the normal form of characteristic = 3 and j ≠ 0. + + If the field is of characteristic = 3, then for any `WeierstrassCurve` with $b_2 \neq 0$ (for an + elliptic curve, this is equivalent to j ≠ 0), there exists a change of variables which will + change it into such normal form (see `WeierstrassCurve.toCharThreeNF` + and `WeierstrassCurve.toCharThreeNF_spec_of_b₂_ne_zero`). + +- `WeierstrassCurve.IsCharThreeNF` is the combination of the above two, that is, asserts that + a `WeierstrassCurve` is of form $Y^2 = X^3 + a_2X^2 + a_6$ or $Y^2 = X^3 + a_4X + a_6$. + It is the normal form of characteristic = 3. + + If the field is of characteristic = 3, then for any `WeierstrassCurve` there exists a change of + variables which will change it into such normal form + (`WeierstrassCurve.exists_variableChange_isCharThreeNF`). + See also `WeierstrassCurve.toCharThreeNF` and `WeierstrassCurve.toCharThreeNF_spec`. + +- `WeierstrassCurve.IsCharTwoJEqZeroNF` is a type class which asserts that a `WeierstrassCurve` is + of form $Y^2 + a_3Y = X^3 + a_4X + a_6$. It is the normal form of characteristic = 2 and j = 0. + + If the ring is of characteristic = 2, then for any `WeierstrassCurve` with $a_1 = 0$ (for an + elliptic curve, this is equivalent to j = 0), there exists a change of variables which will + change it into such normal form (see `WeierstrassCurve.toCharTwoJEqZeroNF` + and `WeierstrassCurve.toCharTwoJEqZeroNF_spec`). + +- `WeierstrassCurve.IsCharTwoJNeZeroNF` is a type class which asserts that a `WeierstrassCurve` is + of form $Y^2 + XY = X^3 + a_2X^2 + a_6$. It is the normal form of characteristic = 2 and j ≠ 0. + + If the field is of characteristic = 2, then for any `WeierstrassCurve` with $a_1 \neq 0$ (for an + elliptic curve, this is equivalent to j ≠ 0), there exists a change of variables which will + change it into such normal form (see `WeierstrassCurve.toCharTwoJNeZeroNF` + and `WeierstrassCurve.toCharTwoJNeZeroNF_spec`). + +- `WeierstrassCurve.IsCharTwoNF` is the combination of the above two, that is, asserts that + a `WeierstrassCurve` is of form $Y^2 + XY = X^3 + a_2X^2 + a_6$ or + $Y^2 + a_3Y = X^3 + a_4X + a_6$. It is the normal form of characteristic = 2. + + If the field is of characteristic = 2, then for any `WeierstrassCurve` there exists a change of + variables which will change it into such normal form + (`WeierstrassCurve.exists_variableChange_isCharTwoNF`). + See also `WeierstrassCurve.toCharTwoNF` and `WeierstrassCurve.toCharTwoNF_spec`. + +## References + +* [J Silverman, *The Arithmetic of Elliptic Curves*][silverman2009] + +## Tags + +elliptic curve, weierstrass equation, normal form + +-/ + +variable {R : Type*} [CommRing R] (W : WeierstrassCurve R) +variable {F : Type*} [Field F] (E : EllipticCurve F) + +namespace WeierstrassCurve + +/-! ### Normal forms of characteristic ≠ 2 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic ≠ 2, if its $a_1, a_3 = 0$. +In other words it is $Y^2 = X^3 + a_2X^2 + a_4X + a_6$. -/ +@[mk_iff] +class IsCharNeTwoNF : Prop where + a₁ : W.a₁ = 0 + a₃ : W.a₃ = 0 + +section Quantity + +variable [W.IsCharNeTwoNF] + +@[simp] +theorem a₁_of_isCharNeTwoNF : W.a₁ = 0 := IsCharNeTwoNF.a₁ + +@[simp] +theorem a₃_of_isCharNeTwoNF : W.a₃ = 0 := IsCharNeTwoNF.a₃ + +@[simp] +theorem b₂_of_isCharNeTwoNF : W.b₂ = 4 * W.a₂ := by + rw [b₂, a₁_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem b₄_of_isCharNeTwoNF : W.b₄ = 2 * W.a₄ := by + rw [b₄, a₃_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem b₆_of_isCharNeTwoNF : W.b₆ = 4 * W.a₆ := by + rw [b₆, a₃_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem b₈_of_isCharNeTwoNF : W.b₈ = 4 * W.a₂ * W.a₆ - W.a₄ ^ 2 := by + rw [b₈, a₁_of_isCharNeTwoNF, a₃_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem c₄_of_isCharNeTwoNF : W.c₄ = 16 * W.a₂ ^ 2 - 48 * W.a₄ := by + rw [c₄, b₂_of_isCharNeTwoNF, b₄_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem c₆_of_isCharNeTwoNF : W.c₆ = -64 * W.a₂ ^ 3 + 288 * W.a₂ * W.a₄ - 864 * W.a₆ := by + rw [c₆, b₂_of_isCharNeTwoNF, b₄_of_isCharNeTwoNF, b₆_of_isCharNeTwoNF] + ring1 + +@[simp] +theorem Δ_of_isCharNeTwoNF : W.Δ = -64 * W.a₂ ^ 3 * W.a₆ + 16 * W.a₂ ^ 2 * W.a₄ ^ 2 - 64 * W.a₄ ^ 3 + - 432 * W.a₆ ^ 2 + 288 * W.a₂ * W.a₄ * W.a₆ := by + rw [Δ, b₂_of_isCharNeTwoNF, b₄_of_isCharNeTwoNF, b₆_of_isCharNeTwoNF, b₈_of_isCharNeTwoNF] + ring1 + +end Quantity + +section VariableChange + +variable [Invertible (2 : R)] + +/-- There is an explicit change of variables of a `WeierstrassCurve` to +a normal form of characteristic ≠ 2, provided that 2 is invertible in the ring. -/ +@[simps] +def toCharNeTwoNF : VariableChange R := ⟨1, 0, ⅟2 * -W.a₁, ⅟2 * -W.a₃⟩ + +instance toCharNeTwoNF_spec : (W.variableChange W.toCharNeTwoNF).IsCharNeTwoNF := by + constructor <;> simp + +theorem exists_variableChange_isCharNeTwoNF : + ∃ C : VariableChange R, (W.variableChange C).IsCharNeTwoNF := + ⟨_, W.toCharNeTwoNF_spec⟩ + +end VariableChange + +/-! ### Short normal form -/ + +/-- A `WeierstrassCurve` is in short normal form, if its $a_1, a_2, a_3 = 0$. +In other words it is $Y^2 = X^3 + a_4X + a_6$. + +This is the normal form of characteristic ≠ 2 or 3, and +also the normal form of characteristic = 3 and j = 0. -/ +@[mk_iff] +class IsShortNF : Prop where + a₁ : W.a₁ = 0 + a₂ : W.a₂ = 0 + a₃ : W.a₃ = 0 + +section Quantity + +variable [W.IsShortNF] + +instance isCharNeTwoNF_of_isShortNF : W.IsCharNeTwoNF := ⟨IsShortNF.a₁, IsShortNF.a₃⟩ + +theorem a₁_of_isShortNF : W.a₁ = 0 := IsShortNF.a₁ + +@[simp] +theorem a₂_of_isShortNF : W.a₂ = 0 := IsShortNF.a₂ + +theorem a₃_of_isShortNF : W.a₃ = 0 := IsShortNF.a₃ + +theorem b₂_of_isShortNF : W.b₂ = 0 := by + simp + +theorem b₄_of_isShortNF : W.b₄ = 2 * W.a₄ := W.b₄_of_isCharNeTwoNF + +theorem b₆_of_isShortNF : W.b₆ = 4 * W.a₆ := W.b₆_of_isCharNeTwoNF + +theorem b₈_of_isShortNF : W.b₈ = -W.a₄ ^ 2 := by + simp + +theorem c₄_of_isShortNF : W.c₄ = -48 * W.a₄ := by + simp + +theorem c₆_of_isShortNF : W.c₆ = -864 * W.a₆ := by + simp + +theorem Δ_of_isShortNF : W.Δ = -16 * (4 * W.a₄ ^ 3 + 27 * W.a₆ ^ 2) := by + rw [Δ_of_isCharNeTwoNF, a₂_of_isShortNF] + ring1 + +variable [CharP R 3] + +theorem b₄_of_isShortNF_of_char_three : W.b₄ = -W.a₄ := by + rw [b₄_of_isShortNF] + linear_combination W.a₄ * CharP.cast_eq_zero R 3 + +theorem b₆_of_isShortNF_of_char_three : W.b₆ = W.a₆ := by + rw [b₆_of_isShortNF] + linear_combination W.a₆ * CharP.cast_eq_zero R 3 + +theorem c₄_of_isShortNF_of_char_three : W.c₄ = 0 := by + rw [c₄_of_isShortNF] + linear_combination -16 * W.a₄ * CharP.cast_eq_zero R 3 + +theorem c₆_of_isShortNF_of_char_three : W.c₆ = 0 := by + rw [c₆_of_isShortNF] + linear_combination -288 * W.a₆ * CharP.cast_eq_zero R 3 + +theorem Δ_of_isShortNF_of_char_three : W.Δ = -W.a₄ ^ 3 := by + rw [Δ_of_isShortNF] + linear_combination (-21 * W.a₄ ^ 3 - 144 * W.a₆ ^ 2) * CharP.cast_eq_zero R 3 + +variable [E.IsShortNF] + +theorem _root_.EllipticCurve.j_of_isShortNF : + E.j = 6912 * E.a₄ ^ 3 / (4 * E.a₄ ^ 3 + 27 * E.a₆ ^ 2) := by + have h := E.Δ'.ne_zero + rw [E.coe_Δ', Δ_of_isShortNF] at h + rw [EllipticCurve.j, Units.val_inv_eq_inv_val, ← div_eq_inv_mul, E.coe_Δ', + c₄_of_isShortNF, Δ_of_isShortNF, div_eq_div_iff h (right_ne_zero_of_mul h)] + ring1 + +@[simp] +theorem _root_.EllipticCurve.j_of_isShortNF_of_char_three [CharP F 3] : E.j = 0 := by + rw [EllipticCurve.j, c₄_of_isShortNF_of_char_three]; simp + +end Quantity + +section VariableChange + +variable [Invertible (2 : R)] [Invertible (3 : R)] + +/-- There is an explicit change of variables of a `WeierstrassCurve` to +a short normal form, provided that 2 and 3 are invertible in the ring. +It is the composition of an explicit change of variables with `WeierstrassCurve.toCharNeTwoNF`. -/ +def toShortNF : VariableChange R := + .comp ⟨1, ⅟3 * -(W.variableChange W.toCharNeTwoNF).a₂, 0, 0⟩ W.toCharNeTwoNF + +instance toShortNF_spec : (W.variableChange W.toShortNF).IsShortNF := by + rw [toShortNF, variableChange_comp] + constructor <;> simp + +theorem exists_variableChange_isShortNF : + ∃ C : VariableChange R, (W.variableChange C).IsShortNF := + ⟨_, W.toShortNF_spec⟩ + +end VariableChange + +/-! ### Normal forms of characteristic = 3 and j ≠ 0 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic = 3 and j ≠ 0, if its +$a_1, a_3, a_4 = 0$. In other words it is $Y^2 = X^3 + a_2X^2 + a_6$. -/ +@[mk_iff] +class IsCharThreeJNeZeroNF : Prop where + a₁ : W.a₁ = 0 + a₃ : W.a₃ = 0 + a₄ : W.a₄ = 0 + +section Quantity + +variable [W.IsCharThreeJNeZeroNF] + +instance isCharNeTwoNF_of_isCharThreeJNeZeroNF : W.IsCharNeTwoNF := + ⟨IsCharThreeJNeZeroNF.a₁, IsCharThreeJNeZeroNF.a₃⟩ + +theorem a₁_of_isCharThreeJNeZeroNF : W.a₁ = 0 := IsCharThreeJNeZeroNF.a₁ + +theorem a₃_of_isCharThreeJNeZeroNF : W.a₃ = 0 := IsCharThreeJNeZeroNF.a₃ + +@[simp] +theorem a₄_of_isCharThreeJNeZeroNF : W.a₄ = 0 := IsCharThreeJNeZeroNF.a₄ + +theorem b₂_of_isCharThreeJNeZeroNF : W.b₂ = 4 * W.a₂ := W.b₂_of_isCharNeTwoNF + +theorem b₄_of_isCharThreeJNeZeroNF : W.b₄ = 0 := by + simp + +theorem b₆_of_isCharThreeJNeZeroNF : W.b₆ = 4 * W.a₆ := W.b₆_of_isCharNeTwoNF + +theorem b₈_of_isCharThreeJNeZeroNF : W.b₈ = 4 * W.a₂ * W.a₆ := by + simp + +theorem c₄_of_isCharThreeJNeZeroNF : W.c₄ = 16 * W.a₂ ^ 2 := by + simp + +theorem c₆_of_isCharThreeJNeZeroNF : W.c₆ = -64 * W.a₂ ^ 3 - 864 * W.a₆ := by + simp + +theorem Δ_of_isCharThreeJNeZeroNF : W.Δ = -64 * W.a₂ ^ 3 * W.a₆ - 432 * W.a₆ ^ 2 := by + simp + +variable [CharP R 3] + +theorem b₂_of_isCharThreeJNeZeroNF_of_char_three : W.b₂ = W.a₂ := by + rw [b₂_of_isCharThreeJNeZeroNF] + linear_combination W.a₂ * CharP.cast_eq_zero R 3 + +theorem b₆_of_isCharThreeJNeZeroNF_of_char_three : W.b₆ = W.a₆ := by + rw [b₆_of_isCharThreeJNeZeroNF] + linear_combination W.a₆ * CharP.cast_eq_zero R 3 + +theorem b₈_of_isCharThreeJNeZeroNF_of_char_three : W.b₈ = W.a₂ * W.a₆ := by + rw [b₈_of_isCharThreeJNeZeroNF] + linear_combination W.a₂ * W.a₆ * CharP.cast_eq_zero R 3 + +theorem c₄_of_isCharThreeJNeZeroNF_of_char_three : W.c₄ = W.a₂ ^ 2 := by + rw [c₄_of_isCharThreeJNeZeroNF] + linear_combination 5 * W.a₂ ^ 2 * CharP.cast_eq_zero R 3 + +theorem c₆_of_isCharThreeJNeZeroNF_of_char_three : W.c₆ = -W.a₂ ^ 3 := by + rw [c₆_of_isCharThreeJNeZeroNF] + linear_combination (-21 * W.a₂ ^ 3 - 288 * W.a₆) * CharP.cast_eq_zero R 3 + +theorem Δ_of_isCharThreeJNeZeroNF_of_char_three : W.Δ = -W.a₂ ^ 3 * W.a₆ := by + rw [Δ_of_isCharThreeJNeZeroNF] + linear_combination (-21 * W.a₂ ^ 3 * W.a₆ - 144 * W.a₆ ^ 2) * CharP.cast_eq_zero R 3 + +variable [E.IsCharThreeJNeZeroNF] [CharP F 3] + +@[simp] +theorem _root_.EllipticCurve.j_of_isCharThreeJNeZeroNF_of_char_three : E.j = -E.a₂ ^ 3 / E.a₆ := by + have h := E.Δ'.ne_zero + rw [E.coe_Δ', Δ_of_isCharThreeJNeZeroNF_of_char_three] at h + rw [EllipticCurve.j, Units.val_inv_eq_inv_val, ← div_eq_inv_mul, E.coe_Δ', + c₄_of_isCharThreeJNeZeroNF_of_char_three, Δ_of_isCharThreeJNeZeroNF_of_char_three, + div_eq_div_iff h (right_ne_zero_of_mul h)] + ring1 + +theorem _root_.EllipticCurve.j_ne_zero_of_isCharThreeJNeZeroNF_of_char_three : E.j ≠ 0 := by + rw [E.j_of_isCharThreeJNeZeroNF_of_char_three, div_ne_zero_iff] + have h := E.Δ'.ne_zero + rwa [E.coe_Δ', Δ_of_isCharThreeJNeZeroNF_of_char_three, mul_ne_zero_iff] at h + +end Quantity + +/-! ### Normal forms of characteristic = 3 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic = 3, if it is +$Y^2 = X^3 + a_2X^2 + a_6$ (`WeierstrassCurve.IsCharThreeJNeZeroNF`) or +$Y^2 = X^3 + a_4X + a_6$ (`WeierstrassCurve.IsShortNF`). -/ +class inductive IsCharThreeNF : Prop +| of_j_ne_zero [W.IsCharThreeJNeZeroNF] : IsCharThreeNF +| of_j_eq_zero [W.IsShortNF] : IsCharThreeNF + +instance isCharThreeNF_of_isCharThreeJNeZeroNF [W.IsCharThreeJNeZeroNF] : W.IsCharThreeNF := + IsCharThreeNF.of_j_ne_zero + +instance isCharThreeNF_of_isShortNF [W.IsShortNF] : W.IsCharThreeNF := + IsCharThreeNF.of_j_eq_zero + +instance isCharNeTwoNF_of_isCharThreeNF [W.IsCharThreeNF] : W.IsCharNeTwoNF := by + cases ‹W.IsCharThreeNF› <;> infer_instance + +section VariableChange + +variable [CharP R 3] [CharP F 3] + +/-- For a `WeierstrassCurve` defined over a ring of characteristic = 3, +there is an explicit change of variables of it to $Y^2 = X^3 + a_4X + a_6$ +(`WeierstrassCurve.IsShortNF`) if its j = 0. +This is in fact given by `WeierstrassCurve.toCharNeTwoNF`. -/ +def toShortNFOfCharThree : VariableChange R := + have h : (2 : R) * 2 = 1 := by linear_combination CharP.cast_eq_zero R 3 + letI : Invertible (2 : R) := ⟨2, h, h⟩ + W.toCharNeTwoNF + +lemma toShortNFOfCharThree_a₂ : (W.variableChange W.toShortNFOfCharThree).a₂ = W.b₂ := by + simp_rw [toShortNFOfCharThree, toCharNeTwoNF, variableChange_a₂, inv_one, Units.val_one, b₂] + linear_combination (-W.a₂ - W.a₁ ^ 2) * CharP.cast_eq_zero R 3 + +theorem toShortNFOfCharThree_spec (hb₂ : W.b₂ = 0) : + (W.variableChange W.toShortNFOfCharThree).IsShortNF := by + have h : (2 : R) * 2 = 1 := by linear_combination CharP.cast_eq_zero R 3 + letI : Invertible (2 : R) := ⟨2, h, h⟩ + have H := W.toCharNeTwoNF_spec + exact ⟨H.a₁, hb₂ ▸ W.toShortNFOfCharThree_a₂, H.a₃⟩ + +variable (W : WeierstrassCurve F) + +/-- For a `WeierstrassCurve` defined over a field of characteristic = 3, +there is an explicit change of variables of it to `WeierstrassCurve.IsCharThreeNF`, that is, +$Y^2 = X^3 + a_2X^2 + a_6$ (`WeierstrassCurve.IsCharThreeJNeZeroNF`) or +$Y^2 = X^3 + a_4X + a_6$ (`WeierstrassCurve.IsShortNF`). +It is the composition of an explicit change of variables with +`WeierstrassCurve.toShortNFOfCharThree`. -/ +def toCharThreeNF : VariableChange F := + .comp ⟨1, (W.variableChange W.toShortNFOfCharThree).a₄ / + (W.variableChange W.toShortNFOfCharThree).a₂, 0, 0⟩ W.toShortNFOfCharThree + +theorem toCharThreeNF_spec_of_b₂_ne_zero (hb₂ : W.b₂ ≠ 0) : + (W.variableChange W.toCharThreeNF).IsCharThreeJNeZeroNF := by + have h : (2 : F) * 2 = 1 := by linear_combination CharP.cast_eq_zero F 3 + letI : Invertible (2 : F) := ⟨2, h, h⟩ + rw [toCharThreeNF, variableChange_comp] + set W' := W.variableChange W.toShortNFOfCharThree + haveI : W'.IsCharNeTwoNF := W.toCharNeTwoNF_spec + constructor + · simp + · simp + · field_simp [W.toShortNFOfCharThree_a₂ ▸ hb₂] + linear_combination (W'.a₄ * W'.a₂ ^ 2 + W'.a₄ ^ 2) * CharP.cast_eq_zero F 3 + +theorem toCharThreeNF_spec_of_b₂_eq_zero (hb₂ : W.b₂ = 0) : + (W.variableChange W.toCharThreeNF).IsShortNF := by + rw [toCharThreeNF, toShortNFOfCharThree_a₂, hb₂, div_zero, ← VariableChange.id, + VariableChange.id_comp] + exact W.toShortNFOfCharThree_spec hb₂ + +instance toCharThreeNF_spec : (W.variableChange W.toCharThreeNF).IsCharThreeNF := by + by_cases hb₂ : W.b₂ = 0 + · haveI := W.toCharThreeNF_spec_of_b₂_eq_zero hb₂ + infer_instance + · haveI := W.toCharThreeNF_spec_of_b₂_ne_zero hb₂ + infer_instance + +theorem exists_variableChange_isCharThreeNF : + ∃ C : VariableChange F, (W.variableChange C).IsCharThreeNF := + ⟨_, W.toCharThreeNF_spec⟩ + +end VariableChange + +/-! ### Normal forms of characteristic = 2 and j ≠ 0 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic = 2 and j ≠ 0, if its $a_1 = 1$ and +$a_3, a_4 = 0$. In other words it is $Y^2 + XY = X^3 + a_2X^2 + a_6$. -/ +@[mk_iff] +class IsCharTwoJNeZeroNF : Prop where + a₁ : W.a₁ = 1 + a₃ : W.a₃ = 0 + a₄ : W.a₄ = 0 + +section Quantity + +variable [W.IsCharTwoJNeZeroNF] + +@[simp] +theorem a₁_of_isCharTwoJNeZeroNF : W.a₁ = 1 := IsCharTwoJNeZeroNF.a₁ + +@[simp] +theorem a₃_of_isCharTwoJNeZeroNF : W.a₃ = 0 := IsCharTwoJNeZeroNF.a₃ + +@[simp] +theorem a₄_of_isCharTwoJNeZeroNF : W.a₄ = 0 := IsCharTwoJNeZeroNF.a₄ + +@[simp] +theorem b₂_of_isCharTwoJNeZeroNF : W.b₂ = 1 + 4 * W.a₂ := by + rw [b₂, a₁_of_isCharTwoJNeZeroNF] + ring1 + +@[simp] +theorem b₄_of_isCharTwoJNeZeroNF : W.b₄ = 0 := by + rw [b₄, a₃_of_isCharTwoJNeZeroNF, a₄_of_isCharTwoJNeZeroNF] + ring1 + +@[simp] +theorem b₆_of_isCharTwoJNeZeroNF : W.b₆ = 4 * W.a₆ := by + rw [b₆, a₃_of_isCharTwoJNeZeroNF] + ring1 + +@[simp] +theorem b₈_of_isCharTwoJNeZeroNF : W.b₈ = W.a₆ + 4 * W.a₂ * W.a₆ := by + rw [b₈, a₁_of_isCharTwoJNeZeroNF, a₃_of_isCharTwoJNeZeroNF, a₄_of_isCharTwoJNeZeroNF] + ring1 + +@[simp] +theorem c₄_of_isCharTwoJNeZeroNF : W.c₄ = W.b₂ ^ 2 := by + rw [c₄, b₄_of_isCharTwoJNeZeroNF] + ring1 + +@[simp] +theorem c₆_of_isCharTwoJNeZeroNF : W.c₆ = -W.b₂ ^ 3 - 864 * W.a₆ := by + rw [c₆, b₄_of_isCharTwoJNeZeroNF, b₆_of_isCharTwoJNeZeroNF] + ring1 + +variable [CharP R 2] + +theorem b₂_of_isCharTwoJNeZeroNF_of_char_two : W.b₂ = 1 := by + rw [b₂_of_isCharTwoJNeZeroNF] + linear_combination 2 * W.a₂ * CharP.cast_eq_zero R 2 + +theorem b₆_of_isCharTwoJNeZeroNF_of_char_two : W.b₆ = 0 := by + rw [b₆_of_isCharTwoJNeZeroNF] + linear_combination 2 * W.a₆ * CharP.cast_eq_zero R 2 + +theorem b₈_of_isCharTwoJNeZeroNF_of_char_two : W.b₈ = W.a₆ := by + rw [b₈_of_isCharTwoJNeZeroNF] + linear_combination 2 * W.a₂ * W.a₆ * CharP.cast_eq_zero R 2 + +theorem c₄_of_isCharTwoJNeZeroNF_of_char_two : W.c₄ = 1 := by + rw [c₄_of_isCharTwoJNeZeroNF, b₂_of_isCharTwoJNeZeroNF_of_char_two] + ring1 + +theorem c₆_of_isCharTwoJNeZeroNF_of_char_two : W.c₆ = 1 := by + rw [c₆_of_isCharTwoJNeZeroNF, b₂_of_isCharTwoJNeZeroNF_of_char_two] + linear_combination (-1 - 432 * W.a₆) * CharP.cast_eq_zero R 2 + +@[simp] +theorem Δ_of_isCharTwoJNeZeroNF_of_char_two : W.Δ = W.a₆ := by + rw [Δ, b₂_of_isCharTwoJNeZeroNF_of_char_two, b₄_of_isCharTwoJNeZeroNF, + b₆_of_isCharTwoJNeZeroNF_of_char_two, b₈_of_isCharTwoJNeZeroNF_of_char_two] + linear_combination -W.a₆ * CharP.cast_eq_zero R 2 + +variable [E.IsCharTwoJNeZeroNF] [CharP F 2] + +@[simp] +theorem _root_.EllipticCurve.j_of_isCharTwoJNeZeroNF_of_char_two : E.j = 1 / E.a₆ := by + rw [EllipticCurve.j, Units.val_inv_eq_inv_val, ← div_eq_inv_mul, E.coe_Δ', + c₄_of_isCharTwoJNeZeroNF_of_char_two, Δ_of_isCharTwoJNeZeroNF_of_char_two, one_pow] + +theorem _root_.EllipticCurve.j_ne_zero_of_isCharTwoJNeZeroNF_of_char_two : E.j ≠ 0 := by + rw [E.j_of_isCharTwoJNeZeroNF_of_char_two, div_ne_zero_iff] + have h := E.Δ'.ne_zero + rw [E.coe_Δ', Δ_of_isCharTwoJNeZeroNF_of_char_two] at h + exact ⟨one_ne_zero, h⟩ + +end Quantity + +/-! ### Normal forms of characteristic = 2 and j = 0 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic = 2 and j = 0, if its $a_1, a_2 = 0$. +In other words it is $Y^2 + a_3Y = X^3 + a_4X + a_6$. -/ +@[mk_iff] +class IsCharTwoJEqZeroNF : Prop where + a₁ : W.a₁ = 0 + a₂ : W.a₂ = 0 + +section Quantity + +variable [W.IsCharTwoJEqZeroNF] + +@[simp] +theorem a₁_of_isCharTwoJEqZeroNF : W.a₁ = 0 := IsCharTwoJEqZeroNF.a₁ + +@[simp] +theorem a₂_of_isCharTwoJEqZeroNF : W.a₂ = 0 := IsCharTwoJEqZeroNF.a₂ + +@[simp] +theorem b₂_of_isCharTwoJEqZeroNF : W.b₂ = 0 := by + rw [b₂, a₁_of_isCharTwoJEqZeroNF, a₂_of_isCharTwoJEqZeroNF] + ring1 + +@[simp] +theorem b₄_of_isCharTwoJEqZeroNF : W.b₄ = 2 * W.a₄ := by + rw [b₄, a₁_of_isCharTwoJEqZeroNF] + ring1 + +@[simp] +theorem b₈_of_isCharTwoJEqZeroNF : W.b₈ = -W.a₄ ^ 2 := by + rw [b₈, a₁_of_isCharTwoJEqZeroNF, a₂_of_isCharTwoJEqZeroNF] + ring1 + +@[simp] +theorem c₄_of_isCharTwoJEqZeroNF : W.c₄ = -48 * W.a₄ := by + rw [c₄, b₂_of_isCharTwoJEqZeroNF, b₄_of_isCharTwoJEqZeroNF] + ring1 + +@[simp] +theorem c₆_of_isCharTwoJEqZeroNF : W.c₆ = -216 * W.b₆ := by + rw [c₆, b₂_of_isCharTwoJEqZeroNF, b₄_of_isCharTwoJEqZeroNF] + ring1 + +@[simp] +theorem Δ_of_isCharTwoJEqZeroNF : W.Δ = -(64 * W.a₄ ^ 3 + 27 * W.b₆ ^ 2) := by + rw [Δ, b₂_of_isCharTwoJEqZeroNF, b₄_of_isCharTwoJEqZeroNF] + ring1 + +variable [CharP R 2] + +theorem b₄_of_isCharTwoJEqZeroNF_of_char_two : W.b₄ = 0 := by + rw [b₄_of_isCharTwoJEqZeroNF] + linear_combination W.a₄ * CharP.cast_eq_zero R 2 + +theorem b₈_of_isCharTwoJEqZeroNF_of_char_two : W.b₈ = W.a₄ ^ 2 := by + rw [b₈_of_isCharTwoJEqZeroNF] + linear_combination -W.a₄ ^ 2 * CharP.cast_eq_zero R 2 + +theorem c₄_of_isCharTwoJEqZeroNF_of_char_two : W.c₄ = 0 := by + rw [c₄_of_isCharTwoJEqZeroNF] + linear_combination -24 * W.a₄ * CharP.cast_eq_zero R 2 + +theorem c₆_of_isCharTwoJEqZeroNF_of_char_two : W.c₆ = 0 := by + rw [c₆_of_isCharTwoJEqZeroNF] + linear_combination -108 * W.b₆ * CharP.cast_eq_zero R 2 + +theorem Δ_of_isCharTwoJEqZeroNF_of_char_two : W.Δ = W.a₃ ^ 4 := by + rw [Δ_of_isCharTwoJEqZeroNF, b₆_of_char_two] + linear_combination (-32 * W.a₄ ^ 3 - 14 * W.a₃ ^ 4) * CharP.cast_eq_zero R 2 + +variable [E.IsCharTwoJEqZeroNF] + +theorem _root_.EllipticCurve.j_of_isCharTwoJEqZeroNF : + E.j = 110592 * E.a₄ ^ 3 / (64 * E.a₄ ^ 3 + 27 * E.b₆ ^ 2) := by + have h := E.Δ'.ne_zero + rw [E.coe_Δ', Δ_of_isCharTwoJEqZeroNF] at h + rw [EllipticCurve.j, Units.val_inv_eq_inv_val, ← div_eq_inv_mul, E.coe_Δ', + c₄_of_isCharTwoJEqZeroNF, Δ_of_isCharTwoJEqZeroNF, div_eq_div_iff h (neg_ne_zero.1 h)] + ring1 + +@[simp] +theorem _root_.EllipticCurve.j_of_isCharTwoJEqZeroNF_of_char_two [CharP F 2] : E.j = 0 := by + rw [EllipticCurve.j, c₄_of_isCharTwoJEqZeroNF_of_char_two]; simp + +end Quantity + +/-! ### Normal forms of characteristic = 2 -/ + +/-- A `WeierstrassCurve` is in normal form of characteristic = 2, if it is +$Y^2 + XY = X^3 + a_2X^2 + a_6$ (`WeierstrassCurve.IsCharTwoJNeZeroNF`) or +$Y^2 + a_3Y = X^3 + a_4X + a_6$ (`WeierstrassCurve.IsCharTwoJEqZeroNF`). -/ +class inductive IsCharTwoNF : Prop +| of_j_ne_zero [W.IsCharTwoJNeZeroNF] : IsCharTwoNF +| of_j_eq_zero [W.IsCharTwoJEqZeroNF] : IsCharTwoNF + +instance isCharTwoNF_of_isCharTwoJNeZeroNF [W.IsCharTwoJNeZeroNF] : W.IsCharTwoNF := + IsCharTwoNF.of_j_ne_zero + +instance isCharTwoNF_of_isCharTwoJEqZeroNF [W.IsCharTwoJEqZeroNF] : W.IsCharTwoNF := + IsCharTwoNF.of_j_eq_zero + +section VariableChange + +variable [CharP R 2] [CharP F 2] + +/-- For a `WeierstrassCurve` defined over a ring of characteristic = 2, +there is an explicit change of variables of it to $Y^2 + a_3Y = X^3 + a_4X + a_6$ +(`WeierstrassCurve.IsCharTwoJEqZeroNF`) if its j = 0. -/ +def toCharTwoJEqZeroNF : VariableChange R := ⟨1, W.a₂, 0, 0⟩ + +theorem toCharTwoJEqZeroNF_spec (ha₁ : W.a₁ = 0) : + (W.variableChange W.toCharTwoJEqZeroNF).IsCharTwoJEqZeroNF := by + constructor + · simp [toCharTwoJEqZeroNF, ha₁] + · simp_rw [toCharTwoJEqZeroNF, variableChange_a₂, inv_one, Units.val_one] + linear_combination 2 * W.a₂ * CharP.cast_eq_zero R 2 + +variable (W : WeierstrassCurve F) + +/-- For a `WeierstrassCurve` defined over a field of characteristic = 2, +there is an explicit change of variables of it to $Y^2 + XY = X^3 + a_2X^2 + a_6$ +(`WeierstrassCurve.IsCharTwoJNeZeroNF`) if its j ≠ 0. -/ +def toCharTwoJNeZeroNF (W : WeierstrassCurve F) (ha₁ : W.a₁ ≠ 0) : VariableChange F := + ⟨Units.mk0 _ ha₁, W.a₃ / W.a₁, 0, (W.a₁ ^ 2 * W.a₄ + W.a₃ ^ 2) / W.a₁ ^ 3⟩ + +theorem toCharTwoJNeZeroNF_spec (ha₁ : W.a₁ ≠ 0) : + (W.variableChange (W.toCharTwoJNeZeroNF ha₁)).IsCharTwoJNeZeroNF := by + constructor + · simp [toCharTwoJNeZeroNF, ha₁] + · field_simp [toCharTwoJNeZeroNF] + linear_combination (W.a₃ * W.a₁ ^ 3 + W.a₁ ^ 2 * W.a₄ + W.a₃ ^ 2) * CharP.cast_eq_zero F 2 + · field_simp [toCharTwoJNeZeroNF] + linear_combination (W.a₁ ^ 4 * W.a₃ ^ 2 + W.a₁ ^ 5 * W.a₃ * W.a₂) * CharP.cast_eq_zero F 2 + +/-- For a `WeierstrassCurve` defined over a field of characteristic = 2, +there is an explicit change of variables of it to `WeierstrassCurve.IsCharTwoNF`, that is, +$Y^2 + XY = X^3 + a_2X^2 + a_6$ (`WeierstrassCurve.IsCharTwoJNeZeroNF`) or +$Y^2 + a_3Y = X^3 + a_4X + a_6$ (`WeierstrassCurve.IsCharTwoJEqZeroNF`). -/ +def toCharTwoNF [DecidableEq F] : VariableChange F := + if ha₁ : W.a₁ = 0 then W.toCharTwoJEqZeroNF else W.toCharTwoJNeZeroNF ha₁ + +instance toCharTwoNF_spec [DecidableEq F] : (W.variableChange W.toCharTwoNF).IsCharTwoNF := by + by_cases ha₁ : W.a₁ = 0 + · rw [toCharTwoNF, dif_pos ha₁] + haveI := W.toCharTwoJEqZeroNF_spec ha₁ + infer_instance + · rw [toCharTwoNF, dif_neg ha₁] + haveI := W.toCharTwoJNeZeroNF_spec ha₁ + infer_instance + +theorem exists_variableChange_isCharTwoNF : + ∃ C : VariableChange F, (W.variableChange C).IsCharTwoNF := by + classical + exact ⟨_, W.toCharTwoNF_spec⟩ + +end VariableChange + +end WeierstrassCurve diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean index 1c20ec00d569e..3d4ea8337acc9 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Projective.lean @@ -115,8 +115,8 @@ lemma comp_fin3 {S : Type v} (f : R → S) (X Y Z : R) : f ∘ ![X, Y, Z] = ![f variable [CommRing R] -lemma smul_fin3 (P : Fin 3 → R) (u : R) : u • P = ![u * P x, u * P y, u * P z] := - List.ofFn_inj.mp rfl +lemma smul_fin3 (P : Fin 3 → R) (u : R) : u • P = ![u * P x, u * P y, u * P z] := by + simp [← List.ofFn_inj] lemma smul_fin3_ext (P : Fin 3 → R) (u : R) : (u • P) x = u * P x ∧ (u • P) y = u * P y ∧ (u • P) z = u * P z := diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/VariableChange.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/VariableChange.lean new file mode 100644 index 0000000000000..8f77cea60aaad --- /dev/null +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/VariableChange.lean @@ -0,0 +1,325 @@ +/- +Copyright (c) 2024 Jz Pan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kevin Buzzard, David Kurniadi Angdinata, Jz Pan +-/ +import Mathlib.AlgebraicGeometry.EllipticCurve.Weierstrass + +/-! +# Change of variables of Weierstrass curves + +This file defines admissible linear change of variables of Weierstrass curves. + +## Main definitions + + * `WeierstrassCurve.VariableChange`: a change of variables of Weierstrass curves. + * `WeierstrassCurve.variableChange`: the Weierstrass curve induced by a change of variables. + * `WeierstrassCurve.instMulActionVariableChange`: change of variables act on Weierstrass curves. + * `EllipticCurve.variableChange`: the elliptic curve induced by a change of variables. + * `EllipticCurve.instMulActionVariableChange`: change of variables act on elliptic curves. + +## Main statements + + * `EllipticCurve.variableChange_j`: the j-invariant of an elliptic curve is invariant under an + admissible linear change of variables. + +## References + + * [J Silverman, *The Arithmetic of Elliptic Curves*][silverman2009] + +## Tags + +elliptic curve, weierstrass equation, change of variables +-/ + +local macro "map_simp" : tactic => + `(tactic| simp only [map_ofNat, map_neg, map_add, map_sub, map_mul, map_pow]) + +universe s u v w + +namespace WeierstrassCurve + +variable {R : Type u} [CommRing R] (W : WeierstrassCurve R) + +section VariableChange + +/-! ### Variable changes -/ + +/-- An admissible linear change of variables of Weierstrass curves defined over a ring `R` given by +a tuple $(u, r, s, t)$ for some $u \in R^\times$ and some $r, s, t \in R$. As a matrix, it is +$\begin{pmatrix} u^2 & 0 & r \cr u^2s & u^3 & t \cr 0 & 0 & 1 \end{pmatrix}$. -/ +@[ext] +structure VariableChange (R : Type u) [CommRing R] where + /-- The `u` coefficient of an admissible linear change of variables, which must be a unit. -/ + u : Rˣ + /-- The `r` coefficient of an admissible linear change of variables. -/ + r : R + /-- The `s` coefficient of an admissible linear change of variables. -/ + s : R + /-- The `t` coefficient of an admissible linear change of variables. -/ + t : R + +namespace VariableChange + +variable (C C' C'' : VariableChange R) + +/-- The identity linear change of variables given by the identity matrix. -/ +def id : VariableChange R := + ⟨1, 0, 0, 0⟩ + +/-- 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 + +/-- 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 + +lemma id_comp (C : VariableChange R) : comp id C = C := by + simp only [comp, id, zero_add, zero_mul, mul_zero, one_mul] + +lemma comp_id (C : VariableChange R) : comp C id = C := by + simp only [comp, id, add_zero, mul_zero, one_mul, mul_one, one_pow, Units.val_one] + +lemma comp_left_inv (C : VariableChange R) : comp (inv C) C = id := by + rw [comp, id, inv] + ext <;> dsimp only + · exact C.u.inv_mul + · linear_combination (norm := ring1) -C.r * pow_mul_pow_eq_one 2 C.u.inv_mul + · linear_combination (norm := ring1) -C.s * C.u.inv_mul + · linear_combination (norm := ring1) (C.r * C.s - C.t) * pow_mul_pow_eq_one 3 C.u.inv_mul + + -C.r * C.s * pow_mul_pow_eq_one 2 C.u.inv_mul + +lemma comp_assoc (C C' C'' : VariableChange R) : comp (comp C C') C'' = comp C (comp C' C'') := by + ext <;> simp only [comp, Units.val_mul] <;> ring1 + +instance instGroup : Group (VariableChange R) where + one := id + inv := inv + mul := comp + one_mul := id_comp + mul_one := comp_id + inv_mul_cancel := comp_left_inv + mul_assoc := comp_assoc + +end VariableChange + +variable (C : VariableChange R) + +/-- The Weierstrass curve over `R` induced by an admissible linear change of variables +$(X, Y) \mapsto (u^2X + r, u^3Y + u^2sX + t)$ for some $u \in R^\times$ and some $r, s, t \in R$. -/ +@[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 + - 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 + - C.r * C.t * W.a₁) + +lemma variableChange_id : W.variableChange VariableChange.id = W := by + rw [VariableChange.id, variableChange, inv_one, Units.val_one] + ext <;> (dsimp only; ring1) + +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.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⁻¹ ^ 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⁻¹ ^ 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⁻¹ ^ 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⁻¹ ^ 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 + one_smul := variableChange_id + mul_smul := variableChange_comp + +@[simp] +lemma variableChange_b₂ : (W.variableChange C).b₂ = C.u⁻¹ ^ 2 * (W.b₂ + 12 * C.r) := by + simp only [b₂, variableChange_a₁, variableChange_a₂] + ring1 + +@[simp] +lemma variableChange_b₄ : + (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 + +@[simp] +lemma variableChange_b₆ : (W.variableChange C).b₆ = + 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 + +@[simp] +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₆] + ring1 + +@[simp] +lemma variableChange_c₄ : (W.variableChange C).c₄ = C.u⁻¹ ^ 4 * W.c₄ := by + simp only [c₄, variableChange_b₂, variableChange_b₄] + ring1 + +@[simp] +lemma variableChange_c₆ : (W.variableChange C).c₆ = C.u⁻¹ ^ 6 * W.c₆ := by + simp only [c₆, variableChange_b₂, variableChange_b₄, variableChange_b₆] + ring1 + +@[simp] +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 + +end VariableChange + +section BaseChange + +/-! ### Maps and base changes of variable changes -/ + +variable {A : Type v} [CommRing A] (φ : R →+* A) + +namespace VariableChange + +variable (C : VariableChange R) + +/-- The change of variables mapped over a ring homomorphism `φ : R →+* A`. -/ +@[simps] +def map : VariableChange A := + ⟨Units.map φ C.u, φ C.r, φ C.s, φ C.t⟩ + +variable (A) + +/-- The change of variables base changed to an algebra `A` over `R`. -/ +abbrev baseChange [Algebra R A] : VariableChange A := + C.map <| algebraMap R A + +variable {A} + +@[simp] +lemma map_id : C.map (RingHom.id R) = C := + rfl + +lemma map_map {A : Type v} [CommRing A] (φ : R →+* A) {B : Type w} [CommRing B] (ψ : A →+* B) : + (C.map φ).map ψ = C.map (ψ.comp φ) := + rfl + +@[simp] +lemma map_baseChange {S : Type s} [CommRing S] [Algebra R S] {A : Type v} [CommRing A] [Algebra R A] + [Algebra S A] [IsScalarTower R S A] {B : Type w} [CommRing B] [Algebra R B] [Algebra S B] + [IsScalarTower R S B] (ψ : A →ₐ[S] B) : (C.baseChange A).map ψ = C.baseChange B := + congr_arg C.map <| ψ.comp_algebraMap_of_tower R + +lemma map_injective {φ : R →+* A} (hφ : Function.Injective φ) : + Function.Injective <| map (φ := φ) := fun _ _ h => by + rcases mk.inj h with ⟨h, _, _, _⟩ + replace h := (Units.mk.inj h).left + ext <;> apply_fun _ using hφ <;> assumption + +private lemma id_map : (id : VariableChange R).map φ = id := by + simp only [id, map] + ext <;> simp only [map_one, Units.val_one, map_zero] + +private lemma comp_map (C' : VariableChange R) : (C.comp C').map φ = (C.map φ).comp (C'.map φ) := by + simp only [comp, map] + ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] + +/-- The map over a ring homomorphism of a change of variables is a group homomorphism. -/ +def mapHom : VariableChange R →* VariableChange A where + toFun := map φ + map_one' := id_map φ + map_mul' := comp_map φ + +end VariableChange + +lemma map_variableChange (C : VariableChange R) : + (W.map φ).variableChange (C.map φ) = (W.variableChange C).map φ := by + simp only [map, variableChange, VariableChange.map] + ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] + +end BaseChange + +end WeierstrassCurve + +/-! ## Variable changes of elliptic curves -/ + +namespace EllipticCurve + +variable {R : Type u} [CommRing R] + +variable (E : EllipticCurve R) + +section VariableChange + +variable (C : WeierstrassCurve.VariableChange R) + +-- Porting note: was just `@[simps]` +/-- The elliptic curve over `R` induced by an admissible linear change of variables +$(X, Y) \mapsto (u^2X + r, u^3Y + u^2sX + t)$ for some $u \in R^\times$ and some $r, s, t \in R$. +When `R` is a field, any two Weierstrass equations isomorphic to `E` are related by this. -/ +@[simps (config := { rhsMd := .default }) a₁ a₂ a₃ a₄ a₆ Δ' toWeierstrassCurve] +def variableChange : EllipticCurve R := + ⟨E.toWeierstrassCurve.variableChange C, C.u⁻¹ ^ 12 * E.Δ', by + rw [Units.val_mul, Units.val_pow_eq_pow_val, coe_Δ', E.variableChange_Δ]⟩ + +lemma variableChange_id : E.variableChange WeierstrassCurve.VariableChange.id = E := by + simp only [variableChange, WeierstrassCurve.variableChange_id] + simp only [WeierstrassCurve.VariableChange.id, inv_one, one_pow, one_mul] + +lemma variableChange_comp (C C' : WeierstrassCurve.VariableChange R) (E : EllipticCurve R) : + E.variableChange (C.comp C') = (E.variableChange C').variableChange C := by + simp only [variableChange, WeierstrassCurve.variableChange_comp] + simp only [WeierstrassCurve.VariableChange.comp, mul_inv, mul_pow, ← mul_assoc] + +instance instMulActionVariableChange : + MulAction (WeierstrassCurve.VariableChange R) (EllipticCurve R) where + smul := fun C E => E.variableChange C + one_smul := variableChange_id + mul_smul := variableChange_comp + +lemma coe_variableChange_Δ' : (E.variableChange C).Δ' = C.u⁻¹ ^ 12 * E.Δ' := + rfl + +lemma coe_inv_variableChange_Δ' : (E.variableChange C).Δ'⁻¹ = C.u ^ 12 * E.Δ'⁻¹ := by + rw [variableChange_Δ', mul_inv, inv_pow, inv_inv] + +@[simp] +lemma variableChange_j : (E.variableChange C).j = E.j := by + 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 + +end VariableChange + +end EllipticCurve diff --git a/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean b/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean index d07fdd996d68d..9d730cf3c9239 100644 --- a/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean +++ b/Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean @@ -3,6 +3,7 @@ Copyright (c) 2021 Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, David Kurniadi Angdinata -/ +import Mathlib.Algebra.CharP.Defs import Mathlib.Algebra.CubicDiscriminant import Mathlib.Tactic.FieldSimp import Mathlib.Tactic.LinearCombination @@ -33,8 +34,6 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi * `WeierstrassCurve.ofJ0`: a Weierstrass curve whose j-invariant is 0. * `WeierstrassCurve.ofJ1728`: a Weierstrass curve whose j-invariant is 1728. * `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.map`: the Weierstrass curve mapped over a ring homomorphism. * `WeierstrassCurve.twoTorsionPolynomial`: the 2-torsion polynomial of a Weierstrass curve. * `EllipticCurve`: an elliptic curve over a commutative ring. @@ -48,8 +47,6 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi * `WeierstrassCurve.twoTorsionPolynomial_disc`: the discriminant of a Weierstrass curve is a constant factor of the cubic discriminant of its 2-torsion polynomial. - * `EllipticCurve.variableChange_j`: the j-invariant of an elliptic curve is invariant under an - admissible linear change of variables. * `EllipticCurve.ofJ_j`: the j-invariant of `EllipticCurve.ofJ` is equal to j. ## Implementation notes @@ -106,22 +103,18 @@ section Quantity /-! ### Standard quantities -/ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `b₂` coefficient of a Weierstrass curve. -/ def b₂ : R := W.a₁ ^ 2 + 4 * W.a₂ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `b₄` coefficient of a Weierstrass curve. -/ def b₄ : R := 2 * W.a₄ + W.a₁ * W.a₃ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `b₆` coefficient of a Weierstrass curve. -/ def b₆ : R := W.a₃ ^ 2 + 4 * W.a₆ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `b₈` coefficient of a Weierstrass curve. -/ def b₈ : R := W.a₁ ^ 2 * W.a₆ + 4 * W.a₂ * W.a₆ - W.a₁ * W.a₃ * W.a₄ + W.a₂ * W.a₃ ^ 2 - W.a₄ ^ 2 @@ -130,17 +123,14 @@ lemma b_relation : 4 * W.b₈ = W.b₂ * W.b₆ - W.b₄ ^ 2 := by simp only [b₂, b₄, b₆, b₈] ring1 --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `c₄` coefficient of a Weierstrass curve. -/ def c₄ : R := W.b₂ ^ 2 - 24 * W.b₄ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The `c₆` coefficient of a Weierstrass curve. -/ def c₆ : R := -W.b₂ ^ 3 + 36 * W.b₂ * W.b₄ - 216 * W.b₆ --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The discriminant `Δ` of a Weierstrass curve. If `R` is a field, then this polynomial vanishes if and only if the cubic curve cut out by this equation is singular. Sometimes only defined up to sign in the literature; we choose the sign used by the LMFDB. For more discussion, see @@ -152,169 +142,89 @@ lemma c_relation : 1728 * W.Δ = W.c₄ ^ 3 - W.c₆ ^ 2 := by simp only [b₂, b₄, b₆, b₈, c₄, c₆, Δ] ring1 -end Quantity +section CharTwo -section VariableChange +variable [CharP R 2] -/-! ### Variable changes -/ +lemma b₂_of_char_two : W.b₂ = W.a₁ ^ 2 := by + rw [b₂] + linear_combination 2 * W.a₂ * CharP.cast_eq_zero R 2 -/-- An admissible linear change of variables of Weierstrass curves defined over a ring `R` given by -a tuple $(u, r, s, t)$ for some $u \in R^\times$ and some $r, s, t \in R$. As a matrix, it is -$\begin{pmatrix} u^2 & 0 & r \cr u^2s & u^3 & t \cr 0 & 0 & 1 \end{pmatrix}$. -/ -@[ext] -structure VariableChange (R : Type u) [CommRing R] where - /-- The `u` coefficient of an admissible linear change of variables, which must be a unit. -/ - u : Rˣ - /-- The `r` coefficient of an admissible linear change of variables. -/ - r : R - /-- The `s` coefficient of an admissible linear change of variables. -/ - s : R - /-- The `t` coefficient of an admissible linear change of variables. -/ - t : R - -namespace VariableChange - -variable (C C' C'' : VariableChange R) - -/-- The identity linear change of variables given by the identity matrix. -/ -def id : VariableChange R := - ⟨1, 0, 0, 0⟩ - -/-- 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 - -/-- 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 - -lemma id_comp (C : VariableChange R) : comp id C = C := by - simp only [comp, id, zero_add, zero_mul, mul_zero, one_mul] - -lemma comp_id (C : VariableChange R) : comp C id = C := by - simp only [comp, id, add_zero, mul_zero, one_mul, mul_one, one_pow, Units.val_one] - -lemma comp_left_inv (C : VariableChange R) : comp (inv C) C = id := by - rw [comp, id, inv] - ext <;> dsimp only - · exact C.u.inv_mul - · linear_combination (norm := ring1) -C.r * pow_mul_pow_eq_one 2 C.u.inv_mul - · linear_combination (norm := ring1) -C.s * C.u.inv_mul - · linear_combination (norm := ring1) (C.r * C.s - C.t) * pow_mul_pow_eq_one 3 C.u.inv_mul - + -C.r * C.s * pow_mul_pow_eq_one 2 C.u.inv_mul - -lemma comp_assoc (C C' C'' : VariableChange R) : comp (comp C C') C'' = comp C (comp C' C'') := by - ext <;> simp only [comp, Units.val_mul] <;> ring1 - -instance instGroup : Group (VariableChange R) where - one := id - inv := inv - mul := comp - one_mul := id_comp - mul_one := comp_id - inv_mul_cancel := comp_left_inv - mul_assoc := comp_assoc - -end VariableChange - -variable (C : VariableChange R) - -/-- The Weierstrass curve over `R` induced by an admissible linear change of variables -$(X, Y) \mapsto (u^2X + r, u^3Y + u^2sX + t)$ for some $u \in R^\times$ and some $r, s, t \in R$. -/ -@[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 - - 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 - - C.r * C.t * W.a₁) - -lemma variableChange_id : W.variableChange VariableChange.id = W := by - rw [VariableChange.id, variableChange, inv_one, Units.val_one] - ext <;> (dsimp only; ring1) - -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.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⁻¹ ^ 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⁻¹ ^ 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⁻¹ ^ 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⁻¹ ^ 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 - one_smul := variableChange_id - mul_smul := variableChange_comp +lemma b₄_of_char_two : W.b₄ = W.a₁ * W.a₃ := by + rw [b₄] + linear_combination W.a₄ * CharP.cast_eq_zero R 2 -@[simp] -lemma variableChange_b₂ : (W.variableChange C).b₂ = C.u⁻¹ ^ 2 * (W.b₂ + 12 * C.r) := by - simp only [b₂, variableChange_a₁, variableChange_a₂] - ring1 +lemma b₆_of_char_two : W.b₆ = W.a₃ ^ 2 := by + rw [b₆] + linear_combination 2 * W.a₆ * CharP.cast_eq_zero R 2 -@[simp] -lemma variableChange_b₄ : - (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 +lemma b₈_of_char_two : + W.b₈ = W.a₁ ^ 2 * W.a₆ + W.a₁ * W.a₃ * W.a₄ + W.a₂ * W.a₃ ^ 2 + W.a₄ ^ 2 := by + rw [b₈] + linear_combination (2 * W.a₂ * W.a₆ - W.a₁ * W.a₃ * W.a₄ - W.a₄ ^ 2) * CharP.cast_eq_zero R 2 -@[simp] -lemma variableChange_b₆ : (W.variableChange C).b₆ = - 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 +lemma c₄_of_char_two : W.c₄ = W.a₁ ^ 4 := by + rw [c₄, b₂_of_char_two] + linear_combination -12 * W.b₄ * CharP.cast_eq_zero R 2 -@[simp] -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₆] - ring1 +lemma c₆_of_char_two : W.c₆ = W.a₁ ^ 6 := by + rw [c₆, b₂_of_char_two] + linear_combination (18 * W.a₁ ^ 2 * W.b₄ - 108 * W.b₆ - W.a₁ ^ 6) * CharP.cast_eq_zero R 2 -@[simp] -lemma variableChange_c₄ : (W.variableChange C).c₄ = C.u⁻¹ ^ 4 * W.c₄ := by - simp only [c₄, variableChange_b₂, variableChange_b₄] - ring1 +lemma Δ_of_char_two : W.Δ = W.a₁ ^ 4 * W.b₈ + W.a₃ ^ 4 + W.a₁ ^ 3 * W.a₃ ^ 3 := by + rw [Δ, b₂_of_char_two, b₄_of_char_two, b₆_of_char_two] + linear_combination (-W.a₁ ^ 4 * W.b₈ - 14 * W.a₃ ^ 4) * CharP.cast_eq_zero R 2 -@[simp] -lemma variableChange_c₆ : (W.variableChange C).c₆ = C.u⁻¹ ^ 6 * W.c₆ := by - simp only [c₆, variableChange_b₂, variableChange_b₄, variableChange_b₆] - ring1 +lemma b_relation_of_char_two : W.b₂ * W.b₆ = W.b₄ ^ 2 := by + linear_combination -W.b_relation + 2 * W.b₈ * CharP.cast_eq_zero R 2 -@[simp] -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 +lemma c_relation_of_char_two : W.c₄ ^ 3 = W.c₆ ^ 2 := by + linear_combination -W.c_relation + 864 * W.Δ * CharP.cast_eq_zero R 2 + +end CharTwo + +section CharThree + +variable [CharP R 3] + +lemma b₂_of_char_three : W.b₂ = W.a₁ ^ 2 + W.a₂ := by + rw [b₂] + linear_combination W.a₂ * CharP.cast_eq_zero R 3 + +lemma b₄_of_char_three : W.b₄ = -W.a₄ + W.a₁ * W.a₃ := by + rw [b₄] + linear_combination W.a₄ * CharP.cast_eq_zero R 3 -end VariableChange +lemma b₆_of_char_three : W.b₆ = W.a₃ ^ 2 + W.a₆ := by + rw [b₆] + linear_combination W.a₆ * CharP.cast_eq_zero R 3 + +lemma b₈_of_char_three : + W.b₈ = W.a₁ ^ 2 * W.a₆ + W.a₂ * W.a₆ - W.a₁ * W.a₃ * W.a₄ + W.a₂ * W.a₃ ^ 2 - W.a₄ ^ 2 := by + rw [b₈] + linear_combination W.a₂ * W.a₆ * CharP.cast_eq_zero R 3 + +lemma c₄_of_char_three : W.c₄ = W.b₂ ^ 2 := by + rw [c₄] + linear_combination -8 * W.b₄ * CharP.cast_eq_zero R 3 + +lemma c₆_of_char_three : W.c₆ = -W.b₂ ^ 3 := by + rw [c₆] + linear_combination (12 * W.b₂ * W.b₄ - 72 * W.b₆) * CharP.cast_eq_zero R 3 + +lemma Δ_of_char_three : W.Δ = -W.b₂ ^ 2 * W.b₈ - 8 * W.b₄ ^ 3 := by + rw [Δ] + linear_combination (-9 * W.b₆ ^ 2 + 3 * W.b₂ * W.b₄ * W.b₆) * CharP.cast_eq_zero R 3 + +lemma b_relation_of_char_three : W.b₈ = W.b₂ * W.b₆ - W.b₄ ^ 2 := by + linear_combination W.b_relation - W.b₈ * CharP.cast_eq_zero R 3 + +lemma c_relation_of_char_three : W.c₄ ^ 3 = W.c₆ ^ 2 := by + linear_combination -W.c_relation + 576 * W.Δ * CharP.cast_eq_zero R 3 + +end CharThree + +end Quantity section BaseChange @@ -388,64 +298,6 @@ lemma map_injective {φ : R →+* A} (hφ : Function.Injective φ) : rcases mk.inj h with ⟨_, _, _, _, _⟩ ext <;> apply_fun _ using hφ <;> assumption -namespace VariableChange - -variable (C : VariableChange R) - -/-- The change of variables mapped over a ring homomorphism `φ : R →+* A`. -/ -@[simps] -def map : VariableChange A := - ⟨Units.map φ C.u, φ C.r, φ C.s, φ C.t⟩ - -variable (A) - -/-- The change of variables base changed to an algebra `A` over `R`. -/ -abbrev baseChange [Algebra R A] : VariableChange A := - C.map <| algebraMap R A - -variable {A} - -@[simp] -lemma map_id : C.map (RingHom.id R) = C := - rfl - -lemma map_map {A : Type v} [CommRing A] (φ : R →+* A) {B : Type w} [CommRing B] (ψ : A →+* B) : - (C.map φ).map ψ = C.map (ψ.comp φ) := - rfl - -@[simp] -lemma map_baseChange {S : Type s} [CommRing S] [Algebra R S] {A : Type v} [CommRing A] [Algebra R A] - [Algebra S A] [IsScalarTower R S A] {B : Type w} [CommRing B] [Algebra R B] [Algebra S B] - [IsScalarTower R S B] (ψ : A →ₐ[S] B) : (C.baseChange A).map ψ = C.baseChange B := - congr_arg C.map <| ψ.comp_algebraMap_of_tower R - -lemma map_injective {φ : R →+* A} (hφ : Function.Injective φ) : - Function.Injective <| map (φ := φ) := fun _ _ h => by - rcases mk.inj h with ⟨h, _, _, _⟩ - replace h := (Units.mk.inj h).left - ext <;> apply_fun _ using hφ <;> assumption - -private lemma id_map : (id : VariableChange R).map φ = id := by - simp only [id, map] - ext <;> simp only [map_one, Units.val_one, map_zero] - -private lemma comp_map (C' : VariableChange R) : (C.comp C').map φ = (C.map φ).comp (C'.map φ) := by - simp only [comp, map] - ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] - -/-- The map over a ring homomorphism of a change of variables is a group homomorphism. -/ -def mapHom : VariableChange R →* VariableChange A where - toFun := map φ - map_one' := id_map φ - map_mul' := comp_map φ - -end VariableChange - -lemma map_variableChange (C : VariableChange R) : - (W.map φ).variableChange (C.map φ) = (W.variableChange C).map φ := by - simp only [map, variableChange, VariableChange.map] - ext <;> map_simp <;> simp only [Units.coe_map, Units.coe_map_inv, MonoidHom.coe_coe] - end BaseChange section TorsionPolynomial @@ -462,6 +314,36 @@ lemma twoTorsionPolynomial_disc : W.twoTorsionPolynomial.disc = 16 * W.Δ := by simp only [b₂, b₄, b₆, b₈, Δ, twoTorsionPolynomial, Cubic.disc] ring1 +section CharTwo + +variable [CharP R 2] + +lemma twoTorsionPolynomial_of_char_two : W.twoTorsionPolynomial = ⟨0, W.b₂, 0, W.b₆⟩ := by + rw [twoTorsionPolynomial] + ext <;> dsimp + · linear_combination 2 * CharP.cast_eq_zero R 2 + · linear_combination W.b₄ * CharP.cast_eq_zero R 2 + +lemma twoTorsionPolynomial_disc_of_char_two : W.twoTorsionPolynomial.disc = 0 := by + linear_combination W.twoTorsionPolynomial_disc + 8 * W.Δ * CharP.cast_eq_zero R 2 + +end CharTwo + +section CharThree + +variable [CharP R 3] + +lemma twoTorsionPolynomial_of_char_three : W.twoTorsionPolynomial = ⟨1, W.b₂, -W.b₄, W.b₆⟩ := by + rw [twoTorsionPolynomial] + ext <;> dsimp + · linear_combination CharP.cast_eq_zero R 3 + · linear_combination W.b₄ * CharP.cast_eq_zero R 3 + +lemma twoTorsionPolynomial_disc_of_char_three : W.twoTorsionPolynomial.disc = W.Δ := by + linear_combination W.twoTorsionPolynomial_disc + 5 * W.Δ * CharP.cast_eq_zero R 3 + +end CharThree + lemma twoTorsionPolynomial_disc_isUnit [Invertible (2 : R)] : IsUnit W.twoTorsionPolynomial.disc ↔ IsUnit W.Δ := by rw [twoTorsionPolynomial_disc, IsUnit.mul_iff, show (16 : R) = 2 ^ 4 by norm_num1] @@ -549,59 +431,61 @@ theorem ext {x y : EllipticCurve R} (h₁ : x.a₁ = y.a₁) (h₂ : x.a₂ = y. variable (E : EllipticCurve R) --- Porting note (#10619): removed `@[simp]` to avoid a `simpNF` linter error /-- The j-invariant `j` of an elliptic curve, which is invariant under isomorphisms over `R`. -/ def j : R := E.Δ'⁻¹ * E.c₄ ^ 3 -lemma twoTorsionPolynomial_disc_ne_zero [Nontrivial R] [Invertible (2 : R)] : - E.twoTorsionPolynomial.disc ≠ 0 := - E.toWeierstrassCurve.twoTorsionPolynomial_disc_ne_zero <| E.coe_Δ' ▸ E.Δ'.isUnit +/-- A variant of `EllipticCurve.j_eq_zero_iff` without assuming a reduced ring. -/ +lemma j_eq_zero_iff' : E.j = 0 ↔ E.c₄ ^ 3 = 0 := by + rw [j, Units.mul_right_eq_zero] -section VariableChange +lemma j_eq_zero (h : E.c₄ = 0) : E.j = 0 := by + rw [j_eq_zero_iff', h, zero_pow three_ne_zero] -/-! ### Variable changes -/ +lemma j_eq_zero_iff [IsReduced R] : E.j = 0 ↔ E.c₄ = 0 := by + rw [j_eq_zero_iff', IsReduced.pow_eq_zero_iff three_ne_zero] -variable (C : WeierstrassCurve.VariableChange R) +section CharTwo --- Porting note: was just `@[simps]` -/-- The elliptic curve over `R` induced by an admissible linear change of variables -$(X, Y) \mapsto (u^2X + r, u^3Y + u^2sX + t)$ for some $u \in R^\times$ and some $r, s, t \in R$. -When `R` is a field, any two Weierstrass equations isomorphic to `E` are related by this. -/ -@[simps (config := { rhsMd := .default }) a₁ a₂ a₃ a₄ a₆ Δ' toWeierstrassCurve] -def variableChange : EllipticCurve R := - ⟨E.toWeierstrassCurve.variableChange C, C.u⁻¹ ^ 12 * E.Δ', by - rw [Units.val_mul, Units.val_pow_eq_pow_val, coe_Δ', E.variableChange_Δ]⟩ - -lemma variableChange_id : E.variableChange WeierstrassCurve.VariableChange.id = E := by - simp only [variableChange, WeierstrassCurve.variableChange_id] - simp only [WeierstrassCurve.VariableChange.id, inv_one, one_pow, one_mul] - -lemma variableChange_comp (C C' : WeierstrassCurve.VariableChange R) (E : EllipticCurve R) : - E.variableChange (C.comp C') = (E.variableChange C').variableChange C := by - simp only [variableChange, WeierstrassCurve.variableChange_comp] - simp only [WeierstrassCurve.VariableChange.comp, mul_inv, mul_pow, ← mul_assoc] - -instance instMulActionVariableChange : - MulAction (WeierstrassCurve.VariableChange R) (EllipticCurve R) where - smul := fun C E => E.variableChange C - one_smul := variableChange_id - mul_smul := variableChange_comp - -lemma coe_variableChange_Δ' : (E.variableChange C).Δ' = C.u⁻¹ ^ 12 * E.Δ' := - rfl +variable [CharP R 2] -lemma coe_inv_variableChange_Δ' : (E.variableChange C).Δ'⁻¹ = C.u ^ 12 * E.Δ'⁻¹ := by - rw [variableChange_Δ', mul_inv, inv_pow, inv_inv] +lemma j_of_char_two : E.j = E.Δ'⁻¹ * E.a₁ ^ 12 := by + rw [j, E.c₄_of_char_two, ← pow_mul] -@[simp] -lemma variableChange_j : (E.variableChange C).j = E.j := by - 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 +/-- A variant of `EllipticCurve.j_eq_zero_iff_of_char_two` without assuming a reduced ring. -/ +lemma j_eq_zero_iff_of_char_two' : E.j = 0 ↔ E.a₁ ^ 12 = 0 := by + rw [j_of_char_two, Units.mul_right_eq_zero] + +lemma j_eq_zero_of_char_two (h : E.a₁ = 0) : E.j = 0 := by + rw [j_eq_zero_iff_of_char_two', h, zero_pow (Nat.succ_ne_zero _)] + +lemma j_eq_zero_iff_of_char_two [IsReduced R] : E.j = 0 ↔ E.a₁ = 0 := by + rw [j_eq_zero_iff_of_char_two', IsReduced.pow_eq_zero_iff (Nat.succ_ne_zero _)] -end VariableChange +end CharTwo + +section CharThree + +variable [CharP R 3] + +lemma j_of_char_three : E.j = E.Δ'⁻¹ * E.b₂ ^ 6 := by + rw [j, E.c₄_of_char_three, ← pow_mul] + +/-- A variant of `EllipticCurve.j_eq_zero_iff_of_char_three` without assuming a reduced ring. -/ +lemma j_eq_zero_iff_of_char_three' : E.j = 0 ↔ E.b₂ ^ 6 = 0 := by + rw [j_of_char_three, Units.mul_right_eq_zero] + +lemma j_eq_zero_of_char_three (h : E.b₂ = 0) : E.j = 0 := by + rw [j_eq_zero_iff_of_char_three', h, zero_pow (Nat.succ_ne_zero _)] + +lemma j_eq_zero_iff_of_char_three [IsReduced R] : E.j = 0 ↔ E.b₂ = 0 := by + rw [j_eq_zero_iff_of_char_three', IsReduced.pow_eq_zero_iff (Nat.succ_ne_zero _)] + +end CharThree + +lemma twoTorsionPolynomial_disc_ne_zero [Nontrivial R] [Invertible (2 : R)] : + E.twoTorsionPolynomial.disc ≠ 0 := + E.toWeierstrassCurve.twoTorsionPolynomial_disc_ne_zero <| E.coe_Δ' ▸ E.Δ'.isUnit section BaseChange diff --git a/Mathlib/AlgebraicGeometry/FunctionField.lean b/Mathlib/AlgebraicGeometry/FunctionField.lean index da34fe72ff8b1..c58bde48fa4db 100644 --- a/Mathlib/AlgebraicGeometry/FunctionField.lean +++ b/Mathlib/AlgebraicGeometry/FunctionField.lean @@ -36,9 +36,9 @@ noncomputable abbrev Scheme.functionField [IrreducibleSpace X] : CommRingCat := /-- The restriction map from a component to the function field. -/ noncomputable abbrev Scheme.germToFunctionField [IrreducibleSpace X] (U : X.Opens) [h : Nonempty U] : Γ(X, U) ⟶ X.functionField := - X.presheaf.germ - ⟨genericPoint X, - ((genericPoint_spec X).mem_open_set_iff U.isOpen).mpr (by simpa using h)⟩ + X.presheaf.germ U + (genericPoint X) + (((genericPoint_spec X).mem_open_set_iff U.isOpen).mpr (by simpa using h)) noncomputable instance [IrreducibleSpace X] (U : X.Opens) [Nonempty U] : Algebra Γ(X, U) X.functionField := @@ -47,7 +47,7 @@ noncomputable instance [IrreducibleSpace X] (U : X.Opens) [Nonempty U] : noncomputable instance [IsIntegral X] : Field X.functionField := by refine .ofIsUnitOrEqZero fun a ↦ ?_ obtain ⟨U, m, s, rfl⟩ := TopCat.Presheaf.germ_exist _ _ a - rw [or_iff_not_imp_right, ← (X.presheaf.germ ⟨_, m⟩).map_zero] + rw [or_iff_not_imp_right, ← (X.presheaf.germ _ _ m).map_zero] intro ha replace ha := ne_of_apply_ne _ ha have hs : genericPoint X ∈ RingedSpace.basicOpen _ s := by @@ -56,22 +56,22 @@ noncomputable instance [IsIntegral X] : Field X.functionField := by · erw [basicOpen_eq_bot_iff] exact ha · exact (RingedSpace.basicOpen _ _).isOpen - have := (X.presheaf.germ ⟨_, hs⟩).isUnit_map (RingedSpace.isUnit_res_basicOpen _ s) + have := (X.presheaf.germ _ _ hs).isUnit_map (RingedSpace.isUnit_res_basicOpen _ s) rwa [TopCat.Presheaf.germ_res_apply] at this -theorem germ_injective_of_isIntegral [IsIntegral X] {U : X.Opens} (x : U) : - Function.Injective (X.presheaf.germ x) := by +theorem germ_injective_of_isIntegral [IsIntegral X] {U : X.Opens} (x : X) (hx : x ∈ U) : + Function.Injective (X.presheaf.germ U x hx) := by rw [injective_iff_map_eq_zero] intro y hy - rw [← (X.presheaf.germ x).map_zero] at hy - obtain ⟨W, hW, iU, iV, e⟩ := X.presheaf.germ_eq _ x.prop x.prop _ _ hy + rw [← (X.presheaf.germ U x hx).map_zero] at hy + obtain ⟨W, hW, iU, iV, e⟩ := X.presheaf.germ_eq _ hx hx _ _ hy cases Subsingleton.elim iU iV haveI : Nonempty W := ⟨⟨_, hW⟩⟩ exact map_injective_of_isIntegral X iU e theorem Scheme.germToFunctionField_injective [IsIntegral X] (U : X.Opens) [Nonempty U] : Function.Injective (X.germToFunctionField U) := - germ_injective_of_isIntegral _ _ + germ_injective_of_isIntegral _ _ _ theorem genericPoint_eq_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] [hX : IrreducibleSpace X] [IrreducibleSpace Y] : @@ -94,7 +94,7 @@ instance functionField_isScalarTower [IrreducibleSpace X] (U : X.Opens) (x : U) [Nonempty U] : IsScalarTower Γ(X, U) (X.presheaf.stalk x) X.functionField := by apply IsScalarTower.of_algebraMap_eq' simp_rw [RingHom.algebraMap_toAlgebra] - change _ = X.presheaf.germ x ≫ _ + change _ = X.presheaf.germ U x x.2 ≫ _ rw [X.presheaf.germ_stalkSpecializes] noncomputable instance (R : CommRingCat.{u}) [IsDomain R] : @@ -148,7 +148,8 @@ theorem functionField_isFractionRing_of_isAffineOpen [IsIntegral X] (U : X.Opens @isIntegral_of_isAffine_of_isDomain _ _ _ (by rw [Scheme.Opens.toScheme_presheaf_obj, Opens.openEmbedding_obj_top]; infer_instance) delta IsFractionRing Scheme.functionField - convert hU.isLocalization_stalk ⟨genericPoint X, _⟩ using 1 + convert hU.isLocalization_stalk ⟨genericPoint X, + (((genericPoint_spec X).mem_open_set_iff U.isOpen).mpr (by simpa using ‹Nonempty U›))⟩ using 1 rw [hU.primeIdealOf_genericPoint, genericPoint_eq_bot_of_affine] ext; exact mem_nonZeroDivisors_iff_ne_zero diff --git a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean index 927e5943d373d..7bd7ef196c89a 100644 --- a/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean +++ b/Mathlib/AlgebraicGeometry/GammaSpecAdjunction.lean @@ -74,7 +74,10 @@ open in `X` defined by the same element (they are equal as sets). -/ theorem toΓSpec_preimage_basicOpen_eq (r : Γ.obj (op X)) : X.toΓSpecFun ⁻¹' (basicOpen r).1 = (X.toRingedSpace.basicOpen r).1 := by ext - erw [X.toRingedSpace.mem_top_basicOpen]; apply not_mem_prime_iff_unit_in_stalk + dsimp + simp only [Set.mem_preimage, SetLike.mem_coe] + rw [X.toRingedSpace.mem_top_basicOpen] + exact not_mem_prime_iff_unit_in_stalk .. /-- `toΓSpecFun` is continuous. -/ theorem toΓSpec_continuous : Continuous X.toΓSpecFun := by @@ -153,7 +156,7 @@ def toΓSpecCBasicOpens : naturality r s f := by apply (StructureSheaf.to_basicOpen_epi (Γ.obj (op X)) r.unop).1 simp only [← Category.assoc] - erw [X.toΓSpecCApp_spec r.unop] + rw [X.toΓSpecCApp_spec r.unop] convert X.toΓSpecCApp_spec s.unop symm apply X.presheaf.map_comp @@ -181,16 +184,13 @@ theorem toΓSpecSheafedSpace_app_eq : stalks (in `Spec Γ(X)` and in `X`). -/ theorem toStalk_stalkMap_toΓSpec (x : X) : toStalk _ _ ≫ X.toΓSpecSheafedSpace.stalkMap x = X.presheaf.Γgerm x := by - rw [PresheafedSpace.Hom.stalkMap] - erw [← toOpen_germ _ (basicOpen (1 : Γ.obj (op X))) - ⟨X.toΓSpecFun x, by rw [basicOpen_one]; trivial⟩] - rw [← Category.assoc, Category.assoc (toOpen _ _)] - erw [stalkFunctor_map_germ] - rw [← Category.assoc, toΓSpecSheafedSpace_app_spec, Γgerm] - rw [← stalkPushforward_germ _ X.toΓSpecBase X.presheaf ⊤] + rw [PresheafedSpace.Hom.stalkMap, + ← toOpen_germ _ (basicOpen (1 : Γ.obj (op X))) _ (by rw [basicOpen_one]; trivial), + ← Category.assoc, Category.assoc (toOpen _ _), stalkFunctor_map_germ, ← Category.assoc, + toΓSpecSheafedSpace_app_spec, Γgerm] + erw [← stalkPushforward_germ _ _ X.presheaf ⊤] congr 1 - change (X.toΓSpecBase _* X.presheaf).map le_top.hom.op ≫ _ = _ - apply germ_res + exact (X.toΓSpecBase _* X.presheaf).germ_res le_top.hom _ _ /-- The canonical morphism from `X` to the spectrum of its global sections. -/ @[simps! val_base] @@ -254,9 +254,8 @@ theorem comp_ring_hom_ext {X : LocallyRingedSpace.{u}} {R : CommRingCat.{u}} {f /-- `toSpecΓ _` is an isomorphism so these are mutually two-sided inverses. -/ theorem Γ_Spec_left_triangle : toSpecΓ (Γ.obj (op X)) ≫ X.toΓSpec.1.c.app (op ⊤) = 𝟙 _ := by unfold toSpecΓ - rw [← toOpen_res _ (basicOpen (1 : Γ.obj (op X))) ⊤ (eqToHom basicOpen_one.symm)] - erw [Category.assoc] - rw [NatTrans.naturality, ← Category.assoc] + rw [← toOpen_res _ (basicOpen (1 : Γ.obj (op X))) ⊤ (eqToHom basicOpen_one.symm), + Category.assoc, NatTrans.naturality, ← Category.assoc] erw [X.toΓSpecSheafedSpace_app_spec 1, ← Functor.map_comp] convert eqToHom_map X.presheaf _; rfl @@ -269,24 +268,15 @@ def identityToΓSpec : 𝟭 LocallyRingedSpace.{u} ⟶ Γ.rightOp ⋙ Spec.toLoc symm apply LocallyRingedSpace.comp_ring_hom_ext · ext1 x - dsimp only [Spec.topMap, LocallyRingedSpace.toΓSpecFun] - -- Porting note: Had to add the next four lines - rw [comp_apply] - dsimp [toΓSpecBase] - -- The next six lines were `rw [ContinuousMap.coe_mk, ContinuousMap.coe_mk]` before - -- leanprover/lean4#2644 - have : (ContinuousMap.mk (toΓSpecFun Y) (toΓSpec_continuous _)) (f.val.base x) - = toΓSpecFun Y (f.val.base x) := by rw [ContinuousMap.coe_mk] - erw [this] - have : (ContinuousMap.mk (toΓSpecFun X) (toΓSpec_continuous _)) x - = toΓSpecFun X x := by rw [ContinuousMap.coe_mk] - erw [this] + dsimp + show PrimeSpectrum.comap (f.val.c.app (op ⊤)) (X.toΓSpecFun x) = Y.toΓSpecFun (f.val.base x) dsimp [toΓSpecFun] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [← LocalRing.comap_closedPoint (f.stalkMap x), ← + -- TODO: this instance was found automatically before #6045 + have := @AlgebraicGeometry.LocallyRingedSpace.isLocalRingHomStalkMap X Y + rw [← LocalRing.comap_closedPoint (f.stalkMap x), ← PrimeSpectrum.comap_comp_apply, ← PrimeSpectrum.comap_comp_apply] congr 2 - exact (PresheafedSpace.stalkMap_germ f.1 ⊤ ⟨x, trivial⟩).symm + exact (PresheafedSpace.stalkMap_germ f.1 ⊤ x trivial).symm · intro r rw [LocallyRingedSpace.comp_val_c_app, ← Category.assoc] erw [Y.toΓSpecSheafedSpace_app_spec, f.1.c.naturality] @@ -403,14 +393,13 @@ theorem adjunction_counit_app' {R : CommRingCatᵒᵖ} : theorem adjunction_counit_app {R : CommRingCatᵒᵖ} : ΓSpec.adjunction.counit.app R = (Scheme.ΓSpecIso (unop R)).inv.op := rfl --- This is not a simp lemma to respect the abstraction -theorem adjunction_unit_app {X : Scheme} : - ΓSpec.adjunction.unit.app X = locallyRingedSpaceAdjunction.unit.app X.1 := rfl +/-- The canonical map `X ⟶ Spec Γ(X, ⊤)`. This is the unit of the `Γ-Spec` adjunction. -/ +def _root_.AlgebraicGeometry.Scheme.toSpecΓ (X : Scheme.{u}) : X ⟶ Spec Γ(X, ⊤) := + ΓSpec.adjunction.unit.app X -@[reassoc (attr := simp)] -theorem adjunction_unit_naturality {X Y : Scheme.{u}} (f : X ⟶ Y) : - f ≫ ΓSpec.adjunction.unit.app Y = ΓSpec.adjunction.unit.app X ≫ Spec.map (f.app ⊤) := - ΓSpec.adjunction.unit.naturality f +@[simp] +theorem adjunction_unit_app {X : Scheme} : + ΓSpec.adjunction.unit.app X = X.toSpecΓ := rfl instance isIso_locallyRingedSpaceAdjunction_counit : IsIso.{u + 1, u + 1} locallyRingedSpaceAdjunction.counit := @@ -422,56 +411,76 @@ instance isIso_adjunction_counit : IsIso ΓSpec.adjunction.counit := by rw [adjunction_counit_app] infer_instance +end ΓSpec + +theorem Scheme.toSpecΓ_val_base (X : Scheme.{u}) (x) : + (Scheme.toSpecΓ X).1.base x = + (Spec.map (X.presheaf.germ ⊤ x trivial)).1.base (LocalRing.closedPoint _) := rfl + +@[reassoc (attr := simp)] +theorem Scheme.toSpecΓ_naturality {X Y : Scheme.{u}} (f : X ⟶ Y) : + f ≫ Y.toSpecΓ = X.toSpecΓ ≫ Spec.map (f.app ⊤) := + ΓSpec.adjunction.unit.naturality f + @[simp] -theorem adjunction_unit_app_app_top (X : Scheme.{u}) : - (ΓSpec.adjunction.unit.app X).app ⊤ = (Scheme.ΓSpecIso Γ(X, ⊤)).hom := by +theorem Scheme.toSpecΓ_app_top (X : Scheme.{u}) : + X.toSpecΓ.app ⊤ = (Scheme.ΓSpecIso Γ(X, ⊤)).hom := by have := ΓSpec.adjunction.left_triangle_components X dsimp at this rw [← IsIso.eq_comp_inv] at this - simp only [adjunction_counit_app, Functor.id_obj, Functor.comp_obj, Functor.rightOp_obj, + simp only [ΓSpec.adjunction_counit_app, Functor.id_obj, Functor.comp_obj, Functor.rightOp_obj, Scheme.Γ_obj, Category.id_comp] at this rw [← Quiver.Hom.op_inj.eq_iff, this, ← op_inv, IsIso.Iso.inv_inv] @[simp] theorem SpecMap_ΓSpecIso_hom (R : CommRingCat.{u}) : - Spec.map ((Scheme.ΓSpecIso R).hom) = adjunction.unit.app (Spec R) := by + Spec.map ((Scheme.ΓSpecIso R).hom) = (Spec R).toSpecΓ := by have := ΓSpec.adjunction.right_triangle_components (op R) dsimp at this rwa [← IsIso.eq_comp_inv, Category.id_comp, ← Spec.map_inv, IsIso.Iso.inv_inv, eq_comm] at this -lemma adjunction_unit_map_basicOpen (X : Scheme.{u}) (r : Γ(X, ⊤)) : - (ΓSpec.adjunction.unit.app X ⁻¹ᵁ (PrimeSpectrum.basicOpen r)) = X.basicOpen r := by - rw [← basicOpen_eq_of_affine] - erw [Scheme.preimage_basicOpen] +lemma Scheme.toSpecΓ_preimage_basicOpen (X : Scheme.{u}) (r : Γ(X, ⊤)) : + X.toSpecΓ ⁻¹ᵁ (PrimeSpectrum.basicOpen r) = X.basicOpen r := by + rw [← basicOpen_eq_of_affine, Scheme.preimage_basicOpen] congr - rw [ΓSpec.adjunction_unit_app_app_top] + rw [Scheme.toSpecΓ_app_top] exact Iso.inv_hom_id_apply _ _ -theorem toOpen_unit_app_val_c_app {X : Scheme.{u}} (U) : - StructureSheaf.toOpen _ _ ≫ (ΓSpec.adjunction.unit.app X).val.c.app U = +-- Warning: this LHS of this lemma breaks the structure-sheaf abstraction. +@[reassoc (attr := simp)] +theorem toOpen_toSpecΓ_app {X : Scheme.{u}} (U) : + StructureSheaf.toOpen _ _ ≫ X.toSpecΓ.app U = X.presheaf.map (homOfLE (by exact le_top)).op := by rw [← StructureSheaf.toOpen_res _ _ _ (homOfLE le_top), Category.assoc, - NatTrans.naturality _ (homOfLE (le_top (a := U.unop))).op] + NatTrans.naturality _ (homOfLE (le_top (a := U))).op] show (ΓSpec.adjunction.counit.app (Scheme.Γ.rightOp.obj X)).unop ≫ (Scheme.Γ.rightOp.map (ΓSpec.adjunction.unit.app X)).unop ≫ _ = _ rw [← Category.assoc, ← unop_comp, ΓSpec.adjunction.left_triangle_components] dsimp exact Category.id_comp _ --- Warning: this LHS of this lemma breaks the structure-sheaf abstraction. -@[reassoc (attr := simp)] -theorem toOpen_unit_app_val_c_app' {X : Scheme.{u}} (U : Opens (PrimeSpectrum Γ(X, ⊤))) : - toOpen Γ(X, ⊤) U ≫ (adjunction.unit.app X).app U = - X.presheaf.map (homOfLE (by exact le_top)).op := - ΓSpec.toOpen_unit_app_val_c_app (op U) +lemma ΓSpecIso_inv_ΓSpec_adjunction_homEquiv {X : Scheme.{u}} {B : CommRingCat} (φ : B ⟶ Γ(X, ⊤)) : + (Scheme.ΓSpecIso B).inv ≫ ((ΓSpec.adjunction.homEquiv X (op B)) φ.op).app ⊤ = φ := by + simp only [Adjunction.homEquiv_apply, Scheme.Spec_map, Opens.map_top, Scheme.comp_app] + simp -end ΓSpec +lemma ΓSpec_adjunction_homEquiv_eq {X : Scheme.{u}} {B : CommRingCat} (φ : B ⟶ Γ(X, ⊤)) : + (((ΓSpec.adjunction.homEquiv X (op B)) φ.op).app ⊤) = (Scheme.ΓSpecIso B).hom ≫ φ := by + simp_rw [← ΓSpecIso_inv_ΓSpec_adjunction_homEquiv φ] + simp theorem ΓSpecIso_obj_hom {X : Scheme.{u}} (U : X.Opens) : (Scheme.ΓSpecIso Γ(X, U)).hom = (Spec.map U.topIso.inv).app ⊤ ≫ - (ΓSpec.adjunction.unit.app U).app ⊤ ≫ U.topIso.hom := by - rw [ΓSpec.adjunction_unit_app_app_top] -- why can't simp find this - simp + U.toScheme.toSpecΓ.app ⊤ ≫ U.topIso.hom := by simp + +@[deprecated (since := "2024-07-24")] +alias ΓSpec.adjunction_unit_naturality := Scheme.toSpecΓ_naturality +@[deprecated (since := "2024-07-24")] +alias ΓSpec.adjunction_unit_naturality_assoc := Scheme.toSpecΓ_naturality_assoc +@[deprecated (since := "2024-07-24")] +alias ΓSpec.adjunction_unit_app_app_top := Scheme.toSpecΓ_app_top +@[deprecated (since := "2024-07-24")] +alias ΓSpec.adjunction_unit_map_basicOpen := Scheme.toSpecΓ_preimage_basicOpen /-! Immediate consequences of the adjunction. -/ diff --git a/Mathlib/AlgebraicGeometry/Gluing.lean b/Mathlib/AlgebraicGeometry/Gluing.lean index 2abed533825f0..a2543e35ee753 100644 --- a/Mathlib/AlgebraicGeometry/Gluing.lean +++ b/Mathlib/AlgebraicGeometry/Gluing.lean @@ -239,7 +239,7 @@ theorem isOpen_iff (U : Set D.glued.carrier) : IsOpen U ↔ ∀ i, IsOpen ((D.ι rw [TopCat.GlueData.isOpen_iff] apply forall_congr' intro i - erw [← Set.preimage_comp, ← ι_isoCarrier_inv] + rw [← Set.preimage_comp, ← ι_isoCarrier_inv] rfl /-- The open cover of the glued space given by the glue data. -/ diff --git a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean index 6233014ed00a7..d4c07982358ac 100644 --- a/Mathlib/AlgebraicGeometry/Modules/Tilde.lean +++ b/Mathlib/AlgebraicGeometry/Modules/Tilde.lean @@ -1,13 +1,15 @@ /- Copyright (c) 2024 Weihong Xu. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Weihong Xu +Authors: Kevin Buzzard, Johan Commelin, Amelia Livingston, Sophie Morel, Jujian Zhang, Weihong Xu -/ import Mathlib.Algebra.Module.LocalizedModule import Mathlib.AlgebraicGeometry.StructureSheaf import Mathlib.AlgebraicGeometry.Modules.Sheaf import Mathlib.Algebra.Category.ModuleCat.Sheaf +import Mathlib.Algebra.Category.ModuleCat.FilteredColimits +import Mathlib.CategoryTheory.Limits.ConcreteCategory.WithAlgebraicStructures /-! @@ -18,9 +20,15 @@ such that `M^~(U)` is the set of dependent functions that are locally fractions. ## Main definitions -* `ModuleCat.tildeInAddCommGrp` : `M^~` as a sheaf of abelian groups. +* `ModuleCat.tildeInType` : `M^~` as a sheaf of types groups. * `ModuleCat.tilde` : `M^~` as a sheaf of `𝒪_{Spec R}`-modules. +## Technical note + +To get the `R`-module structure on the stalks on `M^~`, we had to define +`ModuleCat.tildeInModuleCat`, which is `M^~` seen as sheaf of `R`-modules. We get it by +applying a forgetful functor to `ModuleCat.tilde M`. + -/ universe u @@ -138,37 +146,112 @@ instance (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : AddCommGroup (M.tildeInType.1.obj U) := inferInstanceAs <| AddCommGroup (Tilde.sectionsSubmodule M U) +noncomputable instance (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : + Module ((Spec (.of R)).ringCatSheaf.1.obj U) (M.tildeInType.1.obj U) := + inferInstanceAs <| Module _ (Tilde.sectionsSubmodule M U) + /-- -`M^~` as a presheaf of abelian groups over `Spec R` +`M^~` as a sheaf of `𝒪_{Spec R}`-modules -/ -def preTildeInAddCommGrp : Presheaf AddCommGrp (PrimeSpectrum.Top R) where - obj U := .of ((M.tildeInType).1.obj U) - map {U V} i := - { toFun := M.tildeInType.1.map i - map_zero' := rfl - map_add' := fun x y => rfl} +noncomputable def tilde : (Spec (CommRingCat.of R)).Modules where + val := + { obj := fun U ↦ ModuleCat.of _ (M.tildeInType.val.obj U) + map := fun {U V} i ↦ + { toFun := M.tildeInType.val.map i + map_smul' := by intros; rfl + map_add' := by intros; rfl } } + isSheaf := (TopCat.Presheaf.isSheaf_iff_isSheaf_comp (forget AddCommGrp) _ ).2 + M.tildeInType.2 /-- -`M^~` as a sheaf of abelian groups over `Spec R` +This is `M^~` as a sheaf of `R`-modules. -/ -def tildeInAddCommGrp : Sheaf AddCommGrp (PrimeSpectrum.Top R) := - ⟨M.preTildeInAddCommGrp, - TopCat.Presheaf.isSheaf_iff_isSheaf_comp (forget AddCommGrp) _ |>.mpr - (TopCat.Presheaf.isSheaf_of_iso (NatIso.ofComponents (fun _ => Iso.refl _) fun _ => rfl) - M.tildeInType.2)⟩ +noncomputable def tildeInModuleCat : + TopCat.Presheaf (ModuleCat R) (PrimeSpectrum.Top R) := + (PresheafOfModules.forgetToPresheafModuleCat (op ⊤) <| + Limits.initialOpOfTerminal Limits.isTerminalTop).obj (tilde M).1 ⋙ + ModuleCat.restrictScalars (StructureSheaf.globalSectionsIso R).hom -noncomputable instance (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : - Module ((Spec (.of R)).ringCatSheaf.1.obj U) (M.tildeInAddCommGrp.1.obj U) := - inferInstanceAs <| Module _ (Tilde.sectionsSubmodule M U) +namespace Tilde + +@[simp] +theorem res_apply (U V : Opens (PrimeSpectrum.Top R)) (i : V ⟶ U) + (s : (tildeInModuleCat M).obj (op U)) (x : V) : + ((tildeInModuleCat M).map i.op s).1 x = (s.1 (i x) : _) := + rfl + +lemma smul_section_apply (r : R) (U : Opens (PrimeSpectrum.Top R)) + (s : (tildeInModuleCat M).1.obj (op U)) (x : U) : + (r • s).1 x = r • (s.1 x) := rfl + +lemma smul_stalk_no_nonzero_divisor {x : PrimeSpectrum R} + (r : x.asIdeal.primeCompl) (st : (tildeInModuleCat M).stalk x) (hst : r.1 • st = 0) : + st = 0 := by + refine Limits.Concrete.colimit_no_zero_smul_divisor + _ _ _ ⟨op ⟨PrimeSpectrum.basicOpen r.1, r.2⟩, fun U i s hs ↦ Subtype.eq <| funext fun pt ↦ ?_⟩ + _ hst + apply LocalizedModule.eq_zero_of_smul_eq_zero _ (i.unop pt).2 _ + (congr_fun (Subtype.ext_iff.1 hs) pt) /-- -`M^~` as a sheaf of `𝒪_{Spec R}`-modules +If `U` is an open subset of `Spec R`, this is the morphism of `R`-modules from `M` to +`M^~(U)`. -/ -noncomputable def tilde : (Spec (CommRingCat.of R)).Modules where - val := - { presheaf := M.tildeInAddCommGrp.1 - module := inferInstance - map_smul := fun _ _ _ => rfl } - isSheaf := M.tildeInAddCommGrp.2 +def toOpen (U : Opens (PrimeSpectrum.Top R)) : + ModuleCat.of R M ⟶ (tildeInModuleCat M).1.obj (op U) where + toFun f := + ⟨fun x ↦ LocalizedModule.mkLinearMap _ _ f, fun x ↦ + ⟨U, x.2, 𝟙 _, f, 1, fun y ↦ ⟨(Ideal.ne_top_iff_one _).1 y.1.2.1, by simp⟩⟩⟩ + map_add' f g := Subtype.eq <| funext fun x ↦ LinearMap.map_add _ _ _ + map_smul' r m := by + simp only [isLocallyFraction_pred, LocalizedModule.mkLinearMap_apply, LinearMapClass.map_smul, + RingHom.id_apply] + rfl + +@[simp] +theorem toOpen_res (U V : Opens (PrimeSpectrum.Top R)) (i : V ⟶ U) : + toOpen M U ≫ (tildeInModuleCat M).map i.op = toOpen M V := + rfl + +/-- +If `x` is a point of `Spec R`, this is the morphism of `R`-modules from `M` to the stalk of +`M^~` at `x`. +-/ +noncomputable def toStalk (x : PrimeSpectrum.Top R) : + ModuleCat.of R M ⟶ TopCat.Presheaf.stalk (tildeInModuleCat M) x := + (toOpen M ⊤ ≫ TopCat.Presheaf.germ (tildeInModuleCat M) ⊤ x (by trivial)) + +open LocalizedModule TopCat.Presheaf in +lemma isUnit_toStalk (x : PrimeSpectrum.Top R) (r : x.asIdeal.primeCompl) : + IsUnit ((algebraMap R (Module.End R ((tildeInModuleCat M).stalk x))) r) := by + rw [Module.End_isUnit_iff] + refine ⟨LinearMap.ker_eq_bot.1 <| eq_bot_iff.2 fun st (h : r.1 • st = 0) ↦ + smul_stalk_no_nonzero_divisor M r st h, fun st ↦ ?_⟩ + obtain ⟨U, mem, s, rfl⟩ := germ_exist (F := M.tildeInModuleCat) x st + let O := U ⊓ (PrimeSpectrum.basicOpen r) + refine ⟨germ M.tildeInModuleCat O x ⟨mem, r.2⟩ + ⟨fun q ↦ (Localization.mk 1 ⟨r, q.2.2⟩ : Localization.AtPrime q.1.asIdeal) • s.1 + ⟨q.1, q.2.1⟩, fun q ↦ ?_⟩, by + simpa only [Module.algebraMap_end_apply, ← map_smul] using + germ_ext (W := O) (hxW := ⟨mem, r.2⟩) (iWU := 𝟙 _) (iWV := homOfLE inf_le_left) _ <| + Subtype.eq <| funext fun y ↦ smul_eq_iff_of_mem (S := y.1.1.primeCompl) r _ _ _ |>.2 rfl⟩ + obtain ⟨V, mem_V, iV, num, den, hV⟩ := s.2 ⟨q.1, q.2.1⟩ + refine ⟨V ⊓ O, ⟨mem_V, q.2⟩, homOfLE inf_le_right, num, r * den, fun y ↦ ?_⟩ + obtain ⟨h1, h2⟩ := hV ⟨y, y.2.1⟩ + refine ⟨y.1.asIdeal.primeCompl.mul_mem y.2.2.2 h1, ?_⟩ + simp only [Opens.coe_inf, isLocallyFraction_pred, mkLinearMap_apply, + smul_eq_iff_of_mem (S := y.1.1.primeCompl) (hr := h1), mk_smul_mk, one_smul, mul_one] at h2 ⊢ + simpa only [h2, mk_smul_mk, one_smul, smul'_mk, mk_eq] using ⟨1, by simp only [one_smul]; rfl⟩ + +/-- +The morphism of `R`-modules from the localization of `M` at the prime ideal corresponding to `x` +to the stalk of `M^~` at `x`. +-/ +noncomputable def localizationToStalk (x : PrimeSpectrum.Top R) : + ModuleCat.of R (LocalizedModule x.asIdeal.primeCompl M) ⟶ + (TopCat.Presheaf.stalk (tildeInModuleCat M) x) := + LocalizedModule.lift _ (toStalk M x) <| isUnit_toStalk M x + +end Tilde end ModuleCat diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean index 9cf21c35955ab..c990b0ee818d7 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Affine.lean @@ -122,8 +122,7 @@ lemma isAffine_of_isAffineOpen_basicOpen (s : Set Γ(X, ⊤)) simp only [← basicOpen_eq_of_affine] exact (isAffineOpen_top (Scheme.Spec.obj (op _))).basicOpen _ · rw [PrimeSpectrum.iSup_basicOpen_eq_top_iff, Subtype.range_coe_subtype, Set.setOf_mem_eq, hs] - · show IsAffineOpen (ΓSpec.adjunction.unit.app X ⁻¹ᵁ PrimeSpectrum.basicOpen i.1) - rw [ΓSpec.adjunction_unit_map_basicOpen] + · rw [Scheme.toSpecΓ_preimage_basicOpen] exact hs₂ _ i.2 · simp only [Functor.comp_obj, Functor.rightOp_obj, Scheme.Γ_obj, Scheme.Spec_obj, id_eq, eq_mpr_eq_cast, Functor.id_obj, Opens.map_top, morphismRestrict_app] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean index 7d7bc17702e37..9b5b16f7d5f16 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Basic.lean @@ -326,7 +326,7 @@ theorem respectsIso_mk {P : AffineTargetMorphismProperty} (h₂ : ∀ {X Y Z} (e : Y ≅ Z) (f : X ⟶ Y) [h : IsAffine Y], P f → @P _ _ (f ≫ e.hom) (isAffine_of_isIso e.inv)) : P.toProperty.RespectsIso := by - constructor + apply MorphismProperty.RespectsIso.mk · rintro X Y Z e f ⟨a, h⟩; exact ⟨a, h₁ e f h⟩ · rintro X Y Z e f ⟨a, h⟩; exact ⟨isAffine_of_isIso e.inv, h₂ e f h⟩ @@ -398,7 +398,7 @@ theorem of_targetAffineLocally_of_isPullback instance (P : AffineTargetMorphismProperty) [P.toProperty.RespectsIso] : (targetAffineLocally P).RespectsIso := by - constructor + apply MorphismProperty.RespectsIso.mk · introv H U rw [morphismRestrict_comp, P.cancel_left_of_respectsIso] exact H U diff --git a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean index 4eedb17248903..e0f201805fa3b 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/ClosedImmersion.lean @@ -84,7 +84,7 @@ instance comp {X Y Z : Scheme} (f : X ⟶ Y) (g : Y ⟶ Z) [IsClosedImmersion f] /-- Composition with an isomorphism preserves closed immersions. -/ instance respectsIso : MorphismProperty.RespectsIso @IsClosedImmersion := by - constructor <;> intro X Y Z e f hf <;> infer_instance + apply MorphismProperty.RespectsIso.mk <;> intro X Y Z e f hf <;> infer_instance /-- Given two commutative rings `R S : CommRingCat` and a surjective morphism `f : R ⟶ S`, the induced scheme morphism `specObj S ⟶ specObj R` is a diff --git a/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean b/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean index 91b9cb9c05db1..878d9b451bd27 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/Constructors.lean @@ -251,12 +251,12 @@ variable {P : ∀ {R S : Type u} [CommRing R] [CommRing S], (R →+* S) → Prop /-- If `P` respects isos, then `stalkwise P` respects isos. -/ lemma stalkwise_respectsIso (hP : RingHom.RespectsIso P) : (stalkwise P).RespectsIso where - precomp {X Y Z} e f hf := by + precomp {X Y Z} e (he : IsIso e) f hf := by simp only [stalkwise, Scheme.comp_coeBase, TopCat.coe_comp, Function.comp_apply] intro x rw [Scheme.stalkMap_comp] - exact (RingHom.RespectsIso.cancel_right_isIso hP _ _).mpr <| hf (e.hom.val.base x) - postcomp {X Y Z} e f hf := by + exact (RingHom.RespectsIso.cancel_right_isIso hP _ _).mpr <| hf (e.val.base x) + postcomp {X Y Z} e (he : IsIso e) f hf := by simp only [stalkwise, Scheme.comp_coeBase, TopCat.coe_comp, Function.comp_apply] intro x rw [Scheme.stalkMap_comp] diff --git a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean index 8c02123e45620..3fc310d18e207 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/OpenImmersion.lean @@ -56,7 +56,8 @@ instance : IsLocalAtTarget (stalkwise (fun f ↦ Function.Bijective f)) := by rw [RingHom.toMorphismProperty_respectsIso_iff] convert (inferInstanceAs (MorphismProperty.isomorphisms CommRingCat).RespectsIso) ext - exact (ConcreteCategory.isIso_iff_bijective _).symm + -- Regression in #17583: have to specify C explicitly below. + exact (ConcreteCategory.isIso_iff_bijective (C := CommRingCat) _).symm instance isOpenImmersion_isLocalAtTarget : IsLocalAtTarget @IsOpenImmersion := isOpenImmersion_eq_inf ▸ inferInstance diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean index 211a07cc5edf0..cf3a6124cc51f 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiCompact.lean @@ -198,7 +198,15 @@ theorem exists_pow_mul_eq_zero_of_res_basicOpen_eq_zero_of_isAffineOpen (X : Sch {U : X.Opens} (hU : IsAffineOpen U) (x f : Γ(X, U)) (H : x |_ X.basicOpen f = 0) : ∃ n : ℕ, f ^ n * x = 0 := by rw [← map_zero (X.presheaf.map (homOfLE <| X.basicOpen_le f : X.basicOpen f ⟶ U).op)] at H - obtain ⟨⟨_, n, rfl⟩, e⟩ := (hU.isLocalization_basicOpen f).exists_of_eq H + #adaptation_note + /-- + Prior to nightly-2024-09-29, we could use dot notation here: + `(hU.isLocalization_basicOpen f).exists_of_eq H` + This is no longer possible; + likely changing the signature of `IsLocalization.Away.exists_of_eq` is in order. + -/ + obtain ⟨n, e⟩ := + @IsLocalization.Away.exists_of_eq _ _ _ _ _ _ (hU.isLocalization_basicOpen f) _ _ H exact ⟨n, by simpa [mul_comm x] using e⟩ /-- If `x : Γ(X, U)` is zero on `D(f)` for some `f : Γ(X, U)`, and `U` is quasi-compact, then diff --git a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean index 83373737cbce2..e9ffc71cd889f 100644 --- a/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean +++ b/Mathlib/AlgebraicGeometry/Morphisms/QuasiSeparated.lean @@ -247,7 +247,7 @@ theorem exists_eq_pow_mul_of_isCompact_of_isQuasiSeparated (X : Scheme.{u}) (U : use 0, f refine @Subsingleton.elim _ (CommRingCat.subsingleton_of_isTerminal (X.sheaf.isTerminalOfEqEmpty ?_)) _ _ - erw [eq_bot_iff] + rw [eq_bot_iff] exact X.basicOpen_le f · -- Given `f : 𝒪(S ∪ U), x : 𝒪(X_f)`, we need to show that `f ^ n * x` is the restriction of -- some `y : 𝒪(S ∪ U)` for some `n : ℕ`. @@ -275,13 +275,13 @@ theorem exists_eq_pow_mul_of_isCompact_of_isQuasiSeparated (X : Scheme.{u}) (U : have hs₁ : ∀ i : s, i.1.1 ≤ S := by intro i; change (i : X.Opens) ≤ S refine le_trans ?_ (inf_le_left (b := U.1)) - erw [hs] + rw [hs] -- Porting note: have to add argument explicitly exact @le_iSup X.Opens s _ (fun (i : s) => (i : X.Opens)) i have hs₂ : ∀ i : s, i.1.1 ≤ U.1 := by intro i; change (i : X.Opens) ≤ U refine le_trans ?_ (inf_le_right (a := S)) - erw [hs] + rw [hs] -- Porting note: have to add argument explicitly exact @le_iSup X.Opens s _ (fun (i : s) => (i : X.Opens)) i -- On each affine open in the intersection, we have `f ^ (n + n₂) * y₁ = f ^ (n + n₁) * y₂` @@ -297,7 +297,7 @@ theorem exists_eq_pow_mul_of_isCompact_of_isQuasiSeparated (X : Scheme.{u}) (U : X.presheaf.map (homOfLE <| inf_le_right).op (X.presheaf.map (homOfLE le_sup_right).op f ^ (Finset.univ.sup n + n₁) * y₂) := by fapply X.sheaf.eq_of_locally_eq' fun i : s => i.1.1 - · refine fun i => homOfLE ?_; erw [hs] + · refine fun i => homOfLE ?_; rw [hs] -- Porting note: have to add argument explicitly exact @le_iSup X.Opens s _ (fun (i : s) => (i : X.Opens)) i · exact le_of_eq hs @@ -353,7 +353,7 @@ theorem isIso_ΓSpec_adjunction_unit_app_basicOpen {X : Scheme} [CompactSpace X] [QuasiSeparatedSpace X] (f : X.presheaf.obj (op ⊤)) : IsIso ((ΓSpec.adjunction.unit.app X).val.c.app (op (PrimeSpectrum.basicOpen f))) := by refine @IsIso.of_isIso_comp_right _ _ _ _ _ _ (X.presheaf.map - (eqToHom (ΓSpec.adjunction_unit_map_basicOpen _ _).symm).op) _ ?_ + (eqToHom (Scheme.toSpecΓ_preimage_basicOpen _ _).symm).op) _ ?_ rw [ConcreteCategory.isIso_iff_bijective, CommRingCat.forget_map] apply (config := { allowSynthFailures := true }) IsLocalization.bijective · exact StructureSheaf.IsLocalization.to_basicOpen _ _ @@ -361,8 +361,6 @@ theorem isIso_ΓSpec_adjunction_unit_app_basicOpen {X : Scheme} [CompactSpace X] · exact isCompact_univ · exact isQuasiSeparated_univ · rw [← CommRingCat.comp_eq_ring_hom_comp] - simp [RingHom.algebraMap_toAlgebra] - rw [ΓSpec.toOpen_unit_app_val_c_app'_assoc, ← Functor.map_comp] - rfl + simp [RingHom.algebraMap_toAlgebra, ← Functor.map_comp] end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/OpenImmersion.lean b/Mathlib/AlgebraicGeometry/OpenImmersion.lean index c65f7aa086fbc..70d24f7442e9b 100644 --- a/Mathlib/AlgebraicGeometry/OpenImmersion.lean +++ b/Mathlib/AlgebraicGeometry/OpenImmersion.lean @@ -105,6 +105,12 @@ lemma preimage_image_eq (U : X.Opens) : f ⁻¹ᵁ f ''ᵁ U = U := by apply Opens.ext simp [Set.preimage_image_eq _ f.openEmbedding.inj] +lemma image_le_image_iff (f : X ⟶ Y) [IsOpenImmersion f] (U U' : X.Opens) : + f ''ᵁ U ≤ f ''ᵁ U' ↔ U ≤ U' := by + refine ⟨fun h ↦ ?_, image_le_image_of_le f⟩ + rw [← preimage_image_eq f U, ← preimage_image_eq f U'] + apply preimage_le_preimage_of_le f h + lemma image_preimage_eq_opensRange_inter (U : Y.Opens) : f ''ᵁ f ⁻¹ᵁ U = f.opensRange ⊓ U := by apply Opens.ext simp [Set.image_preimage_eq_range_inter] @@ -431,7 +437,7 @@ instance pullback_fst_of_right : IsOpenImmersion (pullback.fst g f) := by rw [← pullbackSymmetry_hom_comp_snd] -- Porting note: was just `infer_instance`, it is a bit weird that no explicit class instance is -- provided but still class inference fail to find this - exact LocallyRingedSpace.IsOpenImmersion.comp (H := inferInstance) _ + exact LocallyRingedSpace.IsOpenImmersion.comp (H := inferInstance) _ _ instance pullback_to_base [IsOpenImmersion g] : IsOpenImmersion (limit.π (cospan f g) WalkingCospan.one) := by @@ -439,14 +445,14 @@ instance pullback_to_base [IsOpenImmersion g] : change IsOpenImmersion (_ ≫ f) -- Porting note: was just `infer_instance`, it is a bit weird that no explicit class instance is -- provided but still class inference fail to find this - exact LocallyRingedSpace.IsOpenImmersion.comp (H := inferInstance) _ + exact LocallyRingedSpace.IsOpenImmersion.comp (H := inferInstance) _ _ instance forgetToTopPreservesOfLeft : PreservesLimit (cospan f g) Scheme.forgetToTop := by delta Scheme.forgetToTop - apply @Limits.compPreservesLimit (K := cospan f g) (F := forget) + refine @Limits.compPreservesLimit _ _ _ _ _ _ (K := cospan f g) _ _ (F := forget) (G := LocallyRingedSpace.forgetToTop) ?_ ?_ · infer_instance - apply @preservesLimitOfIsoDiagram (F := _) _ _ _ _ _ _ (diagramIsoCospan.{u} _).symm ?_ + refine @preservesLimitOfIsoDiagram _ _ _ _ _ _ _ _ _ (diagramIsoCospan.{u} _).symm ?_ dsimp [LocallyRingedSpace.forgetToTop] infer_instance diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean index 34df4b8d2c4b9..f3fa7a4fbdf4a 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Basic.lean @@ -3,14 +3,14 @@ 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.PrimeSpectrum -import Mathlib.Topology.Irreducible -import Mathlib.Topology.Sets.Closeds +import Mathlib.RingTheory.KrullDimension.Basic +import Mathlib.Topology.KrullDimension import Mathlib.Topology.Sober import Mathlib.RingTheory.Ideal.MinimalPrime import Mathlib.RingTheory.Ideal.Over import Mathlib.RingTheory.Localization.Away.Basic import Mathlib.RingTheory.LocalRing.ResidueField.Defs +import Mathlib.RingTheory.LocalRing.RingHom.Basic /-! # The Zariski topology on the prime spectrum of a commutative (semi)ring @@ -207,21 +207,14 @@ section Comap 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) ⁻¹' - zeroLocus s = - zeroLocus (f '' s) := by - ext x - simp only [mem_zeroLocus, Set.image_subset_iff, Set.mem_preimage, mem_zeroLocus, Ideal.coe_comap] - -/-- The function between prime spectra of commutative (semi)rings induced by a ring homomorphism. -This function is continuous. -/ +/-- The continuous function between prime spectra of commutative (semi)rings induced by a ring +homomorphism. -/ def comap (f : R →+* S) : C(PrimeSpectrum S, PrimeSpectrum R) where - toFun y := ⟨Ideal.comap f y.asIdeal, inferInstance⟩ + toFun := f.specComap continuous_toFun := by simp only [continuous_iff_isClosed, isClosed_iff_zeroLocus] rintro _ ⟨s, rfl⟩ - exact ⟨_, preimage_comap_zeroLocus_aux f s⟩ + exact ⟨_, preimage_specComap_zeroLocus_aux f s⟩ variable (f : R →+* S) @@ -244,12 +237,10 @@ theorem comap_comp_apply (f : R →+* S) (g : S →+* S') (x : PrimeSpectrum S') @[simp] theorem preimage_comap_zeroLocus (s : Set R) : comap f ⁻¹' zeroLocus s = zeroLocus (f '' s) := - preimage_comap_zeroLocus_aux f s + preimage_specComap_zeroLocus_aux f s theorem comap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective f) : - Function.Injective (comap f) := fun x y h => - PrimeSpectrum.ext (Ideal.comap_injective_of_surjective f hf - (congr_arg PrimeSpectrum.asIdeal h : (comap f x).asIdeal = (comap f y).asIdeal)) + Function.Injective (comap f) := fun _ _ h => specComap_injective_of_surjective _ hf h variable (S) @@ -266,29 +257,16 @@ theorem localization_comap_inducing [Algebra R S] (M : Submonoid R) [IsLocalizat exact ⟨_, rfl⟩ theorem localization_comap_injective [Algebra R S] (M : Submonoid R) [IsLocalization M S] : - Function.Injective (comap (algebraMap R S)) := by - intro p q h - replace h := congr_arg (fun x : PrimeSpectrum R => Ideal.map (algebraMap R S) x.asIdeal) h - dsimp only [comap, ContinuousMap.coe_mk] at h - rw [IsLocalization.map_comap M S, IsLocalization.map_comap M S] at h - ext1 - exact h + Function.Injective (comap (algebraMap R S)) := + fun _ _ h => localization_specComap_injective S M h theorem localization_comap_embedding [Algebra R S] (M : Submonoid R) [IsLocalization M S] : Embedding (comap (algebraMap R S)) := ⟨localization_comap_inducing S M, localization_comap_injective S M⟩ theorem localization_comap_range [Algebra R S] (M : Submonoid R) [IsLocalization M S] : - Set.range (comap (algebraMap R S)) = { p | Disjoint (M : Set R) p.asIdeal } := by - ext x - constructor - · simp_rw [disjoint_iff_inf_le] - rintro ⟨p, rfl⟩ x ⟨hx₁, hx₂⟩ - exact (p.2.1 : ¬_) (p.asIdeal.eq_top_of_isUnit_mem hx₂ (IsLocalization.map_units S ⟨x, hx₁⟩)) - · intro h - use ⟨x.asIdeal.map (algebraMap R S), IsLocalization.isPrime_of_isPrime_disjoint M S _ x.2 h⟩ - ext1 - exact IsLocalization.comap_map_of_isPrime_disjoint M S _ x.2 h + Set.range (comap (algebraMap R S)) = { p | Disjoint (M : Set R) p.asIdeal } := + localization_specComap_range .. open Function RingHom @@ -336,28 +314,12 @@ theorem comap_singleton_isClosed_of_isIntegral (f : R →+* S) (hf : f.IsIntegra (Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' f hf x.asIdeal) 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] - refine fun p => ⟨?_, fun h_I_p => ?_⟩ - · rintro ⟨p, hp, rfl⟩ a ha - exact hp ha - · have hp : ker f ≤ p.asIdeal := (Ideal.comap_mono bot_le).trans h_I_p - refine ⟨⟨p.asIdeal.map f, Ideal.map_isPrime_of_surjective hf hp⟩, fun x hx => ?_, ?_⟩ - · obtain ⟨x', rfl⟩ := hf x - exact Ideal.mem_map_of_mem f (h_I_p hx) - · ext x - rw [comap_asIdeal, Ideal.mem_comap, Ideal.mem_map_iff_of_surjective f hf] - refine ⟨?_, fun hx => ⟨x, hx, rfl⟩⟩ - rintro ⟨x', hx', heq⟩ - rw [← sub_sub_cancel x' x] - refine p.asIdeal.sub_mem hx' (hp ?_) - rwa [mem_ker, map_sub, sub_eq_zero] + comap f '' zeroLocus I = zeroLocus (I.comap f) := + image_specComap_zeroLocus_eq_zeroLocus_comap _ f hf I theorem range_comap_of_surjective (hf : Surjective f) : - Set.range (comap f) = zeroLocus (ker f) := by - rw [← Set.image_univ] - convert image_comap_zeroLocus_eq_zeroLocus_comap _ _ hf _ - rw [zeroLocus_bot] + Set.range (comap f) = zeroLocus (ker f) := + range_specComap_of_surjective _ f hf theorem isClosed_range_comap_of_surjective (hf : Surjective f) : IsClosed (Set.range (comap f)) := by @@ -693,3 +655,12 @@ theorem PrimeSpectrum.comap_residue (T : Type u) [CommRing T] [LocalRing T] exact Ideal.mk_ker end LocalRing + +section KrullDimension + +theorem PrimeSpectrum.topologicalKrullDim_eq_ringKrullDim [CommRing R] : + topologicalKrullDim (PrimeSpectrum R) = ringKrullDim R := + Order.krullDim_orderDual.symm.trans <| Order.krullDim_eq_of_orderIso + (PrimeSpectrum.pointsEquivIrreducibleCloseds R).symm + +end KrullDimension diff --git a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean index 1e92a49a98670..7522a16f45dbe 100644 --- a/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean +++ b/Mathlib/AlgebraicGeometry/PrimeSpectrum/Noetherian.lean @@ -19,9 +19,8 @@ open TopologicalSpace variable (R : Type u) [CommRing R] [IsNoetherianRing R] -instance : NoetherianSpace (PrimeSpectrum R) := by - apply ((noetherianSpace_TFAE <| PrimeSpectrum R).out 0 1).mpr - exact (closedsEmbedding R).dual.wellFounded IsWellFounded.wf +instance : NoetherianSpace (PrimeSpectrum R) := + ((noetherianSpace_TFAE <| PrimeSpectrum R).out 0 1).mpr (closedsEmbedding R).dual.wellFoundedLT lemma _root_.minimalPrimes.finite_of_isNoetherianRing : (minimalPrimes R).Finite := minimalPrimes.equivIrreducibleComponents R diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean index 139077e8ace13..567d07ccb66d0 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/Scheme.lean @@ -402,7 +402,7 @@ theorem carrier.smul_mem (c x : A) (hx : x ∈ carrier f_deg q) : c • x ∈ ca HomogeneousLocalization.val_mul, HomogeneousLocalization.val_mk, HomogeneousLocalization.val_mk] · simp_rw [mul_pow]; rw [Localization.mk_mul] - · congr; erw [← pow_add, Nat.add_sub_of_le h] + · congr; rw [← pow_add, Nat.add_sub_of_le h] · apply Ideal.mul_mem_left (α := A⁰_ f) _ _ (hx _) rw [(_ : m • n = _)] · mem_tac @@ -594,9 +594,9 @@ def awayToSection (f) : CommRingCat.of (A⁰_ f) ⟶ (structureSheaf 𝒜).1.obj map_zero' := by ext; simp only [map_zero, HomogeneousLocalization.val_zero, Proj.zero_apply] map_one' := by ext; simp only [map_one, HomogeneousLocalization.val_one, Proj.one_apply] -lemma awayToSection_germ (f x) : - awayToSection 𝒜 f ≫ (structureSheaf 𝒜).presheaf.germ x = - (HomogeneousLocalization.mapId 𝒜 (Submonoid.powers_le.mpr x.2)) ≫ +lemma awayToSection_germ (f x hx) : + awayToSection 𝒜 f ≫ (structureSheaf 𝒜).presheaf.germ _ x hx = + (HomogeneousLocalization.mapId 𝒜 (Submonoid.powers_le.mpr hx)) ≫ (Proj.stalkIso' 𝒜 x).toCommRingCatIso.inv := by ext z apply (Proj.stalkIso' 𝒜 x).eq_symm_apply.mpr @@ -685,9 +685,9 @@ lemma toStalk_stalkMap_toSpec (f) (x) : StructureSheaf.toStalk _ _ ≫ (toSpec 𝒜 f).stalkMap x = awayToΓ 𝒜 f ≫ (Proj| pbo f).presheaf.Γgerm x := by rw [StructureSheaf.toStalk, Category.assoc] - simp_rw [CommRingCat.coe_of] - erw [PresheafedSpace.stalkMap_germ'] - rw [toOpen_toSpec_val_c_app_assoc, Presheaf.germ_res] + simp_rw [CommRingCat.coe_of, ← Spec.locallyRingedSpaceObj_presheaf'] + rw [LocallyRingedSpace.stalkMap_germ (toSpec 𝒜 f), + toOpen_toSpec_val_c_app_assoc, Presheaf.germ_res] rfl /-- @@ -806,7 +806,7 @@ If `f ∈ A` is a homogeneous element of positive degree, then the projective sp -/ def projIsoSpec (f) {m} (f_deg : f ∈ 𝒜 m) (hm : 0 < m) : (Proj| pbo f) ≅ (Spec (A⁰_ f)) := - @asIso (f := toSpec 𝒜 f) (isIso_toSpec 𝒜 f f_deg hm) + @asIso _ _ _ _ (f := toSpec 𝒜 f) (isIso_toSpec 𝒜 f f_deg hm) /-- This is the scheme `Proj(A)` for any `ℕ`-graded ring `A`. diff --git a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean index 747ed8efb6ca5..e6fe728b2d042 100644 --- a/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/ProjectiveSpectrum/StructureSheaf.lean @@ -260,22 +260,19 @@ def stalkToFiberRingHom (x : ProjectiveSpectrum.top 𝒜) : openToLocalization 𝒜 ((OpenNhds.inclusion _).obj U.unop) x U.unop.2 } } @[simp] -theorem germ_comp_stalkToFiberRingHom (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : U) : - (Proj.structureSheaf 𝒜).presheaf.germ x ≫ stalkToFiberRingHom 𝒜 x = - openToLocalization 𝒜 U x x.2 := +theorem germ_comp_stalkToFiberRingHom + (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : ProjectiveSpectrum.top 𝒜) (hx : x ∈ U) : + (Proj.structureSheaf 𝒜).presheaf.germ U x hx ≫ stalkToFiberRingHom 𝒜 x = + openToLocalization 𝒜 U x hx := Limits.colimit.ι_desc _ _ @[simp] -theorem stalkToFiberRingHom_germ' (U : Opens (ProjectiveSpectrum.top 𝒜)) +theorem stalkToFiberRingHom_germ (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : ProjectiveSpectrum.top 𝒜) (hx : x ∈ U) (s : (Proj.structureSheaf 𝒜).1.obj (op U)) : - stalkToFiberRingHom 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ ⟨x, hx⟩ s) = (s.1 ⟨x, hx⟩ : _) := - RingHom.ext_iff.1 (germ_comp_stalkToFiberRingHom 𝒜 U ⟨x, hx⟩ : _) s + stalkToFiberRingHom 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ _ x hx s) = s.1 ⟨x, hx⟩ := + RingHom.ext_iff.1 (germ_comp_stalkToFiberRingHom 𝒜 U x hx) s -@[simp] -theorem stalkToFiberRingHom_germ (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : U) - (s : (Proj.structureSheaf 𝒜).1.obj (op U)) : - stalkToFiberRingHom 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ x s) = s.1 x := - stalkToFiberRingHom_germ' 𝒜 U _ _ _ +@[deprecated (since := "2024-07-30")] alias stalkToFiberRingHom_germ' := stalkToFiberRingHom_germ theorem mem_basicOpen_den (x : ProjectiveSpectrum.top 𝒜) (f : HomogeneousLocalization.NumDenSameDeg 𝒜 x.asHomogeneousIdeal.toIdeal.primeCompl) : @@ -300,7 +297,7 @@ stalk at `x` obtained by `sectionInBasicOpen`. This is the inverse of `stalkToFi -/ def homogeneousLocalizationToStalk (x : ProjectiveSpectrum.top 𝒜) (y : at x) : (Proj.structureSheaf 𝒜).presheaf.stalk x := Quotient.liftOn' y (fun f => - (Proj.structureSheaf 𝒜).presheaf.germ ⟨x, mem_basicOpen_den _ x f⟩ (sectionInBasicOpen _ x f)) + (Proj.structureSheaf 𝒜).presheaf.germ _ x (mem_basicOpen_den _ x f) (sectionInBasicOpen _ x f)) fun f g (e : f.embedding = g.embedding) ↦ by simp only [HomogeneousLocalization.NumDenSameDeg.embedding, Localization.mk_eq_mk', IsLocalization.mk'_eq_iff_eq, @@ -325,7 +322,7 @@ lemma homogeneousLocalizationToStalk_stalkToFiberRingHom (x z) : obtain ⟨U, hxU, s, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z obtain ⟨V, hxV, i, n, a, b, h, e⟩ := s.2 ⟨x, hxU⟩ simp only at e - rw [stalkToFiberRingHom_germ', homogeneousLocalizationToStalk, e ⟨x, hxV⟩, Quotient.liftOn'_mk''] + rw [stalkToFiberRingHom_germ, homogeneousLocalizationToStalk, e ⟨x, hxV⟩, Quotient.liftOn'_mk''] refine Presheaf.germ_ext _ V hxV (by exact homOfLE <| fun _ h' ↦ h ⟨_, h'⟩) i ?_ apply Subtype.ext ext ⟨t, ht⟩ @@ -337,7 +334,7 @@ lemma stalkToFiberRingHom_homogeneousLocalizationToStalk (x z) : stalkToFiberRingHom 𝒜 x (homogeneousLocalizationToStalk 𝒜 x z) = z := by obtain ⟨z, rfl⟩ := Quotient.surjective_Quotient_mk'' z rw [homogeneousLocalizationToStalk, Quotient.liftOn'_mk'', - stalkToFiberRingHom_germ', sectionInBasicOpen] + stalkToFiberRingHom_germ, sectionInBasicOpen] /-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x` and homogeneous localization at `x` for any point `x` in `Proj`. -/ @@ -349,21 +346,17 @@ def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) : right_inv := stalkToFiberRingHom_homogeneousLocalizationToStalk 𝒜 x @[simp] -theorem Proj.stalkIso'_germ' (U : Opens (ProjectiveSpectrum.top 𝒜)) +theorem Proj.stalkIso'_germ (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : ProjectiveSpectrum.top 𝒜) (hx : x ∈ U) (s : (Proj.structureSheaf 𝒜).1.obj (op U)) : - Proj.stalkIso' 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ ⟨x, hx⟩ s) = (s.1 ⟨x, hx⟩ : _) := - stalkToFiberRingHom_germ' 𝒜 U x hx s + Proj.stalkIso' 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ _ x hx s) = s.1 ⟨x, hx⟩ := + stalkToFiberRingHom_germ 𝒜 U x hx s -@[simp] -theorem Proj.stalkIso'_germ (U : Opens (ProjectiveSpectrum.top 𝒜)) (x : U) - (s : (Proj.structureSheaf 𝒜).1.obj (op U)) : - Proj.stalkIso' 𝒜 x ((Proj.structureSheaf 𝒜).presheaf.germ x s) = s.1 x := - stalkToFiberRingHom_germ' 𝒜 U x x.2 s +@[deprecated (since := "2024-07-30")] alias Proj.stalkIso'_germ' := Proj.stalkIso'_germ @[simp] theorem Proj.stalkIso'_symm_mk (x) (f) : - (Proj.stalkIso' 𝒜 x).symm (.mk f) = (Proj.structureSheaf 𝒜).presheaf.germ - ⟨x, mem_basicOpen_den _ x f⟩ (sectionInBasicOpen _ x f) := rfl + (Proj.stalkIso' 𝒜 x).symm (.mk f) = (Proj.structureSheaf 𝒜).presheaf.germ _ + x (mem_basicOpen_den _ x f) (sectionInBasicOpen _ x f) := rfl /-- `Proj` of a graded ring as a `LocallyRingedSpace`-/ def Proj.toLocallyRingedSpace : LocallyRingedSpace := diff --git a/Mathlib/AlgebraicGeometry/Properties.lean b/Mathlib/AlgebraicGeometry/Properties.lean index 70e632782f02a..626ba8ab0aecf 100644 --- a/Mathlib/AlgebraicGeometry/Properties.lean +++ b/Mathlib/AlgebraicGeometry/Properties.lean @@ -56,9 +56,9 @@ theorem isReduced_of_isReduced_stalk [∀ x : X, _root_.IsReduced (X.presheaf.st IsReduced X := by refine ⟨fun U => ⟨fun s hs => ?_⟩⟩ apply Presheaf.section_ext X.sheaf U s 0 - intro x + intro x hx rw [RingHom.map_zero] - change X.presheaf.germ x s = 0 + change X.presheaf.germ U x hx s = 0 exact (hs.map _).eq_zero instance isReduced_stalk_of_isReduced [IsReduced X] (x : X) : @@ -66,12 +66,11 @@ instance isReduced_stalk_of_isReduced [IsReduced X] (x : X) : constructor rintro g ⟨n, e⟩ obtain ⟨U, hxU, s, rfl⟩ := X.presheaf.germ_exist x g - rw [← map_pow, ← map_zero (X.presheaf.germ ⟨x, hxU⟩)] at e + rw [← map_pow, ← map_zero (X.presheaf.germ _ x hxU)] at e obtain ⟨V, hxV, iU, iV, e'⟩ := X.presheaf.germ_eq x hxU hxU _ 0 e rw [map_pow, map_zero] at e' replace e' := (IsNilpotent.mk _ _ e').eq_zero (R := Γ(X, V)) - erw [← ConcreteCategory.congr_hom (X.presheaf.germ_res iU ⟨x, hxV⟩) s] - rw [comp_apply, e', map_zero] + rw [← X.presheaf.germ_res iU x hxV, comp_apply, e', map_zero] theorem isReduced_of_isOpenImmersion {X Y : Scheme} (f : X ⟶ Y) [H : IsOpenImmersion f] [IsReduced Y] : IsReduced X := by @@ -114,8 +113,7 @@ theorem reduce_to_affine_global (P : ∀ {X : Scheme} (_ : X.Opens), Prop) (h₁ : ∀ (X : Scheme) (U : X.Opens), (∀ x : U, ∃ (V : _) (_ : x.1 ∈ V) (_ : V ⟶ U), P V) → P U) (h₂ : ∀ (X Y) (f : X ⟶ Y) [hf : IsOpenImmersion f], - ∃ (U : Set X) (V : Set Y) (hU : U = ⊤) (hV : V = Set.range f.1.base), - P ⟨U, hU.symm ▸ isOpen_univ⟩ → P ⟨V, hV.symm ▸ hf.base_open.isOpen_range⟩) + ∃ (U : X.Opens) (V : Y.Opens), U = ⊤ ∧ V = f.opensRange ∧ (P U → P V)) (h₃ : ∀ R : CommRingCat, P (X := Spec R) ⊤) : P U := by apply h₁ intro x @@ -141,28 +139,26 @@ theorem reduce_to_affine_nbhd (P : ∀ (X : Scheme) (_ : X), Prop) theorem eq_zero_of_basicOpen_eq_bot {X : Scheme} [hX : IsReduced X] {U : X.Opens} (s : Γ(X, U)) (hs : X.basicOpen s = ⊥) : s = 0 := by apply TopCat.Presheaf.section_ext X.sheaf U - intro x + intro x hx rw [RingHom.map_zero] + show X.presheaf.germ U x hx s = 0 induction U using reduce_to_affine_global generalizing hX with - | h₁ X U hx => - obtain ⟨V, hx, i, H⟩ := hx x + | h₁ X U H => + obtain ⟨V, hx, i, H⟩ := H ⟨x, hx⟩ specialize H (X.presheaf.map i.op s) - erw [Scheme.basicOpen_res] at H - rw [hs] at H - specialize H (inf_bot_eq _) ⟨x, hx⟩ - erw [TopCat.Presheaf.germ_res_apply] at H + rw [Scheme.basicOpen_res, hs] at H + specialize H (inf_bot_eq _) x hx + rw [TopCat.Presheaf.germ_res_apply] at H exact H | h₂ X Y f => - have e : f.val.base ⁻¹' Set.range ↑f.val.base = Set.univ := by - rw [← Set.image_univ, Set.preimage_image_eq _ ‹IsOpenImmersion f›.base_open.inj] - refine ⟨_, _, e, rfl, ?_⟩ - rintro H hX s hs ⟨_, x, rfl⟩ + refine ⟨f ⁻¹ᵁ f.opensRange, f.opensRange, by ext1; simp, rfl, ?_⟩ + rintro H hX s hs _ ⟨x, rfl⟩ haveI := isReduced_of_isOpenImmersion f - specialize H (f.app _ s) _ ⟨x, by rw [Opens.mem_mk, e]; trivial⟩ + specialize H (f.app _ s) _ x ⟨x, rfl⟩ · rw [← Scheme.preimage_basicOpen, hs]; ext1; simp [Opens.map] - · erw [← PresheafedSpace.stalkMap_germ_apply f.1 ⟨_, _⟩ ⟨x, _⟩] at H + · rw [← Scheme.stalkMap_germ_apply f ⟨_, _⟩ x] at H apply_fun inv <| f.stalkMap x at H - erw [CategoryTheory.IsIso.hom_inv_id_apply, map_zero] at H + rw [CategoryTheory.IsIso.hom_inv_id_apply, map_zero] at H exact H | h₃ R => rw [basicOpen_eq_of_affine', PrimeSpectrum.basicOpen_eq_bot_iff] at hs @@ -239,13 +235,11 @@ theorem isIntegral_of_irreducibleSpace_of_isReduced [IsReduced X] [H : Irreducib refine ⟨fun {a b} e => ?_⟩ simp_rw [← basicOpen_eq_bot_iff, ← Opens.not_nonempty_iff_eq_bot] by_contra! h - obtain ⟨_, ⟨x, hx₁, rfl⟩, ⟨x, hx₂, e'⟩⟩ := + obtain ⟨x, ⟨hxU, hx₁⟩, _, hx₂⟩ := nonempty_preirreducible_inter (X.basicOpen a).2 (X.basicOpen b).2 h.1 h.2 - replace e' := Subtype.eq e' - subst e' - replace e := congr_arg (X.presheaf.germ x) e + replace e := congr_arg (X.presheaf.germ U x hxU) e rw [RingHom.map_mul, RingHom.map_zero] at e - refine zero_ne_one' (X.presheaf.stalk x.1) (isUnit_zero_iff.1 ?_) + refine zero_ne_one' (X.presheaf.stalk x) (isUnit_zero_iff.1 ?_) convert hx₁.mul hx₂ exact e.symm exact NoZeroDivisors.to_isDomain _ diff --git a/Mathlib/AlgebraicGeometry/Pullbacks.lean b/Mathlib/AlgebraicGeometry/Pullbacks.lean index 36ae5c042ab8c..1b43cf9c18bfd 100644 --- a/Mathlib/AlgebraicGeometry/Pullbacks.lean +++ b/Mathlib/AlgebraicGeometry/Pullbacks.lean @@ -453,8 +453,8 @@ instance isAffine_of_isAffine_isAffine_isAffine {X Y Z : Scheme} IsAffine (pullback f g) := isAffine_of_isIso (pullback.map f g (Spec.map (Γ.map f.op)) (Spec.map (Γ.map g.op)) - (ΓSpec.adjunction.unit.app X) (ΓSpec.adjunction.unit.app Y) (ΓSpec.adjunction.unit.app Z) - (ΓSpec.adjunction.unit.naturality f) (ΓSpec.adjunction.unit.naturality g) ≫ + X.toSpecΓ Y.toSpecΓ Z.toSpecΓ + (Scheme.toSpecΓ_naturality f) (Scheme.toSpecΓ_naturality g) ≫ (PreservesPullback.iso Scheme.Spec _ _).inv) /-- Given an open cover `{ Xᵢ }` of `X`, then `X ×[Z] Y` is covered by `Xᵢ ×[Z] Y`. -/ @@ -507,7 +507,7 @@ def openCoverOfBase' (𝒰 : OpenCover Z) (f : X ⟶ Z) (g : Y ⟶ Z) : OpenCove pasteVertIsPullback rfl (pullbackIsPullback g (𝒰.map i)) (pullbackIsPullback (pullback.snd g (𝒰.map i)) (pullback.snd f (𝒰.map i))) refine - @openCoverOfIsIso + @openCoverOfIsIso _ _ (f := (pullbackSymmetry _ _).hom ≫ (limit.isoLimitCone ⟨_, this⟩).inv ≫ pullback.map _ _ _ _ (𝟙 _) (𝟙 _) (𝟙 _) ?_ ?_) inferInstance · simp [← pullback.condition] @@ -583,7 +583,8 @@ the morphism `Spec (S ⊗[R] T) ⟶ Spec T` obtained by applying `Spec.map` to t -/ @[reassoc (attr := simp)] lemma pullbackSpecIso_inv_snd : - (pullbackSpecIso R S T).inv ≫ pullback.snd _ _ = Spec.map (ofHom (toRingHom includeRight)) := + (pullbackSpecIso R S T).inv ≫ pullback.snd _ _ = + Spec.map (ofHom (R := T) (S := S ⊗[R] T) (toRingHom includeRight)) := limit.isoLimitCone_inv_π _ _ /-- The composition of the isomorphism `pullbackSepcIso R S T` (from the pullback of diff --git a/Mathlib/AlgebraicGeometry/ResidueField.lean b/Mathlib/AlgebraicGeometry/ResidueField.lean new file mode 100644 index 0000000000000..1649e31a1b5e3 --- /dev/null +++ b/Mathlib/AlgebraicGeometry/ResidueField.lean @@ -0,0 +1,187 @@ +/- +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.Geometry.RingedSpace.LocallyRingedSpace.ResidueField +import Mathlib.AlgebraicGeometry.Stalk + +/-! + +# Residue fields of points + +## Main definitions + +The following are in the `AlgebraicGeometry.Scheme` namespace: + +- `AlgebraicGeometry.Scheme.residueField`: The residue field of the stalk at `x`. +- `AlgebraicGeometry.Scheme.evaluation`: For open subsets `U` of `X` containing `x`, + the evaluation map from sections over `U` to the residue field at `x`. +- `AlgebraicGeometry.Scheme.Hom.residueFieldMap`: A morphism of schemes induce a homomorphism of + residue fields. +- `AlgebraicGeometry.Scheme.fromSpecResidueField`: The canonical map `Spec κ(x) ⟶ X`. + +-/ + +universe u + +open CategoryTheory TopologicalSpace Opposite + +noncomputable section + +namespace AlgebraicGeometry.Scheme + +variable (X : Scheme.{u}) {U : X.Opens} + +/-- The residue field of `X` at a point `x` is the residue field of the stalk of `X` +at `x`. -/ +def residueField (x : X) : CommRingCat := + CommRingCat.of <| LocalRing.ResidueField (X.presheaf.stalk x) + +instance (x : X) : Field (X.residueField x) := + inferInstanceAs <| Field (LocalRing.ResidueField (X.presheaf.stalk x)) + +/-- The residue map from the stalk to the residue field. -/ +def residue (X : Scheme.{u}) (x) : X.presheaf.stalk x ⟶ X.residueField x := + LocalRing.residue _ + +lemma residue_surjective (X : Scheme.{u}) (x) : Function.Surjective (X.residue x) := + Ideal.Quotient.mk_surjective + +instance (X : Scheme.{u}) (x) : Epi (X.residue x) := + ConcreteCategory.epi_of_surjective _ (X.residue_surjective x) + +/-- +If `U` is an open of `X` containing `x`, we have a canonical ring map from the sections +over `U` to the residue field of `x`. + +If we interpret sections over `U` as functions of `X` defined on `U`, then this ring map +corresponds to evaluation at `x`. +-/ +def evaluation (U : X.Opens) (x : X) (hx : x ∈ U) : Γ(X, U) ⟶ X.residueField x := + X.presheaf.germ U x hx ≫ X.residue _ + +@[reassoc] +lemma germ_residue (x hx) : X.presheaf.germ U x hx ≫ X.residue x = X.evaluation U x hx := rfl + +/-- The global evaluation map from `Γ(X, ⊤)` to the residue field at `x`. -/ +abbrev Γevaluation (x : X) : Γ(X, ⊤) ⟶ X.residueField x := + X.evaluation ⊤ x trivial + +@[simp] +lemma evaluation_eq_zero_iff_not_mem_basicOpen (x : X) (hx : x ∈ U) (f : Γ(X, U)) : + X.evaluation U x hx f = 0 ↔ x ∉ X.basicOpen f := + X.toLocallyRingedSpace.evaluation_eq_zero_iff_not_mem_basicOpen ⟨x, hx⟩ f + +lemma evaluation_ne_zero_iff_mem_basicOpen (x : X) (hx : x ∈ U) (f : Γ(X, U)) : + X.evaluation U x hx f ≠ 0 ↔ x ∈ X.basicOpen f := by + simp + +variable {X Y : Scheme.{u}} (f : X ⟶ Y) + + +-- TODO: This instance is found before #6045. +-- We need this strange instance for `residueFieldMap`, the type of `F` must be fixed +-- like this. The instance `IsLocalRingHom (f.stalkMap x)` already exists, but does not work for +-- `residueFieldMap`. +instance (x): IsLocalRingHom (F := Y.presheaf.stalk (f.val.base x) →+* X.presheaf.stalk x) + (f.stalkMap x) := + f.2 x + +/-- If `X ⟶ Y` is a morphism of locally ringed spaces and `x` a point of `X`, we obtain +a morphism of residue fields in the other direction. -/ +def Hom.residueFieldMap (f : X.Hom Y) (x : X) : + Y.residueField (f.val.base x) ⟶ X.residueField x := + LocalRing.ResidueField.map (f.stalkMap x) + +@[reassoc] +lemma residue_residueFieldMap (x : X) : + Y.residue (f.val.base x) ≫ f.residueFieldMap x = f.stalkMap x ≫ X.residue x := by + simp [Hom.residueFieldMap] + rfl + +@[simp] +lemma residueFieldMap_id (x : X) : + Hom.residueFieldMap (𝟙 X) x = 𝟙 (X.residueField x) := + LocallyRingedSpace.residueFieldMap_id _ + +@[simp] +lemma residueFieldMap_comp {Z : Scheme.{u}} (g : Y ⟶ Z) (x : X) : + (f ≫ g).residueFieldMap x = g.residueFieldMap (f.val.base x) ≫ f.residueFieldMap x := + LocallyRingedSpace.residueFieldMap_comp _ _ _ + +@[reassoc] +lemma evaluation_naturality {V : Opens Y} (x : X) (hx : f.val.base x ∈ V) : + Y.evaluation V (f.val.base x) hx ≫ f.residueFieldMap x = + f.app V ≫ X.evaluation (f ⁻¹ᵁ V) x hx := + LocallyRingedSpace.evaluation_naturality f ⟨x, hx⟩ + +lemma evaluation_naturality_apply {V : Opens Y} (x : X) (hx : f.val.base x ∈ V) (s) : + f.residueFieldMap x (Y.evaluation V (f.val.base x) hx s) = + X.evaluation (f ⁻¹ᵁ V) x hx (f.app V s) := + LocallyRingedSpace.evaluation_naturality_apply f ⟨x, hx⟩ s + +instance [IsOpenImmersion f] (x) : IsIso (f.residueFieldMap x) := + (LocalRing.ResidueField.mapEquiv + (asIso (f.stalkMap x)).commRingCatIsoToRingEquiv).toCommRingCatIso.isIso_hom + +section congr + +-- replace this def if hard to work with +/-- The isomorphism between residue fields of equal points. -/ +def residueFieldCongr {x y : X} (h : x = y) : + X.residueField x ≅ X.residueField y := + eqToIso (by subst h; rfl) + +@[simp] +lemma residueFieldCongr_refl {x : X} : + X.residueFieldCongr (refl x) = Iso.refl _ := rfl + +@[simp] +lemma residueFieldCongr_symm {x y : X} (e : x = y) : + (X.residueFieldCongr e).symm = X.residueFieldCongr e.symm := rfl + +@[simp] +lemma residueFieldCongr_inv {x y : X} (e : x = y) : + (X.residueFieldCongr e).inv = (X.residueFieldCongr e.symm).hom := rfl + +@[simp] +lemma residueFieldCongr_trans {x y z : X} (e : x = y) (e' : y = z) : + X.residueFieldCongr e ≪≫ X.residueFieldCongr e' = X.residueFieldCongr (e.trans e') := by + subst e e' + rfl + +@[reassoc (attr := simp)] +lemma residueFieldCongr_trans_hom (X : Scheme) {x y z : X} (e : x = y) (e' : y = z) : + (X.residueFieldCongr e).hom ≫ (X.residueFieldCongr e').hom = + (X.residueFieldCongr (e.trans e')).hom := by + subst e e' + rfl + +@[reassoc] +lemma residue_residueFieldCongr (X : Scheme) {x y : X} (h : x = y) : + X.residue x ≫ (X.residueFieldCongr h).hom = + (X.presheaf.stalkCongr (.of_eq h)).hom ≫ X.residue y := by + subst h + simp + +end congr + +section fromResidueField + +/-- The canonical map `Spec κ(x) ⟶ X`. -/ +def fromSpecResidueField (X : Scheme) (x : X) : + Spec (X.residueField x) ⟶ X := + Spec.map (CommRingCat.ofHom (X.residue x)) ≫ X.fromSpecStalk x + +@[reassoc (attr := simp)] +lemma residueFieldCongr_fromSpecResidueField {x y : X} (h : x = y) : + Spec.map (X.residueFieldCongr h).hom ≫ X.fromSpecResidueField _ = + X.fromSpecResidueField _ := by + subst h; simp + +end fromResidueField + +end Scheme + +end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Restrict.lean b/Mathlib/AlgebraicGeometry/Restrict.lean index 3c13ad4164037..d4c45b8f826f4 100644 --- a/Mathlib/AlgebraicGeometry/Restrict.lean +++ b/Mathlib/AlgebraicGeometry/Restrict.lean @@ -87,6 +87,10 @@ lemma range_ι : Set.range U.ι.val.base = U := lemma ι_image_top : U.ι ''ᵁ ⊤ = U := U.openEmbedding_obj_top +lemma ι_image_le (W : U.toScheme.Opens) : U.ι ''ᵁ W ≤ U := by + simp_rw [← U.ι_image_top] + exact U.ι.image_le_image_of_le le_top + @[simp] lemma ι_preimage_self : U.ι ⁻¹ᵁ U = ⊤ := Opens.inclusion'_map_eq_top _ @@ -121,22 +125,15 @@ def stalkIso {X : Scheme.{u}} (U : X.Opens) (x : U) : @[reassoc (attr := simp)] lemma germ_stalkIso_hom {X : Scheme.{u}} (U : X.Opens) - {V : U.toScheme.Opens} (x : V) : - U.toScheme.presheaf.germ x ≫ (U.stalkIso x.1).hom = - X.presheaf.germ ⟨x.1.1, show x.1.1 ∈ U.ι ''ᵁ V from ⟨x.1, x.2, rfl⟩⟩ := - PresheafedSpace.restrictStalkIso_hom_eq_germ _ U.openEmbedding _ _ _ - -@[reassoc (attr := simp)] -lemma germ_stalkIso_hom' {X : Scheme.{u}} (U : X.Opens) - {V : TopologicalSpace.Opens U} (x : U) (hx : x ∈ V) : - U.toScheme.presheaf.germ ⟨x, hx⟩ ≫ (U.stalkIso x).hom = - X.presheaf.germ ⟨x.1, show x.1 ∈ U.ι ''ᵁ V from ⟨x, hx, rfl⟩⟩ := + {V : U.toScheme.Opens} (x : U) (hx : x ∈ V) : + U.toScheme.presheaf.germ V x hx ≫ (U.stalkIso x).hom = + X.presheaf.germ (U.ι ''ᵁ V) x.1 ⟨x, hx, rfl⟩ := PresheafedSpace.restrictStalkIso_hom_eq_germ _ U.openEmbedding _ _ _ -@[simp, reassoc] +@[reassoc] lemma germ_stalkIso_inv {X : Scheme.{u}} (U : X.Opens) (V : U.toScheme.Opens) (x : U) - (hx : x ∈ V) : X.presheaf.germ ⟨x.val, show x.val ∈ U.ι ''ᵁ V from ⟨x, hx, rfl⟩⟩ ≫ - (U.stalkIso x).inv = U.toScheme.presheaf.germ ⟨x, hx⟩ := + (hx : x ∈ V) : X.presheaf.germ (U.ι ''ᵁ V) x ⟨x, hx, rfl⟩ ≫ + (U.stalkIso x).inv = U.toScheme.presheaf.germ V x hx := PresheafedSpace.restrictStalkIso_inv_eq_germ X.toPresheafedSpace U.openEmbedding V x hx end Scheme.Opens @@ -173,7 +170,7 @@ lemma Scheme.map_basicOpen' (r : Γ(U, ⊤)) : U.ι ''ᵁ (U.toScheme.basicOpen r) = X.basicOpen (X.presheaf.map (eqToHom U.openEmbedding_obj_top.symm).op r) := by refine (Scheme.image_basicOpen (X.ofRestrict U.openEmbedding) r).trans ?_ - erw [← Scheme.basicOpen_res_eq _ _ (eqToHom U.openEmbedding_obj_top).op] + rw [← Scheme.basicOpen_res_eq _ _ (eqToHom U.openEmbedding_obj_top).op] rw [← comp_apply, ← CategoryTheory.Functor.map_comp, ← op_comp, eqToHom_trans, eqToHom_refl, op_id, CategoryTheory.Functor.map_id] congr @@ -216,8 +213,10 @@ def Scheme.restrictFunctor : X.Opens ⥤ Over X where @[simp] lemma Scheme.restrictFunctor_obj_hom (U : X.Opens) : (X.restrictFunctor.obj U).hom = U.ι := rfl -@[simp] lemma Scheme.restrictFunctor_map_left {U V : X.Opens} (i : U ⟶ V) : - (X.restrictFunctor.map i).left = IsOpenImmersion.lift (V.ι) U.ι (by simpa using i.le) := rfl +/-- This is not a `simp` lemma, as `(X.restricFunctor.map i).left` is used as the `simp` +normal-form for the induced morphism `U.toScheme ⟶ V.toScheme`. -/ +lemma Scheme.restrictFunctor_map_left {U V : X.Opens} (i : U ⟶ V) : + (X.restrictFunctor.map i).left = IsOpenImmersion.lift (V.ι) U.ι (by simpa using i.le) := rfl -- Porting note: the `by ...` used to be automatically done by unification magic @[reassoc] @@ -258,7 +257,7 @@ def Scheme.restrictFunctorΓ : X.restrictFunctor.op ⋙ (Over.forget X).op ⋙ S (fun U => X.presheaf.mapIso ((eqToIso (unop U).openEmbedding_obj_top).symm.op : _)) (by intro U V i - dsimp [-Scheme.restrictFunctor_map_left] + dsimp rw [X.restrictFunctor_map_app, ← Functor.map_comp, ← Functor.map_comp] congr 1) @@ -508,13 +507,87 @@ def morphismRestrictStalkMap {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) (x) apply TopCat.Presheaf.stalk_hom_ext intro V hxV change ↑(f ⁻¹ᵁ U) at x - simp [Scheme.stalkMap_germ'_assoc, Scheme.Hom.appLE] + simp [Scheme.stalkMap_germ_assoc, Scheme.Hom.appLE] instance {X Y : Scheme.{u}} (f : X ⟶ Y) (U : Y.Opens) [IsOpenImmersion f] : IsOpenImmersion (f ∣_ U) := by delta morphismRestrict exact PresheafedSpace.IsOpenImmersion.comp _ _ +variable {X Y : Scheme.{u}} + +namespace Scheme.Hom + +/-- The restriction of a morphism `f : X ⟶ Y` to open sets on the source and target. -/ +def resLE (f : Hom X Y) (U : Y.Opens) (V : X.Opens) (e : V ≤ f ⁻¹ᵁ U) : V.toScheme ⟶ U.toScheme := + (X.restrictFunctor.map (homOfLE e)).left ≫ f ∣_ U + +variable (f : X ⟶ Y) {U U' : Y.Opens} {V V' : X.Opens} (e : V ≤ f ⁻¹ᵁ U) + +lemma resLE_eq_morphismRestrict : f.resLE U (f ⁻¹ᵁ U) le_rfl = f ∣_ U := by + simp [Scheme.Hom.resLE] + +lemma resLE_id (i : V ⟶ V') : resLE (𝟙 X) V' V i.le = (X.restrictFunctor.map i).left := by + simp only [resLE, id_val_base, morphismRestrict_id, Category.comp_id] + rfl + +@[reassoc (attr := simp)] +lemma resLE_comp_ι : f.resLE U V e ≫ U.ι = V.ι ≫ f := by + simp [resLE, restrictFunctor_map_ofRestrict_assoc] + +@[reassoc] +lemma resLE_comp_resLE {Z : Scheme.{u}} (g : Y ⟶ Z) {W : Z.Opens} (e') : + f.resLE U V e ≫ g.resLE W U e' = (f ≫ g).resLE W V + (e.trans ((Opens.map f.val.base).map (homOfLE e')).le) := by + simp [← cancel_mono W.ι] + +@[reassoc (attr := simp)] +lemma map_resLE (i : V' ⟶ V) : + (X.restrictFunctor.map i).left ≫ f.resLE U V e = f.resLE U V' (i.le.trans e) := by + simp_rw [← resLE_id, resLE_comp_resLE, Category.id_comp] + +@[reassoc (attr := simp)] +lemma resLE_map (i : U ⟶ U') : + f.resLE U V e ≫ (Y.restrictFunctor.map i).left = + f.resLE U' V (e.trans ((Opens.map f.1.base).map i).le) := by + simp_rw [← resLE_id, resLE_comp_resLE, Category.comp_id] + +lemma resLE_congr (e₁ : U = U') (e₂ : V = V') (P : MorphismProperty Scheme.{u}) : + P (f.resLE U V e) ↔ P (f.resLE U' V' (e₁ ▸ e₂ ▸ e)) := by + subst e₁; subst e₂; rfl + +lemma resLE_preimage (f : X ⟶ Y) {U : Y.Opens} {V : X.Opens} (e : V ≤ f ⁻¹ᵁ U) + (O : U.toScheme.Opens) : + f.resLE U V e ⁻¹ᵁ O = V.ι ⁻¹ᵁ (f ⁻¹ᵁ U.ι ''ᵁ O) := by + rw [← preimage_comp, ← resLE_comp_ι f e, preimage_comp, preimage_image_eq] + +lemma le_preimage_resLE_iff {U : Y.Opens} {V : X.Opens} (e : V ≤ f ⁻¹ᵁ U) + (O : U.toScheme.Opens) (W : V.toScheme.Opens) : + W ≤ (f.resLE U V e) ⁻¹ᵁ O ↔ V.ι ''ᵁ W ≤ f ⁻¹ᵁ U.ι ''ᵁ O := by + simp [resLE_preimage, ← image_le_image_iff V.ι, image_preimage_eq_opensRange_inter, V.ι_image_le] + +lemma resLE_appLE {U : Y.Opens} {V : X.Opens} (e : V ≤ f ⁻¹ᵁ U) + (O : U.toScheme.Opens) (W : V.toScheme.Opens) (e' : W ≤ resLE f U V e ⁻¹ᵁ O) : + (f.resLE U V e).appLE O W e' = + f.appLE (U.ι ''ᵁ O) (V.ι ''ᵁ W) ((le_preimage_resLE_iff f e O W).mp e') := by + simp only [Scheme.Hom.appLE, Scheme.Hom.resLE, Scheme.restrictFunctor_map_left, Opens.map_coe, + id_eq, Scheme.comp_app, morphismRestrict_app', Category.assoc, IsOpenImmersion.lift_app, + Scheme.Opens.ι_appIso, Scheme.Opens.ι_app, Scheme.Opens.toScheme_presheaf_map, Category.assoc] + rw [← X.presheaf.map_comp, ← X.presheaf.map_comp] + erw [Category.id_comp] + rw [← X.presheaf.map_comp] + rfl + +end Scheme.Hom + +/-- `f.resLE U V` induces `f.appLE U V` on global sections. -/ +noncomputable def arrowResLEAppIso (f : X ⟶ Y) (U : Y.Opens) (V : X.Opens) (e : V ≤ f ⁻¹ᵁ U) : + Arrow.mk ((f.resLE U V e).app ⊤) ≅ Arrow.mk (f.appLE U V e) := + Arrow.isoMk U.topIso V.topIso <| by + simp only [Opens.map_top, Arrow.mk_left, Arrow.mk_right, Functor.id_obj, Scheme.Opens.topIso_hom, + eqToHom_op, Arrow.mk_hom, Scheme.Hom.map_appLE] + rw [← Scheme.Hom.appLE_eq_app, Scheme.Hom.resLE_appLE, Scheme.Hom.appLE_map] + end MorphismRestrict /-- The restriction of an open cover to an open subset. -/ @@ -531,6 +604,6 @@ def Scheme.OpenCover.restrict {X : Scheme.{u}} (𝒰 : X.OpenCover) (U : Opens X rw [← cancel_mono U.ι] simp only [morphismRestrict_ι, pullbackCover_J, Equiv.refl_apply, pullbackCover_obj, pullbackCover_map, Category.assoc, pullback.condition] - erw [IsOpenImmersion.isoOfRangeEq_hom_fac_assoc] + rw [IsOpenImmersion.isoOfRangeEq_hom_fac_assoc] end AlgebraicGeometry diff --git a/Mathlib/AlgebraicGeometry/Scheme.lean b/Mathlib/AlgebraicGeometry/Scheme.lean index 083a5943ef221..7714e1f80579c 100644 --- a/Mathlib/AlgebraicGeometry/Scheme.lean +++ b/Mathlib/AlgebraicGeometry/Scheme.lean @@ -165,6 +165,10 @@ lemma preimage_iSup {ι} (U : ι → Opens Y) : f ⁻¹ᵁ iSup U = ⨆ i, f ⁻ lemma preimage_iSup_eq_top {ι} {U : ι → Opens Y} (hU : iSup U = ⊤) : ⨆ i, f ⁻¹ᵁ U i = ⊤ := f.preimage_iSup U ▸ hU ▸ rfl +lemma preimage_le_preimage_of_le {U U' : Y.Opens} (hUU' : U ≤ U') : + f ⁻¹ᵁ U ≤ f ⁻¹ᵁ U' := + fun _ ha ↦ hUU' ha + end Hom @[simp] @@ -446,22 +450,24 @@ variable (X : Scheme) {V U : X.Opens} (f g : Γ(X, U)) def basicOpen : X.Opens := X.toLocallyRingedSpace.toRingedSpace.basicOpen f +theorem mem_basicOpen (x : X) (hx : x ∈ U) : + x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ U x hx f) := + RingedSpace.mem_basicOpen _ _ _ _ + +/-- A variant of `mem_basicOpen` for bundled `x : U`. -/ @[simp] -theorem mem_basicOpen (x : U) : ↑x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ x f) := - RingedSpace.mem_basicOpen _ _ _ +theorem mem_basicOpen' (x : U) : ↑x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ U x x.2 f) := + RingedSpace.mem_basicOpen _ _ _ _ -theorem mem_basicOpen_top' {U : X.Opens} (f : Γ(X, U)) (x : X) : - x ∈ X.basicOpen f ↔ ∃ (m : x ∈ U), IsUnit (X.presheaf.germ (⟨x, m⟩ : U) f) := by - fconstructor - · rintro ⟨y, hy1, rfl⟩ - exact ⟨y.2, hy1⟩ - · rintro ⟨m, hm⟩ - exact ⟨⟨x, m⟩, hm, rfl⟩ +/-- A variant of `mem_basicOpen` without the `x ∈ U` assumption. -/ +theorem mem_basicOpen'' {U : X.Opens} (f : Γ(X, U)) (x : X) : + x ∈ X.basicOpen f ↔ ∃ (m : x ∈ U), IsUnit (X.presheaf.germ U x m f) := + Iff.rfl @[simp] theorem mem_basicOpen_top (f : Γ(X, ⊤)) (x : X) : - x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ (⟨x, trivial⟩ : (⊤ : Opens _)) f) := - RingedSpace.mem_basicOpen _ f ⟨x, trivial⟩ + x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ ⊤ x trivial f) := + RingedSpace.mem_top_basicOpen _ f x @[simp] theorem basicOpen_res (i : op U ⟶ op V) : X.basicOpen (X.presheaf.map i f) = V ⊓ X.basicOpen f := @@ -554,7 +560,7 @@ theorem basicOpen_eq_of_affine {R : CommRingCat} (f : R) : ext x simp only [SetLike.mem_coe, Scheme.mem_basicOpen_top, Opens.coe_top] suffices IsUnit (StructureSheaf.toStalk R x f) ↔ f ∉ PrimeSpectrum.asIdeal x by exact this - erw [← isUnit_map_iff (StructureSheaf.stalkToFiberRingHom R x), + rw [← isUnit_map_iff (StructureSheaf.stalkToFiberRingHom R x), StructureSheaf.stalkToFiberRingHom_toStalk] exact (IsLocalization.AtPrime.isUnit_to_map_iff (Localization.AtPrime (PrimeSpectrum.asIdeal x)) @@ -664,28 +670,17 @@ lemma stalkMap_inv_hom_apply (e : X ≅ Y) (x : X) (y) : (X.presheaf.stalkCongr (.of_eq (by simp))).hom y := DFunLike.congr_fun (stalkMap_inv_hom e x) y -@[reassoc] -lemma stalkMap_germ (U : Y.Opens) (x : f ⁻¹ᵁ U) : - Y.presheaf.germ ⟨f.val.base x.val, x.property⟩ ≫ f.stalkMap x = - f.app U ≫ X.presheaf.germ x := - PresheafedSpace.stalkMap_germ f.val U x - -lemma stalkMap_germ_apply (U : Y.Opens) (x : f ⁻¹ᵁ U) (y) : - f.stalkMap x.val (Y.presheaf.germ ⟨f.val.base x.val, x.property⟩ y) = - X.presheaf.germ x (f.val.c.app (op U) y) := - PresheafedSpace.stalkMap_germ_apply f.val U x y - @[reassoc (attr := simp)] -lemma stalkMap_germ' (U : Y.Opens) (x : X) (hx : f.val.base x ∈ U) : - Y.presheaf.germ ⟨f.val.base x, hx⟩ ≫ f.stalkMap x = - f.app U ≫ X.presheaf.germ (U := f⁻¹ᵁ U) ⟨x, hx⟩ := - PresheafedSpace.stalkMap_germ' f.val U x hx +lemma stalkMap_germ (U : Y.Opens) (x : X) (hx : f.val.base x ∈ U) : + Y.presheaf.germ U (f.val.base x) hx ≫ f.stalkMap x = + f.app U ≫ X.presheaf.germ (f ⁻¹ᵁ U) x hx := + PresheafedSpace.stalkMap_germ f.val U x hx @[simp] -lemma stalkMap_germ'_apply (U : Y.Opens) (x : X) (hx : f.val.base x ∈ U) (y) : - f.stalkMap x (Y.presheaf.germ ⟨f.val.base x, hx⟩ y) = - X.presheaf.germ (U := (Opens.map f.val.base).obj U) ⟨x, hx⟩ (f.val.c.app (op U) y) := - PresheafedSpace.stalkMap_germ_apply f.val U ⟨x, hx⟩ y +lemma stalkMap_germ_apply (U : Y.Opens) (x : X) (hx : f.val.base x ∈ U) (y) : + f.stalkMap x (Y.presheaf.germ _ (f.val.base x) hx y) = + X.presheaf.germ (f ⁻¹ᵁ U) x hx (f.app U y) := + PresheafedSpace.stalkMap_germ_apply f.val U x hx y end Scheme diff --git a/Mathlib/AlgebraicGeometry/Spec.lean b/Mathlib/AlgebraicGeometry/Spec.lean index 3a10a69127f49..1defa7db8f0e8 100644 --- a/Mathlib/AlgebraicGeometry/Spec.lean +++ b/Mathlib/AlgebraicGeometry/Spec.lean @@ -90,7 +90,7 @@ def Spec.sheafedSpaceObj (R : CommRingCat.{u}) : SheafedSpace CommRingCat where /-- The induced map of a ring homomorphism on the ring spectra, as a morphism of sheafed spaces. -/ -@[simps] +@[simps base c_app] def Spec.sheafedSpaceMap {R S : CommRingCat.{u}} (f : R ⟶ S) : Spec.sheafedSpaceObj S ⟶ Spec.sheafedSpaceObj R where base := Spec.topMap f @@ -196,9 +196,11 @@ lemma Spec.locallyRingedSpaceObj_presheaf_map' (R : Type u) [CommRing R] {U V} ( theorem stalkMap_toStalk {R S : CommRingCat.{u}} (f : R ⟶ S) (p : PrimeSpectrum S) : toStalk R (PrimeSpectrum.comap f p) ≫ (Spec.sheafedSpaceMap f).stalkMap p = f ≫ toStalk S p := by - erw [← toOpen_germ S ⊤ ⟨p, trivial⟩, ← toOpen_germ R ⊤ ⟨PrimeSpectrum.comap f p, trivial⟩, - Category.assoc, PresheafedSpace.stalkMap_germ (Spec.sheafedSpaceMap f) ⊤ ⟨p, trivial⟩, - Spec.sheafedSpaceMap_c_app, toOpen_comp_comap_assoc] + rw [← toOpen_germ S ⊤ p trivial, ← toOpen_germ R ⊤ (PrimeSpectrum.comap f p) trivial, + Category.assoc] + erw [PresheafedSpace.stalkMap_germ (Spec.sheafedSpaceMap f) ⊤ p trivial] + rw [Spec.sheafedSpaceMap_c_app] + erw [toOpen_comp_comap_assoc] rfl /-- Under the isomorphisms `stalkIso`, the map `stalkMap (Spec.sheafedSpaceMap f) p` corresponds @@ -236,6 +238,8 @@ def Spec.locallyRingedSpaceMap {R S : CommRingCat.{u}} (f : R ⟶ S) : #adaptation_note /-- nightly-2024-04-01 It's this `erw` that is blowing up. The implicit arguments differ significantly. -/ erw [← localRingHom_comp_stalkIso_apply] at ha + -- TODO: this instance was found automatically before #6045 + haveI : IsLocalRingHom (stalkIso (↑S) p).inv := isLocalRingHom_of_isIso _ replace ha := (isUnit_map_iff (stalkIso S p).inv _).mp ha -- Porting note: `f` had to be made explicit replace ha := IsLocalRingHom.map_nonunit @@ -322,16 +326,14 @@ This is shown to be the localization at `p` in `isLocalizedModule_toPushforwardS -/ def toPushforwardStalk : S ⟶ (Spec.topMap f _* (structureSheaf S).1).stalk p := StructureSheaf.toOpen S ⊤ ≫ - @TopCat.Presheaf.germ _ _ _ _ (Spec.topMap f _* (structureSheaf S).1) ⊤ ⟨p, trivial⟩ + @TopCat.Presheaf.germ _ _ _ _ (Spec.topMap f _* (structureSheaf S).1) ⊤ p trivial @[reassoc] theorem toPushforwardStalk_comp : f ≫ StructureSheaf.toPushforwardStalk f p = StructureSheaf.toStalk R p ≫ (TopCat.Presheaf.stalkFunctor _ _).map (Spec.sheafedSpaceMap f).c := by - rw [StructureSheaf.toStalk] - erw [Category.assoc] - rw [TopCat.Presheaf.stalkFunctor_map_germ] + rw [StructureSheaf.toStalk, Category.assoc, TopCat.Presheaf.stalkFunctor_map_germ] exact Spec_Γ_naturality_assoc f _ instance : Algebra R ((Spec.topMap f _* (structureSheaf S).1).stalk p) := @@ -364,9 +366,9 @@ theorem isLocalizedModule_toPushforwardStalkAlgHom_aux (y) : change PrimeSpectrum.basicOpen r ≤ U at hrU replace e := ((Spec.topMap (algebraMap R S) _* (structureSheaf S).1).germ_res_apply (homOfLE hrU) - ⟨p, hpr⟩ _).trans e + p hpr _).trans e set s' := (Spec.topMap (algebraMap R S) _* (structureSheaf S).1).map (homOfLE hrU).op s with h - replace e : ((Spec.topMap (algebraMap R S) _* (structureSheaf S).val).germ ⟨p, hpr⟩) s' = y := by + replace e : ((Spec.topMap (algebraMap R S) _* (structureSheaf S).val).germ _ p hpr) s' = y := by rw [h]; exact e clear_value s'; clear! U obtain ⟨⟨s, ⟨_, n, rfl⟩⟩, hsn⟩ := @@ -377,10 +379,10 @@ theorem isLocalizedModule_toPushforwardStalkAlgHom_aux (y) : comp_apply, comp_apply] iterate 2 erw [← (Spec.topMap (algebraMap R S) _* (structureSheaf S).1).germ_res_apply (homOfLE le_top) - ⟨p, hpr⟩] + p hpr] rw [← e] -- Porting note: without this `change`, Lean doesn't know how to rewrite `map_mul` - let f := TopCat.Presheaf.germ (Spec.topMap (algebraMap R S) _* (structureSheaf S).val) ⟨p, hpr⟩ + let f := TopCat.Presheaf.germ (Spec.topMap (algebraMap R S) _* (structureSheaf S).val) _ p hpr change f _ * f _ = f _ rw [← map_mul, mul_comm] dsimp only [Subtype.coe_mk] at hsn @@ -400,7 +402,7 @@ instance isLocalizedModule_toPushforwardStalkAlgHom : toPushforwardStalk] at hx -- Porting note: this `change` is manually rewriting `comp_apply` change _ = (TopCat.Presheaf.germ (Spec.topMap (algebraMap ↑R ↑S) _* (structureSheaf ↑S).val) - (⟨p, trivial⟩ : (⊤ : TopologicalSpace.Opens (PrimeSpectrum R))) (toOpen S ⊤ 0)) at hx + ⊤ p trivial (toOpen S ⊤ 0)) at hx rw [map_zero] at hx change (forget CommRingCat).map _ _ = (forget _).map _ _ at hx obtain ⟨U, hpU, i₁, i₂, e⟩ := TopCat.Presheaf.germ_eq _ _ _ _ _ _ hx diff --git a/Mathlib/AlgebraicGeometry/Stalk.lean b/Mathlib/AlgebraicGeometry/Stalk.lean index f1b9f8a1215c8..8865ed5e23d8f 100644 --- a/Mathlib/AlgebraicGeometry/Stalk.lean +++ b/Mathlib/AlgebraicGeometry/Stalk.lean @@ -24,7 +24,7 @@ neighborhood `U` of `x`. noncomputable def IsAffineOpen.fromSpecStalk {X : Scheme} {U : X.Opens} (hU : IsAffineOpen U) {x : X} (hxU : x ∈ U) : Spec (X.presheaf.stalk x) ⟶ X := - Spec.map (X.presheaf.germ ⟨x, hxU⟩) ≫ hU.fromSpec + Spec.map (X.presheaf.germ _ x hxU) ≫ hU.fromSpec /-- The morphism from `Spec(O_x)` to `X` given by `IsAffineOpen.fromSpec` does not depend on the affine @@ -38,12 +38,12 @@ theorem IsAffineOpen.fromSpecStalk_eq {X : Scheme} (x : X) {U V : X.Opens} transitivity fromSpecStalk h₁ h₂ · delta fromSpecStalk rw [← hU.map_fromSpec h₁ (homOfLE <| h₃.trans inf_le_left).op] - erw [← Scheme.Spec_map (X.presheaf.map _).op, ← Scheme.Spec_map (X.presheaf.germ ⟨x, h₂⟩).op] + erw [← Scheme.Spec_map (X.presheaf.map _).op, ← Scheme.Spec_map (X.presheaf.germ _ x h₂).op] rw [← Functor.map_comp_assoc, ← op_comp, TopCat.Presheaf.germ_res, Scheme.Spec_map, Quiver.Hom.unop_op] · delta fromSpecStalk rw [← hV.map_fromSpec h₁ (homOfLE <| h₃.trans inf_le_right).op] - erw [← Scheme.Spec_map (X.presheaf.map _).op, ← Scheme.Spec_map (X.presheaf.germ ⟨x, h₂⟩).op] + erw [← Scheme.Spec_map (X.presheaf.map _).op, ← Scheme.Spec_map (X.presheaf.germ _ x h₂).op] rw [← Functor.map_comp_assoc, ← op_comp, TopCat.Presheaf.germ_res, Scheme.Spec_map, Quiver.Hom.unop_op] diff --git a/Mathlib/AlgebraicGeometry/StructureSheaf.lean b/Mathlib/AlgebraicGeometry/StructureSheaf.lean index 6d18e0fcb5c9f..fcd5788d01906 100644 --- a/Mathlib/AlgebraicGeometry/StructureSheaf.lean +++ b/Mathlib/AlgebraicGeometry/StructureSheaf.lean @@ -174,7 +174,7 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : fconstructor · intro H; cases y.1.isPrime.mem_or_mem H <;> contradiction · simp only [add_mul, RingHom.map_add, Pi.add_apply, RingHom.map_mul] - erw [← wa, ← wb] + rw [← wa, ← wb] simp only [mul_assoc] congr 2 rw [mul_comm] @@ -187,7 +187,7 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : fconstructor · exact nm · simp only [RingHom.map_neg, Pi.neg_apply] - erw [← w] + rw [← w] simp only [neg_mul] mul_mem' := by intro a b ha hb x @@ -200,7 +200,7 @@ def sectionsSubring (U : (Opens (PrimeSpectrum.Top R))ᵒᵖ) : fconstructor · intro H; cases y.1.isPrime.mem_or_mem H <;> contradiction · simp only [Pi.mul_apply, RingHom.map_mul] - erw [← wa, ← wb] + rw [← wa, ← wb] simp only [mul_left_comm, mul_assoc, mul_comm] end StructureSheaf @@ -300,7 +300,8 @@ def const (f g : R) (U : Opens (PrimeSpectrum.Top R)) @[simp] theorem const_apply (f g : R) (U : Opens (PrimeSpectrum.Top R)) (hu : ∀ x ∈ U, g ∈ (x : PrimeSpectrum.Top R).asIdeal.primeCompl) (x : U) : - (const R f g U hu).1 x = IsLocalization.mk' _ f ⟨g, hu x x.2⟩ := + (const R f g U hu).1 x = + IsLocalization.mk' (Localization.AtPrime x.1.asIdeal) f ⟨g, hu x x.2⟩ := rfl theorem const_apply' (f g : R) (U : Opens (PrimeSpectrum.Top R)) @@ -402,30 +403,32 @@ theorem toOpen_eq_const (U : Opens (PrimeSpectrum.Top R)) (f : R) : /-- The canonical ring homomorphism interpreting an element of `R` as an element of the stalk of `structureSheaf R` at `x`. -/ def toStalk (x : PrimeSpectrum.Top R) : CommRingCat.of R ⟶ (structureSheaf R).presheaf.stalk x := - (toOpen R ⊤ ≫ (structureSheaf R).presheaf.germ ⟨x, by trivial⟩) + (toOpen R ⊤ ≫ (structureSheaf R).presheaf.germ _ x (by trivial)) @[simp] -theorem toOpen_germ (U : Opens (PrimeSpectrum.Top R)) (x : U) : - toOpen R U ≫ (structureSheaf R).presheaf.germ x = toStalk R x := by +theorem toOpen_germ (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) : + toOpen R U ≫ (structureSheaf R).presheaf.germ U x hx = toStalk R x := by rw [← toOpen_res R ⊤ U (homOfLE le_top : U ⟶ ⊤), Category.assoc, Presheaf.germ_res]; rfl @[simp] -theorem germ_toOpen (U : Opens (PrimeSpectrum.Top R)) (x : U) (f : R) : - (structureSheaf R).presheaf.germ x (toOpen R U f) = toStalk R x f := by rw [← toOpen_germ]; rfl +theorem germ_toOpen + (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) (f : R) : + (structureSheaf R).presheaf.germ U x hx (toOpen R U f) = toStalk R x f := by + rw [← toOpen_germ]; rfl -theorem germ_to_top (x : PrimeSpectrum.Top R) (f : R) : - (structureSheaf R).presheaf.germ (⟨x, trivial⟩ : (⊤ : Opens (PrimeSpectrum.Top R))) - (toOpen R ⊤ f) = - toStalk R x f := +theorem toOpen_Γgerm_apply (x : PrimeSpectrum.Top R) (f : R) : + (structureSheaf R).presheaf.Γgerm x (toOpen R ⊤ f) = toStalk R x f := rfl +@[deprecated (since := "2024-07-30")] alias germ_to_top := toOpen_Γgerm_apply + theorem isUnit_to_basicOpen_self (f : R) : IsUnit (toOpen R (PrimeSpectrum.basicOpen f) f) := isUnit_of_mul_eq_one _ (const R 1 f (PrimeSpectrum.basicOpen f) fun _ => id) <| by rw [toOpen_eq_const, const_mul_rev] theorem isUnit_toStalk (x : PrimeSpectrum.Top R) (f : x.asIdeal.primeCompl) : IsUnit (toStalk R x (f : R)) := by - erw [← germ_toOpen R (PrimeSpectrum.basicOpen (f : R)) ⟨x, f.2⟩ (f : R)] + rw [← germ_toOpen R (PrimeSpectrum.basicOpen (f : R)) x f.2 (f : R)] exact RingHom.isUnit_map _ (isUnit_to_basicOpen_self R f) /-- The canonical ring homomorphism from the localization of `R` at `p` to the stalk @@ -442,11 +445,11 @@ theorem localizationToStalk_of (x : PrimeSpectrum.Top R) (f : R) : @[simp] theorem localizationToStalk_mk' (x : PrimeSpectrum.Top R) (f : R) (s : x.asIdeal.primeCompl) : localizationToStalk R x (IsLocalization.mk' (Localization.AtPrime x.asIdeal) f s) = - (structureSheaf R).presheaf.germ (⟨x, s.2⟩ : PrimeSpectrum.basicOpen (s : R)) + (structureSheaf R).presheaf.germ (PrimeSpectrum.basicOpen (s : R)) x s.2 (const R f s (PrimeSpectrum.basicOpen s) fun _ => id) := (IsLocalization.lift_mk'_spec (S := Localization.AtPrime x.asIdeal) _ _ _ _).2 <| by - erw [← germ_toOpen R (PrimeSpectrum.basicOpen s) ⟨x, s.2⟩, - ← germ_toOpen R (PrimeSpectrum.basicOpen s) ⟨x, s.2⟩, ← RingHom.map_mul, toOpen_eq_const, + rw [← germ_toOpen R (PrimeSpectrum.basicOpen s) x s.2, + ← germ_toOpen R (PrimeSpectrum.basicOpen s) x s.2, ← RingHom.map_mul, toOpen_eq_const, toOpen_eq_const, const_mul_cancel'] /-- The ring homomorphism that takes a section of the structure sheaf of `R` on the open set `U`, @@ -484,27 +487,25 @@ def stalkToFiberRingHom (x : PrimeSpectrum.Top R) : openToLocalization R ((OpenNhds.inclusion _).obj (unop U)) x (unop U).2 } } @[simp] -theorem germ_comp_stalkToFiberRingHom (U : Opens (PrimeSpectrum.Top R)) (x : U) : - (structureSheaf R).presheaf.germ x ≫ stalkToFiberRingHom R x = openToLocalization R U x x.2 := +theorem germ_comp_stalkToFiberRingHom + (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) (hx : x ∈ U) : + (structureSheaf R).presheaf.germ U x hx ≫ stalkToFiberRingHom R x = + openToLocalization R U x hx := Limits.colimit.ι_desc _ _ @[simp] -theorem stalkToFiberRingHom_germ' (U : Opens (PrimeSpectrum.Top R)) (x : PrimeSpectrum.Top R) - (hx : x ∈ U) (s : (structureSheaf R).1.obj (op U)) : - stalkToFiberRingHom R x ((structureSheaf R).presheaf.germ ⟨x, hx⟩ s) = (s.1 ⟨x, hx⟩ : _) := - RingHom.ext_iff.1 (germ_comp_stalkToFiberRingHom R U ⟨x, hx⟩ : _) s +theorem stalkToFiberRingHom_germ (U : Opens (PrimeSpectrum.Top R)) + (x : PrimeSpectrum.Top R) (hx : x ∈ U) (s : (structureSheaf R).1.obj (op U)) : + stalkToFiberRingHom R x ((structureSheaf R).presheaf.germ U x hx s) = s.1 ⟨x, hx⟩ := + RingHom.ext_iff.mp (germ_comp_stalkToFiberRingHom R U x hx) s -@[simp] -theorem stalkToFiberRingHom_germ (U : Opens (PrimeSpectrum.Top R)) (x : U) - (s : (structureSheaf R).1.obj (op U)) : - stalkToFiberRingHom R x ((structureSheaf R).presheaf.germ x s) = s.1 x := by - cases x; exact stalkToFiberRingHom_germ' R U _ _ _ +@[deprecated (since := "2024-07-30")] alias stalkToFiberRingHom_germ' := stalkToFiberRingHom_germ @[simp] theorem toStalk_comp_stalkToFiberRingHom (x : PrimeSpectrum.Top R) : -- Porting note: now `algebraMap _ _` needs to be explicitly typed toStalk R x ≫ stalkToFiberRingHom R x = algebraMap R (Localization.AtPrime x.asIdeal) := by - erw [toStalk, Category.assoc, germ_comp_stalkToFiberRingHom]; rfl + rw [toStalk, Category.assoc, germ_comp_stalkToFiberRingHom]; rfl @[simp] theorem stalkToFiberRingHom_toStalk (x : PrimeSpectrum.Top R) (f : R) : @@ -521,31 +522,35 @@ def stalkIso (x : PrimeSpectrum.Top R) : inv := localizationToStalk R x hom_inv_id := by ext U hxU s - -- Note: this `simp` was longer, but the line below had to become an `erw` - simp only [Category.comp_id] - erw [comp_apply, comp_apply, stalkToFiberRingHom_germ'] + dsimp only [Category.comp_id, CommRingCat.forget_obj, + CommRingCat.coe_of, CommRingCat.comp_apply] + rw [stalkToFiberRingHom_germ] obtain ⟨V, hxV, iVU, f, g, (hg : V ≤ PrimeSpectrum.basicOpen _), hs⟩ := exists_const _ _ s x hxU - erw [← res_apply R U V iVU s ⟨x, hxV⟩, ← hs, const_apply, localizationToStalk_mk'] + rw [← res_apply R U V iVU s ⟨x, hxV⟩, ← hs, const_apply, localizationToStalk_mk'] refine (structureSheaf R).presheaf.germ_ext V hxV (homOfLE hg) iVU ?_ - dsimp - erw [← hs, res_const'] + rw [← hs, res_const'] inv_hom_id := @IsLocalization.ringHom_ext R _ x.asIdeal.primeCompl (Localization.AtPrime x.asIdeal) _ _ (Localization.AtPrime x.asIdeal) _ _ (RingHom.comp (stalkToFiberRingHom R x) (localizationToStalk R x)) (RingHom.id (Localization.AtPrime _)) <| by ext f - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - rw [RingHom.comp_apply, RingHom.comp_apply]; erw [localizationToStalk_of, - stalkToFiberRingHom_toStalk]; rw [RingHom.comp_apply, RingHom.id_apply] + rw [RingHom.comp_apply, RingHom.comp_apply, localizationToStalk_of, + stalkToFiberRingHom_toStalk, RingHom.comp_apply, RingHom.id_apply] instance (x : PrimeSpectrum R) : IsIso (stalkToFiberRingHom R x) := (stalkIso R x).isIso_hom +instance (x : PrimeSpectrum R) : IsLocalRingHom (stalkToFiberRingHom R x) := + isLocalRingHom_of_isIso _ + instance (x : PrimeSpectrum R) : IsIso (localizationToStalk R x) := (stalkIso R x).isIso_inv +instance (x : PrimeSpectrum R) : IsLocalRingHom (localizationToStalk R x) := + isLocalRingHom_of_isIso _ + @[simp, reassoc] theorem stalkToFiberRingHom_localizationToStalk (x : PrimeSpectrum.Top R) : stalkToFiberRingHom R x ≫ localizationToStalk R x = 𝟙 _ := @@ -567,8 +572,7 @@ theorem toBasicOpen_mk' (s f : R) (g : Submonoid.powers s) : toBasicOpen R s (IsLocalization.mk' (Localization.Away s) f g) = const R f g (PrimeSpectrum.basicOpen s) fun x hx => Submonoid.powers_le.2 hx g.2 := (IsLocalization.lift_mk'_spec _ _ _ _).2 <| by - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [toOpen_eq_const, toOpen_eq_const]; rw [const_mul_cancel'] + rw [toOpen_eq_const, toOpen_eq_const, const_mul_cancel'] @[simp] theorem localization_toBasicOpen (f : R) : @@ -609,9 +613,7 @@ theorem toBasicOpen_injective (f : R) : Function.Injective (toBasicOpen R f) := rw [PrimeSpectrum.mem_zeroLocus, Set.not_subset] have := congr_fun (congr_arg Subtype.val h_eq) ⟨p, hfp⟩ dsimp at this - -- Porting note: need to tell Lean what `S` is and need to change to `erw` - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [IsLocalization.eq (S := Localization.AtPrime p.asIdeal)] at this + rw [IsLocalization.eq (S := Localization.AtPrime p.asIdeal)] at this cases' this with r hr exact ⟨r.1, hr, r.2⟩ @@ -876,7 +878,7 @@ instance IsLocalization.to_stalk (p : PrimeSpectrum R) : rw [stalkAlgebra_map] congr 1 change toStalk R p = _ ≫ (stalkIso R p).inv - erw [Iso.eq_comp_inv] + rw [Iso.eq_comp_inv] exact toStalk_comp_stalkToFiberRingHom R p instance openAlgebra (U : (Opens (PrimeSpectrum R))ᵒᵖ) : Algebra R ((structureSheaf R).val.obj U) := @@ -1059,9 +1061,7 @@ theorem comap_const (f : R →+* S) (U : Opens (PrimeSpectrum.Top R)) const S (f a) (f b) V fun p hpV => hb (PrimeSpectrum.comap f p) (hUV hpV) := Subtype.eq <| funext fun p => by - rw [comap_apply, const_apply, const_apply] - erw [Localization.localRingHom_mk'] - rfl + rw [comap_apply, const_apply, const_apply, Localization.localRingHom_mk'] /-- For an inclusion `i : V ⟶ U` between open sets of the prime spectrum of `R`, the comap of the identity from OO_X(U) to OO_X(V) equals as the restriction map of the structure sheaf. @@ -1095,7 +1095,7 @@ are not definitionally equal. theorem comap_id {U V : Opens (PrimeSpectrum.Top R)} (hUV : U = V) : (comap (RingHom.id R) U V fun p hpV => by rwa [hUV, PrimeSpectrum.comap_id]) = eqToHom (show (structureSheaf R).1.obj (op U) = _ by rw [hUV]) := by - erw [comap_id_eq_map U V (eqToHom hUV.symm), eqToHom_op, eqToHom_map] + rw [comap_id_eq_map U V (eqToHom hUV.symm), eqToHom_op, eqToHom_map] @[simp] theorem comap_id' (U : Opens (PrimeSpectrum.Top R)) : @@ -1111,7 +1111,7 @@ theorem comap_comp (f : R →+* S) (g : S →+* P) (U : Opens (PrimeSpectrum.Top Subtype.eq <| funext fun p => by rw [comap_apply] - erw [Localization.localRingHom_comp _ (PrimeSpectrum.comap g p.1).asIdeal] <;> + rw [Localization.localRingHom_comp _ (PrimeSpectrum.comap g p.1).asIdeal] <;> -- refl works here, because `PrimeSpectrum.comap (g.comp f) p` is defeq to -- `PrimeSpectrum.comap f (PrimeSpectrum.comap g p)` rfl diff --git a/Mathlib/AlgebraicTopology/CechNerve.lean b/Mathlib/AlgebraicTopology/CechNerve.lean index 0f3fe3235d5db..5f4b8181e1ed0 100644 --- a/Mathlib/AlgebraicTopology/CechNerve.lean +++ b/Mathlib/AlgebraicTopology/CechNerve.lean @@ -142,7 +142,7 @@ def cechNerveEquiv (X : SimplicialObject.Augmented C) (F : Arrow C) : intro A ext · dsimp - erw [WidePullback.lift_π] + rw [WidePullback.lift_π] nth_rw 2 [← Category.id_comp A.left] congr 1 convert X.left.map_id _ @@ -193,7 +193,7 @@ def cechConerve : CosimplicialObject C where map {x y} g := by refine WidePushout.desc (WidePushout.head _) (fun i => (@WidePushout.ι _ _ _ _ _ (fun _ => f.hom) (_) (g.toOrderHom i))) (fun j => ?_) - erw [← WidePushout.arrow_ι] + rw [← WidePushout.arrow_ι] /-- The morphism between Čech conerves associated to a morphism of arrows. -/ @[simps] @@ -308,7 +308,7 @@ def cechConerveEquiv (F : Arrow C) (X : CosimplicialObject.Augmented C) : ext · rfl · dsimp - erw [WidePushout.ι_desc] + rw [WidePushout.ι_desc] nth_rw 2 [← Category.comp_id A.right] congr 1 convert X.right.map_id _ diff --git a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean index 43aa24e304f15..cff0ffb6de103 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/Normalized.lean @@ -142,7 +142,7 @@ def N₁_iso_normalizedMooreComplex_comp_toKaroubi : N₁ ≅ normalizedMooreCom PInftyToNormalizedMooreComplex_comp_inclusionOfMooreComplexMap, inclusionOfMooreComplexMap_comp_PInfty] dsimp only [Functor.comp_obj, toKaroubi] - erw [id_comp] + rw [id_comp] end DoldKan diff --git a/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean b/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean index f9d67b69c0cf5..1640f26ee2f41 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/PInfty.lean @@ -179,7 +179,7 @@ theorem karoubi_PInfty_f {Y : Karoubi (SimplicialObject C)} (n : ℕ) : ((𝟙 (karoubiFunctorCategoryEmbedding SimplexCategoryᵒᵖ C)) ◫ (natTransPInfty_f (Karoubi C) n)) Y dsimp [natTransPInfty_f] at h₁₄ - erw [id_comp, id_comp, comp_id, comp_id] at h₁₄ + rw [id_comp, id_comp, comp_id, comp_id] at h₁₄ -- We use the three equalities h₃₂, h₄₃, h₁₄. rw [← h₃₂, ← h₄₃, h₁₄] simp only [KaroubiFunctorCategoryEmbedding.map_app_f, Karoubi.decompId_p_f, diff --git a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean index 7cf65c0fc934b..1a0800fec44ea 100644 --- a/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/DoldKan/SplitSimplicialObject.lean @@ -229,7 +229,7 @@ noncomputable def nondegComplexFunctor : Split C ⥤ ChainComplex C ℕ where apply S₁.s.hom_ext' intro A dsimp [alternatingFaceMapComplex] - erw [cofan_inj_naturality_symm_assoc Φ A] + rw [cofan_inj_naturality_symm_assoc Φ A] by_cases h : A.EqId · dsimp at h subst h diff --git a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean index 4610e95420a71..478287d6c7e9c 100644 --- a/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean +++ b/Mathlib/AlgebraicTopology/ExtraDegeneracy.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.AlgebraicTopology.AlternatingFaceMapComplex -import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic import Mathlib.AlgebraicTopology.CechNerve import Mathlib.Algebra.Homology.Homotopy import Mathlib.Tactic.FinCases diff --git a/Mathlib/AlgebraicTopology/FundamentalGroupoid/Basic.lean b/Mathlib/AlgebraicTopology/FundamentalGroupoid/Basic.lean index 84980eaca3178..2a8bb0c418f7e 100644 --- a/Mathlib/AlgebraicTopology/FundamentalGroupoid/Basic.lean +++ b/Mathlib/AlgebraicTopology/FundamentalGroupoid/Basic.lean @@ -59,7 +59,7 @@ theorem reflTransSymmAux_mem_I (x : I × I) : reflTransSymmAux x ∈ I := by · norm_num · unit_interval · rw [mul_assoc] - apply mul_le_one + apply mul_le_one₀ · unit_interval · apply mul_nonneg · norm_num @@ -69,7 +69,7 @@ theorem reflTransSymmAux_mem_I (x : I × I) : reflTransSymmAux x ∈ I := by · apply mul_nonneg · unit_interval linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2] - · apply mul_le_one + · apply mul_le_one₀ · unit_interval · linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2] · linarith [unitInterval.nonneg x.2, unitInterval.le_one x.2] diff --git a/Mathlib/AlgebraicTopology/SimplexCategory.lean b/Mathlib/AlgebraicTopology/SimplexCategory.lean index e72f2e8cd7bec..38c94b643e51d 100644 --- a/Mathlib/AlgebraicTopology/SimplexCategory.lean +++ b/Mathlib/AlgebraicTopology/SimplexCategory.lean @@ -165,6 +165,43 @@ theorem const_comp (x : SimplexCategory) {y z : SimplexCategory} const x y i ≫ f = const x z (f.toOrderHom i) := rfl +theorem const_fac_thru_zero (n m : SimplexCategory) (i : Fin (m.len + 1)) : + const n m i = const n [0] 0 ≫ SimplexCategory.const [0] m i := by + rw [const_comp]; rfl + +theorem eq_const_of_zero {n : SimplexCategory} (f : ([0] : SimplexCategory) ⟶ n) : + f = const _ n (f.toOrderHom 0) := by + ext x; match x with | 0 => rfl + +theorem exists_eq_const_of_zero {n : SimplexCategory} (f : ([0] : SimplexCategory) ⟶ n) : + ∃ a, f = const _ n a := ⟨_, eq_const_of_zero _⟩ + +theorem eq_const_to_zero {n : SimplexCategory} (f : n ⟶ [0]) : + f = const n _ 0 := by + ext : 3 + apply @Subsingleton.elim (Fin 1) + +theorem eq_of_one_to_one (f : ([1] : SimplexCategory) ⟶ [1]) : + (∃ a, f = const [1] _ a) ∨ f = 𝟙 _ := by + match e0 : f.toOrderHom 0, e1 : f.toOrderHom 1 with + | 0, 0 | 1, 1 => + refine .inl ⟨f.toOrderHom 0, ?_⟩ + ext i : 3 + match i with + | 0 => rfl + | 1 => exact e1.trans e0.symm + | 0, 1 => + right + ext i : 3 + match i with + | 0 => exact e0 + | 1 => exact e1 + | 1, 0 => + have := f.toOrderHom.monotone (by decide : (0 : Fin 2) ≤ 1) + rw [e0, e1] at this + exact Not.elim (by decide) this + + /-- Make a morphism `[n] ⟶ [m]` from a monotone map between fin's. This is useful for constructing morphisms between `[n]` directly without identifying `n` with `[n].len`. @@ -173,6 +210,36 @@ without identifying `n` with `[n].len`. def mkHom {n m : ℕ} (f : Fin (n + 1) →o Fin (m + 1)) : ([n] : SimplexCategory) ⟶ [m] := SimplexCategory.Hom.mk f +/-- The morphism `[1] ⟶ [n]` that picks out a specified `h : i ≤ j` in `Fin (n+1)`.-/ +def mkOfLe {n} (i j : Fin (n+1)) (h : i ≤ j) : ([1] : SimplexCategory) ⟶ [n] := + SimplexCategory.mkHom { + toFun := fun | 0 => i | 1 => j + monotone' := fun + | 0, 0, _ | 1, 1, _ => le_rfl + | 0, 1, _ => h + } + +/-- The morphism `[1] ⟶ [n]` that picks out the arrow `i ⟶ i+1` in `Fin (n+1)`.-/ +def mkOfSucc {n} (i : Fin n) : ([1] : SimplexCategory) ⟶ [n] := + SimplexCategory.mkHom { + toFun := fun | 0 => i.castSucc | 1 => i.succ + monotone' := fun + | 0, 0, _ | 1, 1, _ => le_rfl + | 0, 1, _ => Fin.castSucc_le_succ i + } + +/-- The morphism `[2] ⟶ [n]` that picks out a specified composite of morphisms in `Fin (n+1)`.-/ +def mkOfLeComp {n} (i j k : Fin (n + 1)) (h₁ : i ≤ j) (h₂ : j ≤ k) : + ([2] : SimplexCategory) ⟶ [n] := + SimplexCategory.mkHom { + toFun := fun | 0 => i | 1 => j | 2 => k + monotone' := fun + | 0, 0, _ | 1, 1, _ | 2, 2, _ => le_rfl + | 0, 1, _ => h₁ + | 1, 2, _ => h₂ + | 0, 2, _ => Fin.le_trans h₁ h₂ + } + instance (Δ : SimplexCategory) : Subsingleton (Δ ⟶ [0]) where allEq f g := by ext : 3; apply Subsingleton.elim (α := Fin 1) @@ -400,6 +467,40 @@ lemma factor_δ_spec {m n : ℕ} (f : ([m] : SimplexCategory) ⟶ [n+1]) (j : Fi · rwa [succ_le_castSucc_iff, lt_pred_iff] rw [succ_pred] + +theorem eq_of_one_to_two (f : ([1] : SimplexCategory) ⟶ [2]) : + f = (δ (n := 1) 0) ∨ f = (δ (n := 1) 1) ∨ f = (δ (n := 1) 2) ∨ + ∃ a, f = SimplexCategory.const _ _ a := by + have : f.toOrderHom 0 ≤ f.toOrderHom 1 := f.toOrderHom.monotone (by decide : (0 : Fin 2) ≤ 1) + match e0 : f.toOrderHom 0, e1 : f.toOrderHom 1 with + | 1, 2 => + left + ext i : 3 + match i with + | 0 => exact e0 + | 1 => exact e1 + | 0, 2 => + right; left + ext i : 3 + match i with + | 0 => exact e0 + | 1 => exact e1 + | 0, 1 => + right; right; left + ext i : 3 + match i with + | 0 => exact e0 + | 1 => exact e1 + | 0, 0 | 1, 1 | 2, 2 => + right; right; right; use f.toOrderHom 0 + ext i : 3 + match i with + | 0 => rfl + | 1 => exact e1.trans e0.symm + | 1, 0 | 2, 0 | 2, 1 => + rw [e0, e1] at this + exact Not.elim (by decide) this + end Generators section Skeleton @@ -490,6 +591,14 @@ def inclusion {n : ℕ} : SimplexCategory.Truncated n ⥤ SimplexCategory := instance (n : ℕ) : (inclusion : Truncated n ⥤ _).Full := FullSubcategory.full _ instance (n : ℕ) : (inclusion : Truncated n ⥤ _).Faithful := FullSubcategory.faithful _ +/-- A proof that the full subcategory inclusion is fully faithful.-/ +noncomputable def inclusion.fullyFaithful (n : ℕ) : + (inclusion : Truncated n ⥤ _).op.FullyFaithful := Functor.FullyFaithful.ofFullyFaithful _ + +@[ext] +theorem Hom.ext {n} {a b : Truncated n} (f g : a ⟶ b) : + f.toOrderHom = g.toOrderHom → f = g := SimplexCategory.Hom.ext _ _ + end Truncated section Concrete @@ -630,7 +739,7 @@ theorem eq_σ_comp_of_not_injective' {n : ℕ} {Δ' : SimplexCategory} (θ : mk dsimp rw [Fin.predAbove_of_le_castSucc i x h'] dsimp [δ] - erw [Fin.succAbove_of_castSucc_lt _ _ _] + rw [Fin.succAbove_of_castSucc_lt _ _ _] · rw [Fin.castSucc_castPred] · exact (Fin.castSucc_lt_succ_iff.mpr h') · simp only [not_le] at h' @@ -645,10 +754,10 @@ theorem eq_σ_comp_of_not_injective' {n : ℕ} {Δ' : SimplexCategory} (θ : mk refine hi.symm.trans ?_ congr 1 dsimp [δ] - erw [Fin.succAbove_of_castSucc_lt i.succ] + rw [Fin.succAbove_of_castSucc_lt i.succ] exact Fin.lt_succ · dsimp [δ] - erw [Fin.succAbove_of_le_castSucc i.succ _] + rw [Fin.succAbove_of_le_castSucc i.succ _] simp only [Fin.lt_iff_val_lt_val, Fin.le_iff_val_le_val, Fin.val_succ, Fin.coe_castSucc, Nat.lt_succ_iff, Fin.ext_iff] at h' h'' ⊢ cases' Nat.le.dest h' with c hc @@ -693,18 +802,17 @@ theorem eq_comp_δ_of_not_surjective' {n : ℕ} {Δ : SimplexCategory} (θ : Δ simp only [len_mk, Category.assoc, comp_toOrderHom, OrderHom.comp_coe, Function.comp_apply] by_cases h' : θ.toOrderHom x ≤ i · simp only [σ, mkHom, Hom.toOrderHom_mk, OrderHom.coe_mk] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [Fin.predAbove_of_le_castSucc _ _ (by rwa [Fin.castSucc_castPred])] + rw [Fin.predAbove_of_le_castSucc _ _ (by rwa [Fin.castSucc_castPred])] dsimp [δ] - erw [Fin.succAbove_of_castSucc_lt i] + rw [Fin.succAbove_of_castSucc_lt i] · rw [Fin.castSucc_castPred] · rw [(hi x).le_iff_lt] at h' exact h' · simp only [not_le] at h' dsimp [σ, δ] - erw [Fin.predAbove_of_castSucc_lt _ _ (by rwa [Fin.castSucc_castPred])] + rw [Fin.predAbove_of_castSucc_lt _ _ (by rwa [Fin.castSucc_castPred])] rw [Fin.succAbove_of_le_castSucc i _] - · erw [Fin.succ_pred] + · rw [Fin.succ_pred] · exact 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 _) diff --git a/Mathlib/AlgebraicTopology/SimplicialObject.lean b/Mathlib/AlgebraicTopology/SimplicialObject.lean index ea02f63a11c95..c15da7cf1c35d 100644 --- a/Mathlib/AlgebraicTopology/SimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SimplicialObject.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ import Mathlib.AlgebraicTopology.SimplexCategory +import Mathlib.CategoryTheory.Adjunction.Reflective import Mathlib.CategoryTheory.Comma.Arrow +import Mathlib.CategoryTheory.Functor.KanExtension.Adjunction import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Opposites @@ -23,7 +25,7 @@ open Opposite open CategoryTheory -open CategoryTheory.Limits +open CategoryTheory.Limits CategoryTheory.Functor universe v u v' u' @@ -241,13 +243,103 @@ variable {C} end Truncated -section Skeleton +section Truncation -/-- The skeleton functor from simplicial objects to truncated simplicial objects. -/ -def sk (n : ℕ) : SimplicialObject C ⥤ SimplicialObject.Truncated C n := +/-- The truncation functor from simplicial objects to truncated simplicial objects. -/ +def truncation (n : ℕ) : SimplicialObject C ⥤ SimplicialObject.Truncated C n := (whiskeringLeft _ _ _).obj SimplexCategory.Truncated.inclusion.op -end Skeleton +end Truncation + + +noncomputable section + +/-- The n-skeleton as a functor `SimplicialObject.Truncated C n ⥤ SimplicialObject C`. -/ +protected abbrev Truncated.sk (n : ℕ) [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasLeftKanExtension F] : + SimplicialObject.Truncated C n ⥤ SimplicialObject C := + lan (SimplexCategory.Truncated.inclusion.op) + +/-- The n-coskeleton as a functor `SimplicialObject.Truncated C n ⥤ SimplicialObject C`. -/ +protected abbrev Truncated.cosk (n : ℕ) [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasRightKanExtension F] : + SimplicialObject.Truncated C n ⥤ SimplicialObject C := + ran (SimplexCategory.Truncated.inclusion.op) + +/-- The n-skeleton as an endofunctor on `SimplicialObject C`. -/ +abbrev sk (n : ℕ) [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasLeftKanExtension F] : + SimplicialObject C ⥤ SimplicialObject C := truncation n ⋙ Truncated.sk n + +/-- The n-coskeleton as an endofunctor on `SimplicialObject C`. -/ +abbrev cosk (n : ℕ) [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasRightKanExtension F] : + SimplicialObject C ⥤ SimplicialObject C := truncation n ⋙ Truncated.cosk n + +end + +section adjunctions +/- When the left and right Kan extensions exist, `Truncated.sk n` and `Truncated.cosk n` +respectively define left and right adjoints to `truncation n`.-/ + + +variable (n : ℕ) +variable [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasRightKanExtension F] +variable [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasLeftKanExtension F] + +/-- The adjunction between the n-skeleton and n-truncation.-/ +noncomputable def skAdj : Truncated.sk (C := C) n ⊣ truncation n := + lanAdjunction _ _ + +/-- The adjunction between n-truncation and the n-coskeleton.-/ +noncomputable def coskAdj : truncation (C := C) n ⊣ Truncated.cosk n := + ranAdjunction _ _ + +namespace Truncated +/- When the left and right Kan extensions exist and are pointwise Kan extensions, +`skAdj n` and `coskAdj n` are respectively coreflective and reflective.-/ + +variable [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasPointwiseRightKanExtension F] +variable [∀ (F : (SimplexCategory.Truncated n)ᵒᵖ ⥤ C), + SimplexCategory.Truncated.inclusion.op.HasPointwiseLeftKanExtension F] + +instance cosk_reflective : IsIso (coskAdj (C := C) n).counit := + reflective' SimplexCategory.Truncated.inclusion.op + +instance sk_coreflective : IsIso (skAdj (C := C) n).unit := + coreflective' SimplexCategory.Truncated.inclusion.op + +/-- Since `Truncated.inclusion` is fully faithful, so is right Kan extension along it.-/ +noncomputable def cosk.fullyFaithful : + (Truncated.cosk (C := C) n).FullyFaithful := by + apply Adjunction.fullyFaithfulROfIsIsoCounit (coskAdj n) + +instance cosk.full : (Truncated.cosk (C := C) n).Full := FullyFaithful.full (cosk.fullyFaithful _) + +instance cosk.faithful : (Truncated.cosk (C := C) n).Faithful := + FullyFaithful.faithful (cosk.fullyFaithful _) + +noncomputable instance coskAdj.reflective : Reflective (Truncated.cosk (C := C) n) := + Reflective.mk (truncation _) (coskAdj _) + +/-- Since `Truncated.inclusion` is fully faithful, so is left Kan extension along it.-/ +noncomputable def sk.fullyFaithful : (Truncated.sk (C := C) n).FullyFaithful := + Adjunction.fullyFaithfulLOfIsIsoUnit (skAdj n) + +instance sk.full : (Truncated.sk (C := C) n).Full := FullyFaithful.full (sk.fullyFaithful _) + +instance sk.faithful : (Truncated.sk (C := C) n).Faithful := + FullyFaithful.faithful (sk.fullyFaithful _) + +noncomputable instance skAdj.coreflective : Coreflective (Truncated.sk (C := C) n) := + Coreflective.mk (truncation _) (skAdj _) + +end Truncated + +end adjunctions variable (C) @@ -576,13 +668,13 @@ variable {C} end Truncated -section Skeleton +section Truncation -/-- The skeleton functor from cosimplicial objects to truncated cosimplicial objects. -/ -def sk (n : ℕ) : CosimplicialObject C ⥤ CosimplicialObject.Truncated C n := +/-- The truncation functor from cosimplicial objects to truncated cosimplicial objects. -/ +def truncation (n : ℕ) : CosimplicialObject C ⥤ CosimplicialObject.Truncated C n := (whiskeringLeft _ _ _).obj SimplexCategory.Truncated.inclusion -end Skeleton +end Truncation variable (C) diff --git a/Mathlib/AlgebraicTopology/SimplicialSet.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean similarity index 82% rename from Mathlib/AlgebraicTopology/SimplicialSet.lean rename to Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean index a8198f848a6c7..2a21c558b5ebb 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Basic.lean @@ -33,7 +33,7 @@ a morphism `Δ[n] ⟶ ∂Δ[n]`. universe v u -open CategoryTheory CategoryTheory.Limits +open CategoryTheory CategoryTheory.Limits CategoryTheory.Functor open Simplicial @@ -303,7 +303,7 @@ lemma hom_ext {n : ℕ} {i : Fin (n+2)} {S : SSet} (σ₁ σ₂ : Λ[n+1, i] ⟶ 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] + rw [H, H₁, H₂, h _ hji] end horn @@ -335,18 +335,91 @@ instance Truncated.hasColimits {n : ℕ} : HasColimits (Truncated n) := by dsimp only [Truncated] infer_instance +/-- The ulift functor `SSet.Truncated.{u} ⥤ SSet.Truncated.{max u v}` on truncated +simplicial sets. -/ +def Truncated.uliftFunctor (k : ℕ) : SSet.Truncated.{u} k ⥤ SSet.Truncated.{max u v} k := + (whiskeringRight _ _ _).obj CategoryTheory.uliftFunctor.{v, u} + -- Porting note (#5229): added an `ext` lemma. @[ext] lemma Truncated.hom_ext {n : ℕ} {X Y : Truncated n} {f g : X ⟶ Y} (w : ∀ n, f.app n = g.app n) : f = g := NatTrans.ext (funext w) -/-- The skeleton functor on simplicial sets. -/ -def sk (n : ℕ) : SSet ⥤ SSet.Truncated n := - SimplicialObject.sk n +/-- The truncation functor on simplicial sets. -/ +abbrev truncation (n : ℕ) : SSet ⥤ SSet.Truncated n := SimplicialObject.truncation n instance {n} : Inhabited (SSet.Truncated n) := - ⟨(sk n).obj <| Δ[0]⟩ + ⟨(truncation n).obj <| Δ[0]⟩ + + +open SimplexCategory + +noncomputable section + +/-- The n-skeleton as a functor `SSet.Truncated n ⥤ SSet`. -/ +protected abbrev Truncated.sk (n : ℕ) : SSet.Truncated n ⥤ SSet.{u} := + SimplicialObject.Truncated.sk n + +/-- The n-coskeleton as a functor `SSet.Truncated n ⥤ SSet`. -/ +protected abbrev Truncated.cosk (n : ℕ) : SSet.Truncated n ⥤ SSet.{u} := + SimplicialObject.Truncated.cosk n + +/-- The n-skeleton as an endofunctor on `SSet`. -/ +abbrev sk (n : ℕ) : SSet ⥤ SSet := SimplicialObject.sk n + +/-- The n-coskeleton as an endofunctor on `SSet`. -/ +abbrev cosk (n : ℕ) : SSet ⥤ SSet := SimplicialObject.cosk n + +end + +section adjunctions + +/-- The adjunction between the n-skeleton and n-truncation.-/ +noncomputable def skAdj (n : ℕ) : Truncated.sk n ⊣ truncation.{u} n := + SimplicialObject.skAdj n + +/-- The adjunction between n-truncation and the n-coskeleton.-/ +noncomputable def coskAdj (n : ℕ) : truncation.{u} n ⊣ Truncated.cosk n := + SimplicialObject.coskAdj n + +namespace Truncated + +instance cosk_reflective (n) : IsIso (coskAdj n).counit := + SimplicialObject.Truncated.cosk_reflective n + +instance sk_coreflective (n) : IsIso (skAdj n).unit := + SimplicialObject.Truncated.sk_coreflective n + +/-- Since `Truncated.inclusion` is fully faithful, so is right Kan extension along it.-/ +noncomputable def cosk.fullyFaithful (n) : + (Truncated.cosk n).FullyFaithful := + SimplicialObject.Truncated.cosk.fullyFaithful n + +instance cosk.full (n) : (Truncated.cosk n).Full := + SimplicialObject.Truncated.cosk.full n + +instance cosk.faithful (n) : (Truncated.cosk n).Faithful := + SimplicialObject.Truncated.cosk.faithful n + +noncomputable instance coskAdj.reflective (n) : Reflective (Truncated.cosk n) := + SimplicialObject.Truncated.coskAdj.reflective n + +/-- Since `Truncated.inclusion` is fully faithful, so is left Kan extension along it.-/ +noncomputable def sk.fullyFaithful (n) : + (Truncated.sk n).FullyFaithful := SimplicialObject.Truncated.sk.fullyFaithful n + +instance sk.full (n) : (Truncated.sk n).Full := SimplicialObject.Truncated.sk.full n + +instance sk.faithful (n) : (Truncated.sk n).Faithful := + SimplicialObject.Truncated.sk.faithful n + +noncomputable instance skAdj.coreflective (n) : Coreflective (Truncated.sk n) := + SimplicialObject.Truncated.skAdj.coreflective n + +end Truncated + +end adjunctions /-- The category of augmented simplicial sets, as a particular case of augmented simplicial objects. -/ diff --git a/Mathlib/AlgebraicTopology/KanComplex.lean b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean similarity index 95% rename from Mathlib/AlgebraicTopology/KanComplex.lean rename to Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean index 73a6d4e026c32..531bc99ebc39c 100644 --- a/Mathlib/AlgebraicTopology/KanComplex.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/KanComplex.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic /-! # Kan complexes diff --git a/Mathlib/AlgebraicTopology/SimplicialSet/Monoidal.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Monoidal.lean index 0c12ff6bec5e4..fbee414ae5bd4 100644 --- a/Mathlib/AlgebraicTopology/SimplicialSet/Monoidal.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Monoidal.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou, Jack McKoen -/ -import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic import Mathlib.CategoryTheory.ChosenFiniteProducts.FunctorCategory import Mathlib.CategoryTheory.Monoidal.Types.Basic diff --git a/Mathlib/AlgebraicTopology/Nerve.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Nerve.lean similarity index 96% rename from Mathlib/AlgebraicTopology/Nerve.lean rename to Mathlib/AlgebraicTopology/SimplicialSet/Nerve.lean index 611b1fea9cd22..9e299bd44fc83 100644 --- a/Mathlib/AlgebraicTopology/Nerve.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Nerve.lean @@ -3,7 +3,7 @@ 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.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic import Mathlib.CategoryTheory.ComposableArrows /-! diff --git a/Mathlib/AlgebraicTopology/Quasicategory.lean b/Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean similarity index 97% rename from Mathlib/AlgebraicTopology/Quasicategory.lean rename to Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean index a2590b4c956f6..381e65660f632 100644 --- a/Mathlib/AlgebraicTopology/Quasicategory.lean +++ b/Mathlib/AlgebraicTopology/SimplicialSet/Quasicategory.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.AlgebraicTopology.KanComplex +import Mathlib.AlgebraicTopology.SimplicialSet.KanComplex /-! # Quasicategories diff --git a/Mathlib/AlgebraicTopology/SingularSet.lean b/Mathlib/AlgebraicTopology/SingularSet.lean index bc3d246833408..d97397b1c6019 100644 --- a/Mathlib/AlgebraicTopology/SingularSet.lean +++ b/Mathlib/AlgebraicTopology/SingularSet.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Kim Morrison, Adam Topaz -/ -import Mathlib.AlgebraicTopology.SimplicialSet +import Mathlib.AlgebraicTopology.SimplicialSet.Basic import Mathlib.AlgebraicTopology.TopologicalSimplex import Mathlib.CategoryTheory.Limits.Presheaf import Mathlib.Topology.Category.TopCat.Limits.Basic diff --git a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean index 447b1a9770800..156266bbc5e76 100644 --- a/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean +++ b/Mathlib/AlgebraicTopology/SplitSimplicialObject.lean @@ -241,7 +241,7 @@ def φ (f : X ⟶ Y) (n : ℕ) : s.N n ⟶ Y _[n] := theorem cofan_inj_comp_app (f : X ⟶ Y) {Δ : SimplexCategoryᵒᵖ} (A : IndexSet Δ) : (s.cofan Δ).inj A ≫ f.app Δ = s.φ f A.1.unop.len ≫ Y.map A.e.op := by simp only [cofan_inj_eq_assoc, φ, assoc] - erw [NatTrans.naturality] + rw [NatTrans.naturality] theorem hom_ext' {Z : C} {Δ : SimplexCategoryᵒᵖ} (f g : X.obj Δ ⟶ Z) (h : ∀ A : IndexSet Δ, (s.cofan Δ).inj A ≫ f = (s.cofan Δ).inj A ≫ g) : f = g := @@ -383,7 +383,7 @@ theorem comp_f {S₁ S₂ S₃ : Split C} (Φ₁₂ : S₁ ⟶ S₂) (Φ₂₃ : theorem cofan_inj_naturality_symm {S₁ S₂ : Split C} (Φ : S₁ ⟶ S₂) {Δ : SimplexCategoryᵒᵖ} (A : Splitting.IndexSet Δ) : (S₁.s.cofan Δ).inj A ≫ Φ.F.app Δ = Φ.f A.1.unop.len ≫ (S₂.s.cofan Δ).inj A := by - erw [S₁.s.cofan_inj_eq, S₂.s.cofan_inj_eq, assoc, Φ.F.naturality, ← Φ.comm_assoc] + rw [S₁.s.cofan_inj_eq, S₂.s.cofan_inj_eq, assoc, Φ.F.naturality, ← Φ.comm_assoc] variable (C) diff --git a/Mathlib/Analysis/Analytic/Basic.lean b/Mathlib/Analysis/Analytic/Basic.lean index 1abdcf481ef99..cd994fb7364b8 100644 --- a/Mathlib/Analysis/Analytic/Basic.lean +++ b/Mathlib/Analysis/Analytic/Basic.lean @@ -49,13 +49,13 @@ Additionally, let `f` be a function from `E` to `F`. * `HasFPowerSeriesAt f p x`: on some ball of center `x` with positive radius, holds `HasFPowerSeriesOnBall f p x r`. * `AnalyticAt 𝕜 f x`: there exists a power series `p` such that holds `HasFPowerSeriesAt f p x`. -* `AnalyticOn 𝕜 f s`: the function `f` is analytic at every point of `s`. +* `AnalyticOnNhd 𝕜 f s`: the function `f` is analytic at every point of `s`. -We also define versions of `HasFPowerSeriesOnBall`, `AnalyticAt`, and `AnalyticOn` restricted to a -set, similar to `ContinuousWithinAt`. See `Mathlib.Analysis.Analytic.Within` for basic properties. +We also define versions of `HasFPowerSeriesOnBall`, `AnalyticAt`, and `AnalyticOnNhd` restricted to +a set, similar to `ContinuousWithinAt`. See `Mathlib.Analysis.Analytic.Within` for basic properties. * `AnalyticWithinAt 𝕜 f s x` means a power series at `x` converges to `f` on `𝓝[s ∪ {x}] x`. -* `AnalyticWithinOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. +* `AnalyticOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. We develop the basic properties of these notions, notably: * If a function admits a power series, it is continuous (see @@ -225,7 +225,7 @@ theorem lt_radius_of_isBigO (h₀ : r ≠ 0) {a : ℝ} (ha : a ∈ Ioo (-1 : ℝ theorem norm_mul_pow_le_of_lt_radius (p : FormalMultilinearSeries 𝕜 E F) {r : ℝ≥0} (h : (r : ℝ≥0∞) < p.radius) : ∃ C > 0, ∀ n, ‖p n‖ * (r : ℝ) ^ n ≤ C := let ⟨_, ha, C, hC, h⟩ := p.norm_mul_pow_le_mul_pow_of_lt_radius h - ⟨C, hC, fun n => (h n).trans <| mul_le_of_le_one_right hC.lt.le (pow_le_one _ ha.1.le ha.2.le)⟩ + ⟨C, hC, fun n => (h n).trans <| mul_le_of_le_one_right hC.lt.le (pow_le_one₀ ha.1.le ha.2.le)⟩ /-- For `r` strictly smaller than the radius of `p`, then `‖pₙ‖ rⁿ` is bounded. -/ theorem norm_le_div_pow_of_pos_of_lt_radius (p : FormalMultilinearSeries 𝕜 E F) {r : ℝ≥0} @@ -301,6 +301,18 @@ theorem le_mul_pow_of_radius_pos (p : FormalMultilinearSeries 𝕜 E F) (h : 0 < rw [inv_pow, ← div_eq_mul_inv] exact hCp n +lemma radius_le_of_le {𝕜' E' F' : Type*} + [NontriviallyNormedField 𝕜'] [NormedAddCommGroup E'] [NormedSpace 𝕜' E'] + [NormedAddCommGroup F'] [NormedSpace 𝕜' F'] + {p : FormalMultilinearSeries 𝕜 E F} {q : FormalMultilinearSeries 𝕜' E' F'} + (h : ∀ n, ‖p n‖ ≤ ‖q n‖) : q.radius ≤ p.radius := by + apply le_of_forall_nnreal_lt (fun r hr ↦ ?_) + rcases norm_mul_pow_le_of_lt_radius _ hr with ⟨C, -, hC⟩ + apply le_radius_of_bound _ C (fun n ↦ ?_) + apply le_trans _ (hC n) + gcongr + exact h n + /-- The radius of the sum of two formal series is at least the minimum of their two radii. -/ theorem min_radius_le_radius_add (p q : FormalMultilinearSeries 𝕜 E F) : min p.radius q.radius ≤ (p + q).radius := by @@ -384,14 +396,17 @@ def AnalyticWithinAt (f : E → F) (s : Set E) (x : E) : Prop := /-- Given a function `f : E → F`, we say that `f` is analytic on a set `s` if it is analytic around every point of `s`. -/ -def AnalyticOn (f : E → F) (s : Set E) := +def AnalyticOnNhd (f : E → F) (s : Set E) := ∀ x, x ∈ s → AnalyticAt 𝕜 f x -/-- `f` is analytic within `s` if it is analytic within `s` at each point of `t`. Note that -this is weaker than `AnalyticOn 𝕜 f s`, as `f` is allowed to be arbitrary outside `s`. -/ -def AnalyticWithinOn (f : E → F) (s : Set E) : Prop := +/-- `f` is analytic within `s` if it is analytic within `s` at each point of `s`. Note that +this is weaker than `AnalyticOnNhd 𝕜 f s`, as `f` is allowed to be arbitrary outside `s`. -/ +def AnalyticOn (f : E → F) (s : Set E) : Prop := ∀ x ∈ s, AnalyticWithinAt 𝕜 f s x +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn := AnalyticOn + /-! ### `HasFPowerSeriesOnBall` and `HasFPowerSeriesWithinOnBall` -/ @@ -475,6 +490,16 @@ lemma HasFPowerSeriesWithinOnBall.congr {f g : E → F} {p : FormalMultilinearSe refine ⟨hy, ?_⟩ simpa [edist_eq_coe_nnnorm_sub] using h'y +/-- Variant of `HasFPowerSeriesWithinOnBall.congr` in which one requests equality on `insert x s` +instead of separating `x` and `s`. -/ +lemma HasFPowerSeriesWithinOnBall.congr' {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} + {s : Set E} {x : E} {r : ℝ≥0∞} (h : HasFPowerSeriesWithinOnBall f p s x r) + (h' : EqOn g f (insert x s ∩ EMetric.ball x r)) : + HasFPowerSeriesWithinOnBall g p s x r := by + refine ⟨h.r_le, h.r_pos, fun {y} hy h'y ↦ ?_⟩ + convert h.hasSum hy h'y using 1 + exact h' ⟨hy, by simpa [edist_eq_coe_nnnorm_sub] using h'y⟩ + lemma HasFPowerSeriesWithinAt.congr {f g : E → F} {p : FormalMultilinearSeries 𝕜 E F} {s : Set E} {x : E} (h : HasFPowerSeriesWithinAt f p s x) (h' : g =ᶠ[𝓝[s] x] f) (h'' : g x = f x) : HasFPowerSeriesWithinAt g p s x := by @@ -578,6 +603,37 @@ lemma HasFPowerSeriesAt.hasFPowerSeriesWithinAt (hf : HasFPowerSeriesAt f p x) : rw [← hasFPowerSeriesWithinAt_univ] at hf apply hf.mono (subset_univ _) +theorem HasFPowerSeriesWithinAt.mono_of_mem + (h : HasFPowerSeriesWithinAt f p s x) (hst : s ∈ 𝓝[t] x) : + HasFPowerSeriesWithinAt f p t x := by + rcases h with ⟨r, hr⟩ + rcases EMetric.mem_nhdsWithin_iff.1 hst with ⟨r', r'_pos, hr'⟩ + refine ⟨min r r', ?_⟩ + have Z := hr.of_le (by simp [r'_pos, hr.r_pos]) (min_le_left r r') + refine ⟨Z.r_le, Z.r_pos, fun {y} hy h'y ↦ ?_⟩ + apply Z.hasSum ?_ h'y + simp only [mem_insert_iff, add_right_eq_self] at hy + rcases hy with rfl | hy + · simp + apply mem_insert_of_mem _ (hr' ?_) + simp only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, sub_zero, lt_min_iff, mem_inter_iff, + add_sub_cancel_left, hy, and_true] at h'y ⊢ + exact h'y.2 + +@[simp] lemma hasFPowerSeriesWithinOnBall_insert_self : + HasFPowerSeriesWithinOnBall f p (insert x s) x r ↔ HasFPowerSeriesWithinOnBall f p s x r := by + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ <;> + exact ⟨h.r_le, h.r_pos, fun {y} ↦ by simpa only [insert_idem] using h.hasSum (y := y)⟩ + +@[simp] theorem hasFPowerSeriesWithinAt_insert {y : E} : + HasFPowerSeriesWithinAt f p (insert y s) x ↔ HasFPowerSeriesWithinAt f p s x := by + rcases eq_or_ne x y with rfl | hy + · simp [HasFPowerSeriesWithinAt] + · refine ⟨fun h ↦ h.mono (subset_insert _ _), fun h ↦ ?_⟩ + apply HasFPowerSeriesWithinAt.mono_of_mem h + rw [nhdsWithin_insert_of_ne hy] + exact self_mem_nhdsWithin + theorem HasFPowerSeriesWithinOnBall.coeff_zero (hf : HasFPowerSeriesWithinOnBall f pf s x r) (v : Fin 0 → E) : pf 0 v = f x := by have v_eq : v = fun i => 0 := Subsingleton.elim _ _ @@ -612,9 +668,12 @@ theorem HasFPowerSeriesAt.coeff_zero (hf : HasFPowerSeriesAt f pf x) (v : Fin 0 AnalyticWithinAt 𝕜 f univ x ↔ AnalyticAt 𝕜 f x := by simp [AnalyticWithinAt, AnalyticAt] -@[simp] lemma analyticWithinOn_univ {f : E → F} : - AnalyticWithinOn 𝕜 f univ ↔ AnalyticOn 𝕜 f univ := by - simp only [AnalyticWithinOn, analyticWithinAt_univ, AnalyticOn] +@[simp] lemma analyticOn_univ {f : E → F} : + AnalyticOn 𝕜 f univ ↔ AnalyticOnNhd 𝕜 f univ := by + simp only [AnalyticOn, analyticWithinAt_univ, AnalyticOnNhd] + +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_univ := analyticOn_univ lemma AnalyticWithinAt.mono (hf : AnalyticWithinAt 𝕜 f s x) (h : t ⊆ s) : AnalyticWithinAt 𝕜 f t x := by @@ -625,25 +684,37 @@ lemma AnalyticAt.analyticWithinAt (hf : AnalyticAt 𝕜 f x) : AnalyticWithinAt rw [← analyticWithinAt_univ] at hf apply hf.mono (subset_univ _) -lemma AnalyticOn.analyticWithinOn (hf : AnalyticOn 𝕜 f s) : AnalyticWithinOn 𝕜 f s := +lemma AnalyticOnNhd.analyticOn (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOn 𝕜 f s := fun x hx ↦ (hf x hx).analyticWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.analyticWithinOn := AnalyticOnNhd.analyticOn + lemma AnalyticWithinAt.congr_of_eventuallyEq {f g : E → F} {s : Set E} {x : E} (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[s] x] f) (hx : g x = f x) : AnalyticWithinAt 𝕜 g s x := by rcases hf with ⟨p, hp⟩ exact ⟨p, hp.congr hs hx⟩ +lemma AnalyticWithinAt.congr_of_eventuallyEq_insert {f g : E → F} {s : Set E} {x : E} + (hf : AnalyticWithinAt 𝕜 f s x) (hs : g =ᶠ[𝓝[insert x s] x] f) : + AnalyticWithinAt 𝕜 g s x := by + apply hf.congr_of_eventuallyEq (nhdsWithin_mono x (subset_insert x s) hs) + apply mem_of_mem_nhdsWithin (mem_insert x s) hs + lemma AnalyticWithinAt.congr {f g : E → F} {s : Set E} {x : E} (hf : AnalyticWithinAt 𝕜 f s x) (hs : EqOn g f s) (hx : g x = f x) : AnalyticWithinAt 𝕜 g s x := hf.congr_of_eventuallyEq hs.eventuallyEq_nhdsWithin hx -lemma AnalyticWithinOn.congr {f g : E → F} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hs : EqOn g f s) : - AnalyticWithinOn 𝕜 g s := +lemma AnalyticOn.congr {f g : E → F} {s : Set E} + (hf : AnalyticOn 𝕜 f s) (hs : EqOn g f s) : + AnalyticOn 𝕜 g s := fun x m ↦ (hf x m).congr hs (hs m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.congr := AnalyticOn.congr + theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 g x := let ⟨_, hpf⟩ := hf (hpf.congr hg).analyticAt @@ -651,50 +722,89 @@ theorem AnalyticAt.congr (hf : AnalyticAt 𝕜 f x) (hg : f =ᶠ[𝓝 x] g) : An theorem analyticAt_congr (h : f =ᶠ[𝓝 x] g) : AnalyticAt 𝕜 f x ↔ AnalyticAt 𝕜 g x := ⟨fun hf ↦ hf.congr h, fun hg ↦ hg.congr h.symm⟩ -theorem AnalyticOn.mono {s t : Set E} (hf : AnalyticOn 𝕜 f t) (hst : s ⊆ t) : AnalyticOn 𝕜 f s := +theorem AnalyticOnNhd.mono {s t : Set E} (hf : AnalyticOnNhd 𝕜 f t) (hst : s ⊆ t) : + AnalyticOnNhd 𝕜 f s := fun z hz => hf z (hst hz) -theorem AnalyticOn.congr' (hf : AnalyticOn 𝕜 f s) (hg : f =ᶠ[𝓝ˢ s] g) : - AnalyticOn 𝕜 g s := +theorem AnalyticOnNhd.congr' (hf : AnalyticOnNhd 𝕜 f s) (hg : f =ᶠ[𝓝ˢ s] g) : + AnalyticOnNhd 𝕜 g s := fun z hz => (hf z hz).congr (mem_nhdsSet_iff_forall.mp hg z hz) -theorem analyticOn_congr' (h : f =ᶠ[𝓝ˢ s] g) : AnalyticOn 𝕜 f s ↔ AnalyticOn 𝕜 g s := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.congr' := AnalyticOnNhd.congr' + +theorem analyticOnNhd_congr' (h : f =ᶠ[𝓝ˢ s] g) : AnalyticOnNhd 𝕜 f s ↔ AnalyticOnNhd 𝕜 g s := ⟨fun hf => hf.congr' h, fun hg => hg.congr' h.symm⟩ -theorem AnalyticOn.congr (hs : IsOpen s) (hf : AnalyticOn 𝕜 f s) (hg : s.EqOn f g) : - AnalyticOn 𝕜 g s := +@[deprecated (since := "2024-09-26")] +alias analyticOn_congr' := analyticOnNhd_congr' + +theorem AnalyticOnNhd.congr (hs : IsOpen s) (hf : AnalyticOnNhd 𝕜 f s) (hg : s.EqOn f g) : + AnalyticOnNhd 𝕜 g s := hf.congr' <| mem_nhdsSet_iff_forall.mpr (fun _ hz => eventuallyEq_iff_exists_mem.mpr ⟨s, hs.mem_nhds hz, hg⟩) -theorem analyticOn_congr (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOn 𝕜 f s ↔ - AnalyticOn 𝕜 g s := ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ +theorem analyticOnNhd_congr (hs : IsOpen s) (h : s.EqOn f g) : AnalyticOnNhd 𝕜 f s ↔ + AnalyticOnNhd 𝕜 g s := ⟨fun hf => hf.congr hs h, fun hg => hg.congr hs h.symm⟩ + +@[deprecated (since := "2024-09-26")] +alias analyticOn_congr := analyticOnNhd_congr -lemma AnalyticWithinOn.mono {f : E → F} {s t : Set E} (h : AnalyticWithinOn 𝕜 f t) - (hs : s ⊆ t) : AnalyticWithinOn 𝕜 f s := +theorem AnalyticWithinAt.mono_of_mem + (h : AnalyticWithinAt 𝕜 f s x) (hst : s ∈ 𝓝[t] x) : AnalyticWithinAt 𝕜 f t x := by + rcases h with ⟨p, hp⟩ + exact ⟨p, hp.mono_of_mem hst⟩ + +lemma AnalyticOn.mono {f : E → F} {s t : Set E} (h : AnalyticOn 𝕜 f t) + (hs : s ⊆ t) : AnalyticOn 𝕜 f s := fun _ m ↦ (h _ (hs m)).mono hs +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.mono := AnalyticOn.mono + +@[simp] theorem analyticWithinAt_insert {f : E → F} {s : Set E} {x y : E} : + AnalyticWithinAt 𝕜 f (insert y s) x ↔ AnalyticWithinAt 𝕜 f s x := by + simp [AnalyticWithinAt] + /-! ### Composition with linear maps -/ +/-- If a function `f` has a power series `p` on a ball within a set and `g` is linear, +then `g ∘ f` has the power series `g ∘ p` on the same ball. -/ +theorem ContinuousLinearMap.comp_hasFPowerSeriesWithinOnBall (g : F →L[𝕜] G) + (h : HasFPowerSeriesWithinOnBall f p s x r) : + HasFPowerSeriesWithinOnBall (g ∘ f) (g.compFormalMultilinearSeries p) s x r where + r_le := h.r_le.trans (p.radius_le_radius_continuousLinearMap_comp _) + r_pos := h.r_pos + hasSum hy h'y := by + simpa only [ContinuousLinearMap.compFormalMultilinearSeries_apply, + ContinuousLinearMap.compContinuousMultilinearMap_coe, Function.comp_apply] using + g.hasSum (h.hasSum hy h'y) + /-- If a function `f` has a power series `p` on a ball and `g` is linear, then `g ∘ f` has the power series `g ∘ p` on the same ball. -/ theorem ContinuousLinearMap.comp_hasFPowerSeriesOnBall (g : F →L[𝕜] G) (h : HasFPowerSeriesOnBall f p x r) : - HasFPowerSeriesOnBall (g ∘ f) (g.compFormalMultilinearSeries p) x r := - { r_le := h.r_le.trans (p.radius_le_radius_continuousLinearMap_comp _) - r_pos := h.r_pos - hasSum := fun hy => by - simpa only [ContinuousLinearMap.compFormalMultilinearSeries_apply, - ContinuousLinearMap.compContinuousMultilinearMap_coe, Function.comp_apply] using - g.hasSum (h.hasSum hy) } + HasFPowerSeriesOnBall (g ∘ f) (g.compFormalMultilinearSeries p) x r := by + rw [← hasFPowerSeriesWithinOnBall_univ] at h ⊢ + exact g.comp_hasFPowerSeriesWithinOnBall h /-- If a function `f` is analytic on a set `s` and `g` is linear, then `g ∘ f` is analytic on `s`. -/ -theorem ContinuousLinearMap.comp_analyticOn {s : Set E} (g : F →L[𝕜] G) (h : AnalyticOn 𝕜 f s) : +theorem ContinuousLinearMap.comp_analyticOn (g : F →L[𝕜] G) (h : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (g ∘ f) s := by rintro x hx rcases h x hx with ⟨p, r, hp⟩ + exact ⟨g.compFormalMultilinearSeries p, r, g.comp_hasFPowerSeriesWithinOnBall hp⟩ + +/-- If a function `f` is analytic on a set `s` and `g` is linear, then `g ∘ f` is analytic +on `s`. -/ +theorem ContinuousLinearMap.comp_analyticOnNhd + {s : Set E} (g : F →L[𝕜] G) (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (g ∘ f) s := by + rintro x hx + rcases h x hx with ⟨p, r, hp⟩ exact ⟨g.compFormalMultilinearSeries p, r, g.comp_hasFPowerSeriesOnBall hp⟩ /-! @@ -712,6 +822,13 @@ theorem HasFPowerSeriesOnBall.tendsto_partialSum Tendsto (fun n => p.partialSum n y) atTop (𝓝 (f (x + y))) := (hf.hasSum hy).tendsto_sum_nat +theorem HasFPowerSeriesAt.tendsto_partialSum + (hf : HasFPowerSeriesAt f p x) : + ∀ᶠ y in 𝓝 0, Tendsto (fun n => p.partialSum n y) atTop (𝓝 (f (x + y))) := by + rcases hf with ⟨r, hr⟩ + filter_upwards [EMetric.ball_mem_nhds (0 : E) hr.r_pos] with y hy + exact hr.tendsto_partialSum hy + open Finset in /-- If a function admits a power series expansion within a ball, then the partial sums `p.partialSum n z` converge to `f (x + y)` as `n → ∞` and `z → y`. Note that `x + z` doesn't need @@ -808,7 +925,7 @@ theorem HasFPowerSeriesWithinOnBall.uniform_geometric_approx' {r' : ℝ≥0} exact mod_cast yr' rw [norm_sub_rev, ← mul_div_right_comm] have ya : a * (‖y‖ / ↑r') ≤ a := - mul_le_of_le_one_right ha.1.le (div_le_one_of_le yr'.le r'.coe_nonneg) + mul_le_of_le_one_right ha.1.le (div_le_one_of_le₀ yr'.le r'.coe_nonneg) suffices ‖p.partialSum n y - f (x + y)‖ ≤ C * (a * (‖y‖ / r')) ^ n / (1 - a * (‖y‖ / r')) by refine this.trans ?_ have : 0 < a := ha.1 @@ -849,7 +966,7 @@ theorem HasFPowerSeriesWithinOnBall.uniform_geometric_approx {r' : ℝ≥0} 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 - exact 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) /-- If a function admits a power series expansion, then it is exponentially close to the partial sums of this power series on strict subdisks of the disk of convergence. -/ @@ -1164,17 +1281,24 @@ protected theorem AnalyticAt.continuousAt (hf : AnalyticAt 𝕜 f x) : Continuou let ⟨_, hp⟩ := hf hp.continuousAt -protected theorem AnalyticOn.continuousOn {s : Set E} (hf : AnalyticOn 𝕜 f s) : ContinuousOn f s := +protected theorem AnalyticOnNhd.continuousOn {s : Set E} (hf : AnalyticOnNhd 𝕜 f s) : + ContinuousOn f s := fun x hx => (hf x hx).continuousAt.continuousWithinAt -protected lemma AnalyticWithinOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticWithinOn 𝕜 f s) : +protected lemma AnalyticOn.continuousOn {f : E → F} {s : Set E} (h : AnalyticOn 𝕜 f s) : ContinuousOn f s := fun x m ↦ (h x m).continuousWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.continuousOn := AnalyticOn.continuousOn + /-- Analytic everywhere implies continuous -/ -theorem AnalyticOn.continuous {f : E → F} (fa : AnalyticOn 𝕜 f univ) : Continuous f := by +theorem AnalyticOnNhd.continuous {f : E → F} (fa : AnalyticOnNhd 𝕜 f univ) : Continuous f := by rw [continuous_iff_continuousOn_univ]; exact fa.continuousOn +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.continuous := AnalyticOnNhd.continuous + /-- In a complete space, the sum of a converging power series `p` admits `p` as a power series. This is not totally obvious as we need to check the convergence of the series. -/ protected theorem FormalMultilinearSeries.hasFPowerSeriesOnBall [CompleteSpace F] @@ -1186,6 +1310,10 @@ protected theorem FormalMultilinearSeries.hasFPowerSeriesOnBall [CompleteSpace F rw [zero_add] exact p.hasSum hy } +theorem HasFPowerSeriesWithinOnBall.sum (h : HasFPowerSeriesWithinOnBall f p s x r) {y : E} + (h'y : x + y ∈ insert x s) (hy : y ∈ EMetric.ball (0 : E) r) : f (x + y) = p.sum y := + (h.hasSum h'y hy).tsum_eq.symm + theorem HasFPowerSeriesOnBall.sum (h : HasFPowerSeriesOnBall f p x r) {y : E} (hy : y ∈ EMetric.ball (0 : E) r) : f (x + y) = p.sum y := (h.hasSum hy).tsum_eq.symm diff --git a/Mathlib/Analysis/Analytic/CPolynomial.lean b/Mathlib/Analysis/Analytic/CPolynomial.lean index bda50d02ecbfb..9576f0b22c613 100644 --- a/Mathlib/Analysis/Analytic/CPolynomial.lean +++ b/Mathlib/Analysis/Analytic/CPolynomial.lean @@ -29,7 +29,7 @@ for `n : ℕ`, and let `f` be a function from `E` to `F`. 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`. + `CPolynomialAt.analyticAt` and `CPolynomialOn.analyticOnNhd`. * 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 polynomial at @@ -116,9 +116,16 @@ theorem CPolynomialAt.analyticAt (hf : CPolynomialAt 𝕜 f x) : AnalyticAt 𝕜 let ⟨p, _, hp⟩ := hf ⟨p, hp.toHasFPowerSeriesAt⟩ -theorem CPolynomialOn.analyticOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOn 𝕜 f s := +theorem CPolynomialAt.analyticWithinAt {s : Set E} (hf : CPolynomialAt 𝕜 f x) : + AnalyticWithinAt 𝕜 f s x := + hf.analyticAt.analyticWithinAt + +theorem CPolynomialOn.analyticOnNhd {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOnNhd 𝕜 f s := fun x hx ↦ (hf x hx).analyticAt +theorem CPolynomialOn.analyticOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : AnalyticOn 𝕜 f s := + hf.analyticOnNhd.analyticOn + 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⟩ @@ -335,7 +342,7 @@ protected theorem CPolynomialAt.continuousAt (hf : CPolynomialAt 𝕜 f x) : Con protected theorem CPolynomialOn.continuousOn {s : Set E} (hf : CPolynomialOn 𝕜 f s) : ContinuousOn f s := - hf.analyticOn.continuousOn + hf.analyticOnNhd.continuousOn /-- Continuously polynomial everywhere implies continuous -/ theorem CPolynomialOn.continuous {f : E → F} (fa : CPolynomialOn 𝕜 f univ) : Continuous f := by @@ -571,10 +578,12 @@ lemma cpolynomialAt : CPolynomialAt 𝕜 f x := lemma cpolyomialOn : CPolynomialOn 𝕜 f s := fun _ _ ↦ f.cpolynomialAt -lemma analyticOn : AnalyticOn 𝕜 f s := f.cpolyomialOn.analyticOn +lemma analyticOnNhd : AnalyticOnNhd 𝕜 f s := f.cpolyomialOn.analyticOnNhd + +lemma analyticOn : AnalyticOn 𝕜 f s := f.analyticOnNhd.analyticOn -lemma analyticWithinOn : AnalyticWithinOn 𝕜 f s := - f.analyticOn.analyticWithinOn +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := analyticOn lemma analyticAt : AnalyticAt 𝕜 f x := f.cpolynomialAt.analyticAt @@ -624,12 +633,16 @@ lemma cpolyomialOn_uncurry_of_multilinear : CPolynomialOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := fun _ _ ↦ f.cpolynomialAt_uncurry_of_multilinear -lemma analyticOn_uncurry_of_multilinear : AnalyticOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.cpolyomialOn_uncurry_of_multilinear.analyticOn +lemma analyticOnNhd_uncurry_of_multilinear : + AnalyticOnNhd 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := + f.cpolyomialOn_uncurry_of_multilinear.analyticOnNhd -lemma analyticWithinOn_uncurry_of_multilinear : - AnalyticWithinOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.analyticOn_uncurry_of_multilinear.analyticWithinOn +lemma analyticOn_uncurry_of_multilinear : + AnalyticOn 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := + f.analyticOnNhd_uncurry_of_multilinear.analyticOn + +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_uncurry_of_multilinear := analyticOn_uncurry_of_multilinear lemma analyticAt_uncurry_of_multilinear : AnalyticAt 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) x := f.cpolynomialAt_uncurry_of_multilinear.analyticAt @@ -638,20 +651,4 @@ lemma analyticWithinAt_uncurry_of_multilinear : AnalyticWithinAt 𝕜 (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s x := f.analyticAt_uncurry_of_multilinear.analyticWithinAt -lemma continuousOn_uncurry_of_multilinear : - ContinuousOn (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s := - f.analyticOn_uncurry_of_multilinear.continuousOn - -lemma continuous_uncurry_of_multilinear : - Continuous (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) := - f.analyticOn_uncurry_of_multilinear.continuous - -lemma continuousAt_uncurry_of_multilinear : - ContinuousAt (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) x := - f.analyticAt_uncurry_of_multilinear.continuousAt - -lemma continuousWithinAt_uncurry_of_multilinear : - ContinuousWithinAt (fun (p : G × (Π i, Em i)) ↦ f p.1 p.2) s x := - f.analyticWithinAt_uncurry_of_multilinear.continuousWithinAt - end ContinuousLinearMap diff --git a/Mathlib/Analysis/Analytic/ChangeOrigin.lean b/Mathlib/Analysis/Analytic/ChangeOrigin.lean index de0ca613e74d3..ff6fdee77e8d2 100644 --- a/Mathlib/Analysis/Analytic/ChangeOrigin.lean +++ b/Mathlib/Analysis/Analytic/ChangeOrigin.lean @@ -60,7 +60,7 @@ p (k + l) (s.piecewise (fun _ ↦ x) (fun _ ↦ y))` def changeOriginSeriesTerm (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) : E[×l]→L[𝕜] E[×k]→L[𝕜] F := let a := ContinuousMultilinearMap.curryFinFinset 𝕜 E F hs - (by erw [Finset.card_compl, Fintype.card_fin, hs, add_tsub_cancel_right]) + (by rw [Finset.card_compl, Fintype.card_fin, hs, add_tsub_cancel_right]) a (p (k + l)) theorem changeOriginSeriesTerm_apply (k l : ℕ) (s : Finset (Fin (k + l))) (hs : s.card = l) @@ -226,6 +226,12 @@ def derivSeries : FormalMultilinearSeries 𝕜 E (E →L[𝕜] F) := (continuousMultilinearCurryFin1 𝕜 E F : (E[×1]→L[𝕜] F) →L[𝕜] E →L[𝕜] F) |>.compFormalMultilinearSeries (p.changeOriginSeries 1) +theorem radius_le_radius_derivSeries : p.radius ≤ p.derivSeries.radius := by + apply (p.le_changeOriginSeries_radius 1).trans (radius_le_of_le (fun n ↦ ?_)) + apply (ContinuousLinearMap.norm_compContinuousMultilinearMap_le _ _).trans + apply mul_le_of_le_one_left (norm_nonneg _) + exact ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp) + end -- From this point on, assume that the space is complete, to make sure that series that converge @@ -284,44 +290,77 @@ theorem analyticAt_changeOrigin (p : FormalMultilinearSeries 𝕜 E F) (rp : p.r end FormalMultilinearSeries + section -variable [CompleteSpace F] {f : E → F} {p : FormalMultilinearSeries 𝕜 E F} {x y : E} {r : ℝ≥0∞} +variable [CompleteSpace F] {f : E → F} {p : FormalMultilinearSeries 𝕜 E F} {s : Set E} + {x y : E} {r : ℝ≥0∞} + +/-- If a function admits a power series expansion `p` within a set `s` on a ball `B (x, r)`, then +it also admits a power series on any subball of this ball (even with a different center provided +it belongs to `s`), given by `p.changeOrigin`. -/ +theorem HasFPowerSeriesWithinOnBall.changeOrigin (hf : HasFPowerSeriesWithinOnBall f p s x r) + (h : (‖y‖₊ : ℝ≥0∞) < r) (hy : x + y ∈ insert x s) : + HasFPowerSeriesWithinOnBall f (p.changeOrigin y) s (x + y) (r - ‖y‖₊) where + r_le := by + apply le_trans _ p.changeOrigin_radius + exact tsub_le_tsub hf.r_le le_rfl + r_pos := by simp [h] + hasSum {z} h'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 (hz.trans_le hf.r_le), add_assoc, hf.sum] + · have : insert (x + y) s ⊆ insert (x + y) (insert x s) := by + apply insert_subset_insert (subset_insert _ _) + rw [insert_eq_of_mem hy] at this + apply this + simpa [add_assoc] using h'z + 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 + refine EMetric.ball_subset_ball (le_trans ?_ p.changeOrigin_radius) hz + exact tsub_le_tsub hf.r_le le_rfl /-- If a function admits a power series expansion `p` on a ball `B (x, r)`, then it also admits a power series on any subball of this ball (even with a different center), given by `p.changeOrigin`. -/ theorem HasFPowerSeriesOnBall.changeOrigin (hf : HasFPowerSeriesOnBall f p x r) - (h : (‖y‖₊ : ℝ≥0∞) < r) : HasFPowerSeriesOnBall f (p.changeOrigin y) (x + y) (r - ‖y‖₊) := - { r_le := by - apply le_trans _ p.changeOrigin_radius - exact tsub_le_tsub hf.r_le le_rfl - r_pos := by simp [h] - hasSum := fun {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 (hz.trans_le hf.r_le), 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 - refine EMetric.ball_subset_ball (le_trans ?_ p.changeOrigin_radius) hz - exact tsub_le_tsub hf.r_le le_rfl } + (h : (‖y‖₊ : ℝ≥0∞) < r) : HasFPowerSeriesOnBall f (p.changeOrigin y) (x + y) (r - ‖y‖₊) := by + rw [← hasFPowerSeriesWithinOnBall_univ] at hf ⊢ + exact hf.changeOrigin h (by simp) + +/-- If a function admits a power series expansion `p` on an open ball `B (x, r)`, then +it is analytic at every point of this ball. -/ +theorem HasFPowerSeriesWithinOnBall.analyticWithinAt_of_mem + (hf : HasFPowerSeriesWithinOnBall f p s x r) + (h : y ∈ insert x s ∩ EMetric.ball x r) : AnalyticWithinAt 𝕜 f s y := by + have : (‖y - x‖₊ : ℝ≥0∞) < r := by simpa [edist_eq_coe_nnnorm_sub] using h.2 + have := hf.changeOrigin this (by simpa using h.1) + rw [add_sub_cancel] at this + exact this.analyticWithinAt /-- If a function admits a power series expansion `p` on an open ball `B (x, r)`, then it is analytic at every point of this ball. -/ theorem HasFPowerSeriesOnBall.analyticAt_of_mem (hf : HasFPowerSeriesOnBall f p x r) (h : y ∈ EMetric.ball x r) : AnalyticAt 𝕜 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] at this - exact this.analyticAt + rw [← hasFPowerSeriesWithinOnBall_univ] at hf + rw [← analyticWithinAt_univ] + exact hf.analyticWithinAt_of_mem (by simpa using h) + +theorem HasFPowerSeriesWithinOnBall.analyticOn (hf : HasFPowerSeriesWithinOnBall f p s x r) : + AnalyticOn 𝕜 f (insert x s ∩ EMetric.ball x r) := + fun _ hy ↦ ((analyticWithinAt_insert (y := x)).2 (hf.analyticWithinAt_of_mem hy)).mono + inter_subset_left -theorem HasFPowerSeriesOnBall.analyticOn (hf : HasFPowerSeriesOnBall f p x r) : - AnalyticOn 𝕜 f (EMetric.ball x r) := +theorem HasFPowerSeriesOnBall.analyticOnNhd (hf : HasFPowerSeriesOnBall f p x r) : + AnalyticOnNhd 𝕜 f (EMetric.ball x r) := fun _y hy => hf.analyticAt_of_mem hy +@[deprecated (since := "2024-09-26")] +alias HasFPowerSeriesOnBall.analyticOn := HasFPowerSeriesOnBall.analyticOnNhd + variable (𝕜 f) in /-- For any function `f` from a normed vector space to a Banach space, the set of points `x` such that `f` is analytic at `x` is open. -/ @@ -334,13 +373,19 @@ theorem AnalyticAt.eventually_analyticAt (h : AnalyticAt 𝕜 f x) : ∀ᶠ y in 𝓝 x, AnalyticAt 𝕜 f y := (isOpen_analyticAt 𝕜 f).mem_nhds h -theorem AnalyticAt.exists_mem_nhds_analyticOn (h : AnalyticAt 𝕜 f x) : - ∃ s ∈ 𝓝 x, AnalyticOn 𝕜 f s := +theorem AnalyticAt.exists_mem_nhds_analyticOnNhd (h : AnalyticAt 𝕜 f x) : + ∃ s ∈ 𝓝 x, AnalyticOnNhd 𝕜 f s := h.eventually_analyticAt.exists_mem +@[deprecated (since := "2024-09-26")] +alias AnalyticAt.exists_mem_nhds_analyticOn := AnalyticAt.exists_mem_nhds_analyticOnNhd + /-- If we're analytic at a point, we're analytic in a nonempty ball -/ -theorem AnalyticAt.exists_ball_analyticOn (h : AnalyticAt 𝕜 f x) : - ∃ r : ℝ, 0 < r ∧ AnalyticOn 𝕜 f (Metric.ball x r) := +theorem AnalyticAt.exists_ball_analyticOnNhd (h : AnalyticAt 𝕜 f x) : + ∃ r : ℝ, 0 < r ∧ AnalyticOnNhd 𝕜 f (Metric.ball x r) := Metric.isOpen_iff.mp (isOpen_analyticAt _ _) _ h +@[deprecated (since := "2024-09-26")] +alias AnalyticAt.exists_ball_analyticOn := AnalyticAt.exists_ball_analyticOnNhd + end diff --git a/Mathlib/Analysis/Analytic/Composition.lean b/Mathlib/Analysis/Analytic/Composition.lean index a6ee6bbde78ed..c73176c9a5ec5 100644 --- a/Mathlib/Analysis/Analytic/Composition.lean +++ b/Mathlib/Analysis/Analytic/Composition.lean @@ -331,29 +331,34 @@ section variable (𝕜 E) /-- The identity formal multilinear series, with all coefficients equal to `0` except for `n = 1` -where it is (the continuous multilinear version of) the identity. -/ -def id : FormalMultilinearSeries 𝕜 E E - | 0 => 0 +where it is (the continuous multilinear version of) the identity. We allow an arbitrary +constant coefficient `x`. -/ +def id (x : E) : FormalMultilinearSeries 𝕜 E E + | 0 => ContinuousMultilinearMap.uncurry0 𝕜 _ x | 1 => (continuousMultilinearCurryFin1 𝕜 E E).symm (ContinuousLinearMap.id 𝕜 E) | _ => 0 +@[simp] theorem id_apply_zero (x : E) (v : Fin 0 → E) : + (FormalMultilinearSeries.id 𝕜 E x) 0 v = x := rfl + /-- The first coefficient of `id 𝕜 E` is the identity. -/ @[simp] -theorem id_apply_one (v : Fin 1 → E) : (FormalMultilinearSeries.id 𝕜 E) 1 v = v 0 := +theorem id_apply_one (x : E) (v : Fin 1 → E) : (FormalMultilinearSeries.id 𝕜 E x) 1 v = v 0 := rfl /-- The `n`th coefficient of `id 𝕜 E` is the identity when `n = 1`. We state this in a dependent way, as it will often appear in this form. -/ -theorem id_apply_one' {n : ℕ} (h : n = 1) (v : Fin n → E) : - (id 𝕜 E) n v = v ⟨0, h.symm ▸ zero_lt_one⟩ := by +theorem id_apply_one' (x : E) {n : ℕ} (h : n = 1) (v : Fin n → E) : + (id 𝕜 E x) n v = v ⟨0, h.symm ▸ zero_lt_one⟩ := by subst n apply id_apply_one /-- For `n ≠ 1`, the `n`-th coefficient of `id 𝕜 E` is zero, by definition. -/ @[simp] -theorem id_apply_ne_one {n : ℕ} (h : n ≠ 1) : (FormalMultilinearSeries.id 𝕜 E) n = 0 := by +theorem id_apply_of_one_lt (x : E) {n : ℕ} (h : 1 < n) : + (FormalMultilinearSeries.id 𝕜 E x) n = 0 := by cases' n with n - · rfl + · contradiction · cases n · contradiction · rfl @@ -361,11 +366,11 @@ theorem id_apply_ne_one {n : ℕ} (h : n ≠ 1) : (FormalMultilinearSeries.id end @[simp] -theorem comp_id (p : FormalMultilinearSeries 𝕜 E F) : p.comp (id 𝕜 E) = p := by +theorem comp_id (p : FormalMultilinearSeries 𝕜 E F) (x : E) : p.comp (id 𝕜 E x) = p := by ext1 n dsimp [FormalMultilinearSeries.comp] rw [Finset.sum_eq_single (Composition.ones n)] - · show compAlongComposition p (id 𝕜 E) (Composition.ones n) = p n + · show compAlongComposition p (id 𝕜 E x) (Composition.ones n) = p n ext v rw [compAlongComposition_apply] apply p.congr (Composition.ones_length n) @@ -375,50 +380,60 @@ theorem comp_id (p : FormalMultilinearSeries 𝕜 E F) : p.comp (id 𝕜 E) = p rw [Fin.ext_iff, Fin.coe_castLE, Fin.val_mk] · show ∀ b : Composition n, - b ∈ Finset.univ → b ≠ Composition.ones n → compAlongComposition p (id 𝕜 E) b = 0 + b ∈ Finset.univ → b ≠ Composition.ones n → compAlongComposition p (id 𝕜 E x) b = 0 intro b _ hb obtain ⟨k, hk, lt_k⟩ : ∃ (k : ℕ), k ∈ Composition.blocks b ∧ 1 < k := Composition.ne_ones_iff.1 hb obtain ⟨i, hi⟩ : ∃ (i : Fin b.blocks.length), b.blocks[i] = k := List.get_of_mem hk - let j : Fin b.length := ⟨i.val, b.blocks_length ▸ i.prop⟩ have A : 1 < b.blocksFun j := by convert lt_k ext v rw [compAlongComposition_apply, ContinuousMultilinearMap.zero_apply] apply ContinuousMultilinearMap.map_coord_zero _ j dsimp [applyComposition] - rw [id_apply_ne_one _ _ (ne_of_gt A)] + rw [id_apply_of_one_lt _ _ _ A] rfl · simp @[simp] -theorem id_comp (p : FormalMultilinearSeries 𝕜 E F) (h : p 0 = 0) : (id 𝕜 F).comp p = p := by +theorem id_comp (p : FormalMultilinearSeries 𝕜 E F) (v0 : Fin 0 → E) : + (id 𝕜 F (p 0 v0)).comp p = p := by ext1 n by_cases hn : n = 0 - · rw [hn, h] + · rw [hn] ext v - rw [comp_coeff_zero', id_apply_ne_one _ _ zero_ne_one] - rfl + simp only [comp_coeff_zero', id_apply_zero] + congr with i + exact i.elim0 · dsimp [FormalMultilinearSeries.comp] have n_pos : 0 < n := bot_lt_iff_ne_bot.mpr hn rw [Finset.sum_eq_single (Composition.single n n_pos)] - · show compAlongComposition (id 𝕜 F) p (Composition.single n n_pos) = p n + · show compAlongComposition (id 𝕜 F (p 0 v0)) p (Composition.single n n_pos) = p n ext v - rw [compAlongComposition_apply, id_apply_one' _ _ (Composition.single_length n_pos)] + rw [compAlongComposition_apply, id_apply_one' _ _ _ (Composition.single_length n_pos)] dsimp [applyComposition] refine p.congr rfl fun i him hin => congr_arg v <| ?_ ext; simp · show - ∀ b : Composition n, - b ∈ Finset.univ → b ≠ Composition.single n n_pos → compAlongComposition (id 𝕜 F) p b = 0 + ∀ b : Composition n, b ∈ Finset.univ → b ≠ Composition.single n n_pos → + compAlongComposition (id 𝕜 F (p 0 v0)) p b = 0 intro b _ hb - have A : b.length ≠ 1 := by simpa [Composition.eq_single_iff_length] using hb + have A : 1 < b.length := by + have : b.length ≠ 1 := by simpa [Composition.eq_single_iff_length] using hb + have : 0 < b.length := Composition.length_pos_of_pos b n_pos + omega ext v - rw [compAlongComposition_apply, id_apply_ne_one _ _ A] + rw [compAlongComposition_apply, id_apply_of_one_lt _ _ _ A] rfl · simp +/-- Variant of `id_comp` in which the zero coefficient is given by an equality hypothesis instead +of a definitional equality. Useful for rewriting or simplifying out in some situations. -/ +theorem id_comp' (p : FormalMultilinearSeries 𝕜 E F) (x : F) (v0 : Fin 0 → E) (h : x = p 0 v0) : + (id 𝕜 F x).comp p = p := by + simp [h] + /-! ### Summability properties of the composition of formal power series -/ @@ -458,7 +473,7 @@ theorem comp_summable_nnreal (q : FormalMultilinearSeries 𝕜 F G) (p : FormalM simp only [Finset.prod_mul_distrib, Finset.prod_pow_eq_pow_sum, c.sum_blocksFun] _ ≤ ∏ _i : Fin c.length, Cp := Finset.prod_le_prod' fun i _ => hCp _ _ = Cp ^ c.length := by simp - _ ≤ Cp ^ n := pow_le_pow_right hCp1 c.length_le + _ ≤ Cp ^ n := pow_right_mono₀ hCp1 c.length_le calc ‖q.compAlongComposition p c‖₊ * r ^ n ≤ (‖q c.length‖₊ * ∏ i, ‖p (c.blocksFun i)‖₊) * r ^ n := @@ -634,11 +649,12 @@ theorem compChangeOfVariables_sum {α : Type*} [AddCommMonoid α] (m M N : ℕ) /-- The auxiliary set corresponding to the composition of partial sums asymptotically contains all possible compositions. -/ -theorem compPartialSumTarget_tendsto_atTop : - Tendsto (fun N => compPartialSumTarget 0 N N) atTop atTop := by +theorem compPartialSumTarget_tendsto_prod_atTop : + Tendsto (fun (p : ℕ × ℕ) => compPartialSumTarget 0 p.1 p.2) atTop atTop := by apply Monotone.tendsto_atTop_finset · intro m n hmn a ha - have : ∀ i, i < m → i < n := fun i hi => lt_of_lt_of_le hi hmn + have : ∀ i, i < m.1 → i < n.1 := fun i hi => lt_of_lt_of_le hi hmn.1 + have : ∀ i, i < m.2 → i < n.2 := fun i hi => lt_of_lt_of_le hi hmn.2 aesop · rintro ⟨n, c⟩ simp only [mem_compPartialSumTarget_iff] @@ -650,29 +666,35 @@ theorem compPartialSumTarget_tendsto_atTop : apply hn simp only [Finset.mem_image_of_mem, Finset.mem_coe, Finset.mem_univ] +/-- The auxiliary set corresponding to the composition of partial sums asymptotically contains +all possible compositions. -/ +theorem compPartialSumTarget_tendsto_atTop : + Tendsto (fun N => compPartialSumTarget 0 N N) atTop atTop := by + apply Tendsto.comp compPartialSumTarget_tendsto_prod_atTop tendsto_atTop_diagonal + /-- Composing the partial sums of two multilinear series coincides with the sum over all compositions in `compPartialSumTarget 0 N N`. This is precisely the motivation for the definition of `compPartialSumTarget`. -/ theorem comp_partialSum (q : FormalMultilinearSeries 𝕜 F G) (p : FormalMultilinearSeries 𝕜 E F) - (N : ℕ) (z : E) : - q.partialSum N (∑ i ∈ Finset.Ico 1 N, p i fun _j => z) = - ∑ i ∈ compPartialSumTarget 0 N N, q.compAlongComposition p i.2 fun _j => z := by + (M N : ℕ) (z : E) : + q.partialSum M (∑ i ∈ Finset.Ico 1 N, p i fun _j => z) = + ∑ i ∈ compPartialSumTarget 0 M N, q.compAlongComposition p i.2 fun _j => z := by -- we expand the composition, using the multilinearity of `q` to expand along each coordinate. suffices H : - (∑ n ∈ Finset.range N, + (∑ n ∈ Finset.range M, ∑ r ∈ Fintype.piFinset fun i : Fin n => Finset.Ico 1 N, q n fun i : Fin n => p (r i) fun _j => z) = - ∑ i ∈ compPartialSumTarget 0 N N, q.compAlongComposition p i.2 fun _j => z by + ∑ i ∈ compPartialSumTarget 0 M N, q.compAlongComposition p i.2 fun _j => z by simpa only [FormalMultilinearSeries.partialSum, ContinuousMultilinearMap.map_sum_finset] using H -- rewrite the first sum as a big sum over a sigma type, in the finset -- `compPartialSumTarget 0 N N` rw [Finset.range_eq_Ico, Finset.sum_sigma'] -- use `compChangeOfVariables_sum`, saying that this change of variables respects sums - apply compChangeOfVariables_sum 0 N N + apply compChangeOfVariables_sum 0 M N rintro ⟨k, blocks_fun⟩ H - apply congr _ (compChangeOfVariables_length 0 N N H).symm + apply congr _ (compChangeOfVariables_length 0 M N H).symm intros - rw [← compChangeOfVariables_blocksFun 0 N N H] + rw [← compChangeOfVariables_blocksFun 0 M N H] rfl end FormalMultilinearSeries @@ -830,11 +852,14 @@ theorem AnalyticWithinAt.comp_of_eq {g : F → G} {f : E → F} {y : F} {x : E} rw [← hy] at hg exact hg.comp hf h -lemma AnalyticWithinOn.comp {f : F → G} {g : E → F} {s : Set F} - {t : Set E} (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g t) (h : Set.MapsTo g t s) : - AnalyticWithinOn 𝕜 (f ∘ g) t := +lemma AnalyticOn.comp {f : F → G} {g : E → F} {s : Set F} + {t : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g t) (h : Set.MapsTo g t s) : + AnalyticOn 𝕜 (f ∘ g) t := fun x m ↦ (hf _ (h m)).comp (hg x m) h +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.comp := AnalyticOn.comp + /-- If two functions `g` and `f` are analytic respectively at `f x` and `x`, then `g ∘ f` is analytic at `x`. -/ theorem AnalyticAt.comp {g : F → G} {f : E → F} {x : E} (hg : AnalyticAt 𝕜 g (f x)) @@ -862,19 +887,26 @@ theorem AnalyticAt.comp_analyticWithinAt_of_eq {g : F → G} {f : E → F} {x : /-- If two functions `g` and `f` are analytic respectively on `s.image f` and `s`, then `g ∘ f` is analytic on `s`. -/ -theorem AnalyticOn.comp' {s : Set E} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g (s.image f)) - (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (g ∘ f) s := +theorem AnalyticOnNhd.comp' {s : Set E} {g : F → G} {f : E → F} (hg : AnalyticOnNhd 𝕜 g (s.image f)) + (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOnNhd 𝕜 (g ∘ f) s := fun z hz => (hg (f z) (Set.mem_image_of_mem f hz)).comp (hf z hz) -theorem AnalyticOn.comp {s : Set E} {t : Set F} {g : F → G} {f : E → F} (hg : AnalyticOn 𝕜 g t) - (hf : AnalyticOn 𝕜 f s) (st : Set.MapsTo f s t) : AnalyticOn 𝕜 (g ∘ f) s := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.comp' := AnalyticOnNhd.comp' + +theorem AnalyticOnNhd.comp {s : Set E} {t : Set F} {g : F → G} {f : E → F} + (hg : AnalyticOnNhd 𝕜 g t) (hf : AnalyticOnNhd 𝕜 f s) (st : Set.MapsTo f s t) : + AnalyticOnNhd 𝕜 (g ∘ f) s := comp' (mono hg (Set.mapsTo'.mp st)) hf -lemma AnalyticOn.comp_analyticWithinOn {f : F → G} {g : E → F} {s : Set F} - {t : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g t) (h : Set.MapsTo g t s) : - AnalyticWithinOn 𝕜 (f ∘ g) t := +lemma AnalyticOnNhd.comp_analyticOn {f : F → G} {g : E → F} {s : Set F} + {t : Set E} (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOn 𝕜 g t) (h : Set.MapsTo g t s) : + AnalyticOn 𝕜 (f ∘ g) t := fun x m ↦ (hf _ (h m)).comp_analyticWithinAt (hg x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.comp_analyticWithinOn := AnalyticOnNhd.comp_analyticOn + /-! ### Associativity of the composition of formal multilinear series @@ -1011,7 +1043,7 @@ def sigmaCompositionAux (a : Composition n) (b : Composition a.length) a.blocks_pos (by rw [← a.blocks.join_splitWrtComposition b] - exact mem_join_of_mem (List.getElem_mem _ _ _) hi) + exact mem_join_of_mem (List.getElem_mem _) hi) blocks_sum := by simp [Composition.blocksFun, getElem_map, Composition.gather] theorem length_sigmaCompositionAux (a : Composition n) (b : Composition a.length) @@ -1077,7 +1109,7 @@ theorem sizeUpTo_sizeUpTo_add (a : Composition n) (b : Composition a.length) {i have : sizeUpTo b i + Nat.succ j = (sizeUpTo b i + j).succ := rfl rw [this, sizeUpTo_succ _ D, IHj A, sizeUpTo_succ _ B] simp only [sigmaCompositionAux, add_assoc, add_left_inj, Fin.val_mk] - rw [getElem_of_eq (getElem_splitWrtComposition _ _ _ _), getElem_drop, getElem_take _ _ C] + rw [getElem_of_eq (getElem_splitWrtComposition _ _ _ _), getElem_drop, getElem_take' _ _ C] /-- Natural equivalence between `(Σ (a : Composition n), Composition a.length)` and `(Σ (c : Composition n), Π (i : Fin c.length), Composition (c.blocksFun i))`, that shows up as a @@ -1148,7 +1180,7 @@ def sigmaEquivSigmaPi (n : ℕ) : · intro i dsimp [Composition.sigmaCompositionAux] rw [getElem_of_eq (splitWrtComposition_join _ _ _)] - · simp only [getElem_ofFn] + · simp only [List.getElem_ofFn] · simp only [map_ofFn] rfl · congr diff --git a/Mathlib/Analysis/Analytic/Constructions.lean b/Mathlib/Analysis/Analytic/Constructions.lean index 5b268c5b5d826..42de038a5780f 100644 --- a/Mathlib/Analysis/Analytic/Constructions.lean +++ b/Mathlib/Analysis/Analytic/Constructions.lean @@ -48,14 +48,17 @@ theorem hasFPowerSeriesAt_const {c : F} {e : E} : theorem analyticAt_const {v : F} {x : E} : AnalyticAt 𝕜 (fun _ => v) x := ⟨constFormalMultilinearSeries 𝕜 E v, hasFPowerSeriesAt_const⟩ -theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := +theorem analyticOnNhd_const {v : F} {s : Set E} : AnalyticOnNhd 𝕜 (fun _ => v) s := fun _ _ => analyticAt_const theorem analyticWithinAt_const {v : F} {s : Set E} {x : E} : AnalyticWithinAt 𝕜 (fun _ => v) s x := analyticAt_const.analyticWithinAt -theorem analyticWithinOn_const {v : F} {s : Set E} : AnalyticWithinOn 𝕜 (fun _ => v) s := - analyticOn_const.analyticWithinOn +theorem analyticOn_const {v : F} {s : Set E} : AnalyticOn 𝕜 (fun _ => v) s := + analyticOnNhd_const.analyticOn + +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_const := analyticOn_const /-! ### Addition, negation, subtraction @@ -159,28 +162,37 @@ theorem AnalyticAt.sub (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : AnalyticAt 𝕜 (f - g) x := by simpa only [sub_eq_add_neg] using hf.add hg.neg -theorem AnalyticWithinOn.add (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f + g) s := - fun z hz => (hf z hz).add (hg z hz) - theorem AnalyticOn.add (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (f + g) s := fun z hz => (hf z hz).add (hg z hz) -theorem AnalyticWithinOn.neg (hf : AnalyticWithinOn 𝕜 f s) : AnalyticWithinOn 𝕜 (-f) s := - fun z hz ↦ (hf z hz).neg +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.add := AnalyticOn.add + +theorem AnalyticOnNhd.add (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (f + g) s := + fun z hz => (hf z hz).add (hg z hz) theorem AnalyticOn.neg (hf : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (-f) s := fun z hz ↦ (hf z hz).neg -theorem AnalyticWithinOn.sub (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (f - g) s := - fun z hz => (hf z hz).sub (hg z hz) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.neg := AnalyticOn.neg + +theorem AnalyticOnNhd.neg (hf : AnalyticOnNhd 𝕜 f s) : AnalyticOnNhd 𝕜 (-f) s := + fun z hz ↦ (hf z hz).neg theorem AnalyticOn.sub (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (f - g) s := fun z hz => (hf z hz).sub (hg z hz) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.sub := AnalyticOn.sub + +theorem AnalyticOnNhd.sub (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (f - g) s := + fun z hz => (hf z hz).sub (hg z hz) + end /-! @@ -270,17 +282,20 @@ lemma AnalyticAt.prod {e : E} {f : E → F} {g : E → G} exact ⟨_, hf.prod hg⟩ /-- The Cartesian product of analytic functions within a set is analytic. -/ -lemma AnalyticWithinOn.prod {f : E → F} {g : E → G} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ (f x, g x)) s := - fun x hx ↦ (hf x hx).prod (hg x hx) - -/-- The Cartesian product of analytic functions is analytic. -/ lemma AnalyticOn.prod {f : E → F} {g : E → G} {s : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : AnalyticOn 𝕜 (fun x ↦ (f x, g x)) s := fun x hx ↦ (hf x hx).prod (hg x hx) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.prod := AnalyticOn.prod + +/-- The Cartesian product of analytic functions is analytic. -/ +lemma AnalyticOnNhd.prod {f : E → F} {g : E → G} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ (f x, g x)) s := + fun x hx ↦ (hf x hx).prod (hg x hx) + /-- `AnalyticAt.comp` for functions on product spaces -/ theorem AnalyticAt.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {x : E} (ha : AnalyticAt 𝕜 h (f x, g x)) (fa : AnalyticAt 𝕜 f x) @@ -304,20 +319,23 @@ theorem AnalyticAt.comp₂_analyticWithinAt AnalyticWithinAt 𝕜 (fun x ↦ h (f x, g x)) s x := AnalyticAt.comp_analyticWithinAt ha (fa.prod ga) -/-- `AnalyticOn.comp` for functions on product spaces -/ -theorem AnalyticOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} - (ha : AnalyticOn 𝕜 h s) (fa : AnalyticOn 𝕜 f t) (ga : AnalyticOn 𝕜 g t) - (m : ∀ x, x ∈ t → (f x, g x) ∈ s) : AnalyticOn 𝕜 (fun x ↦ h (f x, g x)) t := +/-- `AnalyticOnNhd.comp` for functions on product spaces -/ +theorem AnalyticOnNhd.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} + (ha : AnalyticOnNhd 𝕜 h s) (fa : AnalyticOnNhd 𝕜 f t) (ga : AnalyticOnNhd 𝕜 g t) + (m : ∀ x, x ∈ t → (f x, g x) ∈ s) : AnalyticOnNhd 𝕜 (fun x ↦ h (f x, g x)) t := fun _ xt ↦ (ha _ (m _ xt)).comp₂ (fa _ xt) (ga _ xt) -/-- `AnalyticWithinOn.comp` for functions on product spaces -/ -theorem AnalyticWithinOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} +/-- `AnalyticOn.comp` for functions on product spaces -/ +theorem AnalyticOn.comp₂ {h : F × G → H} {f : E → F} {g : E → G} {s : Set (F × G)} {t : Set E} - (ha : AnalyticWithinOn 𝕜 h s) (fa : AnalyticWithinOn 𝕜 f t) - (ga : AnalyticWithinOn 𝕜 g t) (m : Set.MapsTo (fun y ↦ (f y, g y)) t s) : - AnalyticWithinOn 𝕜 (fun x ↦ h (f x, g x)) t := + (ha : AnalyticOn 𝕜 h s) (fa : AnalyticOn 𝕜 f t) + (ga : AnalyticOn 𝕜 g t) (m : Set.MapsTo (fun y ↦ (f y, g y)) t s) : + AnalyticOn 𝕜 (fun x ↦ h (f x, g x)) t := fun x hx ↦ (ha _ (m hx)).comp₂ (fa x hx) (ga x hx) m +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.comp₂ := AnalyticOn.comp₂ + /-- Analytic functions on products are analytic in the first coordinate -/ theorem AnalyticAt.curry_left {f : E × F → G} {p : E × F} (fa : AnalyticAt 𝕜 f p) : AnalyticAt 𝕜 (fun x ↦ f (x, p.2)) p.1 := @@ -341,27 +359,41 @@ theorem AnalyticWithinAt.curry_right AnalyticWithinAt.comp₂ fa analyticWithinAt_const analyticWithinAt_id (fun _ hx ↦ hx) /-- Analytic functions on products are analytic in the first coordinate -/ -theorem AnalyticOn.curry_left {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := +theorem AnalyticOnNhd.curry_left {f : E × F → G} {s : Set (E × F)} {y : F} + (fa : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := fun x m ↦ (fa (x, y) m).curry_left -alias AnalyticOn.along_fst := AnalyticOn.curry_left +alias AnalyticOnNhd.along_fst := AnalyticOnNhd.curry_left + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.along_fst := AnalyticOnNhd.curry_left -theorem AnalyticWithinOn.curry_left - {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticWithinOn 𝕜 f s) : - AnalyticWithinOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := +theorem AnalyticOn.curry_left + {f : E × F → G} {s : Set (E × F)} {y : F} (fa : AnalyticOn 𝕜 f s) : + AnalyticOn 𝕜 (fun x ↦ f (x, y)) {x | (x, y) ∈ s} := fun x m ↦ (fa (x, y) m).curry_left +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.curry_left := AnalyticOn.curry_left + /-- Analytic functions on products are analytic in the second coordinate -/ -theorem AnalyticOn.curry_right {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := +theorem AnalyticOnNhd.curry_right {f : E × F → G} {x : E} {s : Set (E × F)} + (fa : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := fun y m ↦ (fa (x, y) m).curry_right -alias AnalyticOn.along_snd := AnalyticOn.curry_right +alias AnalyticOnNhd.along_snd := AnalyticOnNhd.curry_right + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.along_snd := AnalyticOnNhd.curry_right -theorem AnalyticWithinOn.curry_right - {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticWithinOn 𝕜 f s) : - AnalyticWithinOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := +theorem AnalyticOn.curry_right + {f : E × F → G} {x : E} {s : Set (E × F)} (fa : AnalyticOn 𝕜 f s) : + AnalyticOn 𝕜 (fun y ↦ f (x, y)) {y | (x, y) ∈ s} := fun y m ↦ (fa (x, y) m).curry_right +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.curry_right := AnalyticOn.curry_right + /-! ### Analyticity in Pi spaces @@ -491,20 +523,26 @@ lemma analyticAt_pi_iff : simp_rw [← analyticWithinAt_univ] exact analyticWithinAt_pi_iff -lemma AnalyticWithinOn.pi (hf : ∀ i, AnalyticWithinOn 𝕜 (f i) s) : - AnalyticWithinOn 𝕜 (fun x ↦ (f · x)) s := +lemma AnalyticOn.pi (hf : ∀ i, AnalyticOn 𝕜 (f i) s) : + AnalyticOn 𝕜 (fun x ↦ (f · x)) s := fun x hx ↦ AnalyticWithinAt.pi (fun i ↦ hf i x hx) -lemma analyticWithinOn_pi_iff : - AnalyticWithinOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticWithinOn 𝕜 (f i) s := +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.pi := AnalyticOn.pi + +lemma analyticOn_pi_iff : + AnalyticOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOn 𝕜 (f i) s := ⟨fun h i x hx ↦ analyticWithinAt_pi_iff.1 (h x hx) i, fun h ↦ .pi h⟩ -lemma AnalyticOn.pi (hf : ∀ i, AnalyticOn 𝕜 (f i) s) : - AnalyticOn 𝕜 (fun x ↦ (f · x)) s := +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_pi_iff := analyticOn_pi_iff + +lemma AnalyticOnNhd.pi (hf : ∀ i, AnalyticOnNhd 𝕜 (f i) s) : + AnalyticOnNhd 𝕜 (fun x ↦ (f · x)) s := fun x hx ↦ AnalyticAt.pi (fun i ↦ hf i x hx) -lemma analyticOn_pi_iff : - AnalyticOn 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOn 𝕜 (f i) s := +lemma analyticOnNhd_pi_iff : + AnalyticOnNhd 𝕜 (fun x ↦ (f · x)) s ↔ ∀ i, AnalyticOnNhd 𝕜 (f i) s := ⟨fun h i x hx ↦ analyticAt_pi_iff.1 (h x hx) i, fun h ↦ .pi h⟩ end @@ -540,16 +578,19 @@ lemma AnalyticAt.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E (analyticAt_smul _).comp₂ hf hg /-- Scalar multiplication of one analytic function by another. -/ -lemma AnalyticWithinOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] +lemma AnalyticOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ f x • g x) s := + (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (fun x ↦ f x • g x) s := fun _ m ↦ (hf _ m).smul (hg _ m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.smul := AnalyticOn.smul + /-- Scalar multiplication of one analytic function by another. -/ -lemma AnalyticOn.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} - (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (fun x ↦ f x • g x) s := +lemma AnalyticOnNhd.smul [NormedSpace 𝕝 F] [IsScalarTower 𝕜 𝕝 F] {f : E → 𝕝} {g : E → F} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ f x • g x) s := fun _ m ↦ (hf _ m).smul (hg _ m) /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ @@ -564,14 +605,18 @@ lemma AnalyticAt.mul {f g : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (hg : An (analyticAt_mul _).comp₂ hf hg /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ -lemma AnalyticWithinOn.mul {f g : E → A} {s : Set E} - (hf : AnalyticWithinOn 𝕜 f s) (hg : AnalyticWithinOn 𝕜 g s) : - AnalyticWithinOn 𝕜 (fun x ↦ f x * g x) s := +lemma AnalyticOn.mul {f g : E → A} {s : Set E} + (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : + AnalyticOn 𝕜 (fun x ↦ f x * g x) s := fun _ m ↦ (hf _ m).mul (hg _ m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.mul := AnalyticOn.mul + /-- Multiplication of analytic functions (valued in a normed `𝕜`-algebra) is analytic. -/ -lemma AnalyticOn.mul {f g : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (hg : AnalyticOn 𝕜 g s) : - AnalyticOn 𝕜 (fun x ↦ f x * g x) s := +lemma AnalyticOnNhd.mul {f g : E → A} {s : Set E} + (hf : AnalyticOnNhd 𝕜 f s) (hg : AnalyticOnNhd 𝕜 g s) : + AnalyticOnNhd 𝕜 (fun x ↦ f x * g x) s := fun _ m ↦ (hf _ m).mul (hg _ m) /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ @@ -592,15 +637,73 @@ lemma AnalyticAt.pow {f : E → A} {z : E} (hf : AnalyticAt 𝕜 f z) (n : ℕ) exact hf.pow n /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ -lemma AnalyticWithinOn.pow {f : E → A} {s : Set E} (hf : AnalyticWithinOn 𝕜 f s) (n : ℕ) : - AnalyticWithinOn 𝕜 (fun x ↦ f x ^ n) s := +lemma AnalyticOn.pow {f : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (n : ℕ) : + AnalyticOn 𝕜 (fun x ↦ f x ^ n) s := fun _ m ↦ (hf _ m).pow n +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.pow := AnalyticOn.pow + /-- Powers of analytic functions (into a normed `𝕜`-algebra) are analytic. -/ -lemma AnalyticOn.pow {f : E → A} {s : Set E} (hf : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (fun x ↦ f x ^ n) s := +lemma AnalyticOnNhd.pow {f : E → A} {s : Set E} (hf : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (fun x ↦ f x ^ n) s := fun _ m ↦ (hf _ m).pow n + +/-! +### Restriction of scalars +-/ + +section + +variable {𝕜' : Type*} [NontriviallyNormedField 𝕜'] [NormedAlgebra 𝕜 𝕜'] + [NormedSpace 𝕜' E] [IsScalarTower 𝕜 𝕜' E] + [NormedSpace 𝕜' F] [IsScalarTower 𝕜 𝕜' F] + {f : E → F} {p : FormalMultilinearSeries 𝕜' E F} {x : E} {s : Set E} {r : ℝ≥0∞} + +lemma HasFPowerSeriesWithinOnBall.restrictScalars (hf : HasFPowerSeriesWithinOnBall f p s x r) : + HasFPowerSeriesWithinOnBall f (p.restrictScalars 𝕜) s x r := + ⟨hf.r_le.trans (FormalMultilinearSeries.radius_le_of_le (fun n ↦ by simp)), hf.r_pos, hf.hasSum⟩ + +lemma HasFPowerSeriesOnBall.restrictScalars (hf : HasFPowerSeriesOnBall f p x r) : + HasFPowerSeriesOnBall f (p.restrictScalars 𝕜) x r := + ⟨hf.r_le.trans (FormalMultilinearSeries.radius_le_of_le (fun n ↦ by simp)), hf.r_pos, hf.hasSum⟩ + +lemma HasFPowerSeriesWithinAt.restrictScalars (hf : HasFPowerSeriesWithinAt f p s x) : + HasFPowerSeriesWithinAt f (p.restrictScalars 𝕜) s x := by + rcases hf with ⟨r, hr⟩ + exact ⟨r, hr.restrictScalars⟩ + +lemma HasFPowerSeriesAt.restrictScalars (hf : HasFPowerSeriesAt f p x) : + HasFPowerSeriesAt f (p.restrictScalars 𝕜) x := by + rcases hf with ⟨r, hr⟩ + exact ⟨r, hr.restrictScalars⟩ + +lemma AnalyticWithinAt.restrictScalars (hf : AnalyticWithinAt 𝕜' f s x) : + AnalyticWithinAt 𝕜 f s x := by + rcases hf with ⟨p, hp⟩ + exact ⟨p.restrictScalars 𝕜, hp.restrictScalars⟩ + +lemma AnalyticAt.restrictScalars (hf : AnalyticAt 𝕜' f x) : + AnalyticAt 𝕜 f x := by + rcases hf with ⟨p, hp⟩ + exact ⟨p.restrictScalars 𝕜, hp.restrictScalars⟩ + +lemma AnalyticOn.restrictScalars (hf : AnalyticOn 𝕜' f s) : + AnalyticOn 𝕜 f s := + fun x hx ↦ (hf x hx).restrictScalars + +lemma AnalyticOnNhd.restrictScalars (hf : AnalyticOnNhd 𝕜' f s) : + AnalyticOnNhd 𝕜 f s := + fun x hx ↦ (hf x hx).restrictScalars + +end + + +/-! +### Inversion is analytic +-/ + section Geometric variable (𝕜 A : Type*) [NontriviallyNormedField 𝕜] [NormedRing A] [NormedAlgebra 𝕜 A] @@ -631,7 +734,7 @@ lemma one_le_formalMultilinearSeries_geometric_radius (𝕜 : Type*) [Nontrivial apply le_trans ?_ (formalMultilinearSeries_geometric_apply_norm_le 𝕜 A n) conv_rhs => rw [← mul_one (‖formalMultilinearSeries_geometric 𝕜 A n‖)] gcongr - exact pow_le_one _ (coe_nonneg r) hr.le + exact pow_le_one₀ (coe_nonneg r) hr.le lemma formalMultilinearSeries_geometric_radius (𝕜 : Type*) [NontriviallyNormedField 𝕜] (A : Type*) [NormedRing A] [NormOneClass A] [NormedAlgebra 𝕜 A] : @@ -657,7 +760,7 @@ lemma formalMultilinearSeries_geometric_radius (𝕜 : Type*) [NontriviallyNorme simp_rw [formalMultilinearSeries_geometric_apply_norm, one_mul] refine isBigO_of_le atTop (fun n ↦ ?_) rw [norm_one, Real.norm_of_nonneg (pow_nonneg (coe_nonneg r) _)] - exact pow_le_one _ (coe_nonneg r) hr.le + exact pow_le_one₀ (coe_nonneg r) hr.le lemma hasFPowerSeriesOnBall_inverse_one_sub (𝕜 : Type*) [NontriviallyNormedField 𝕜] @@ -709,6 +812,11 @@ lemma analyticAt_inverse {𝕜 : Type*} [NontriviallyNormedField 𝕜] exact analyticAt_inverse_one_sub 𝕜 A · exact analyticAt_const.sub (analyticAt_const.mul analyticAt_id) +lemma analyticOnNhd_inverse {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {A : Type*} [NormedRing A] [NormedAlgebra 𝕜 A] [HasSummableGeomSeries A] : + AnalyticOnNhd 𝕜 Ring.inverse {x : A | IsUnit x} := + fun _ hx ↦ analyticAt_inverse (IsUnit.unit hx) + lemma hasFPowerSeriesOnBall_inv_one_sub (𝕜 𝕝 : Type*) [NontriviallyNormedField 𝕜] [NontriviallyNormedField 𝕝] [NormedAlgebra 𝕜 𝕝] : HasFPowerSeriesOnBall (fun x : 𝕝 ↦ (1 - x)⁻¹) (formalMultilinearSeries_geometric 𝕜 𝕝) 0 1 := by @@ -726,9 +834,12 @@ lemma analyticAt_inv {z : 𝕝} (hz : z ≠ 0) : AnalyticAt 𝕜 Inv.inv z := by exact Ring.inverse_eq_inv'.symm /-- `x⁻¹` is analytic away from zero -/ -lemma analyticOn_inv : AnalyticOn 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := by +lemma analyticOnNhd_inv : AnalyticOnNhd 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := by intro z m; exact analyticAt_inv m +lemma analyticOn_inv : AnalyticOn 𝕜 (fun z ↦ z⁻¹) {z : 𝕝 | z ≠ 0} := + analyticOnNhd_inv.analyticOn + /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ theorem AnalyticWithinAt.inv {f : E → 𝕝} {x : E} {s : Set E} (fa : AnalyticWithinAt 𝕜 f s x) (f0 : f x ≠ 0) : @@ -741,14 +852,18 @@ theorem AnalyticAt.inv {f : E → 𝕝} {x : E} (fa : AnalyticAt 𝕜 f x) (f0 : (analyticAt_inv f0).comp fa /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ -theorem AnalyticWithinOn.inv {f : E → 𝕝} {s : Set E} - (fa : AnalyticWithinOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : - AnalyticWithinOn 𝕜 (fun x ↦ (f x)⁻¹) s := +theorem AnalyticOn.inv {f : E → 𝕝} {s : Set E} + (fa : AnalyticOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : + AnalyticOn 𝕜 (fun x ↦ (f x)⁻¹) s := fun x m ↦ (fa x m).inv (f0 x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.inv := AnalyticOn.inv + /-- `(f x)⁻¹` is analytic away from `f x = 0` -/ -theorem AnalyticOn.inv {f : E → 𝕝} {s : Set E} (fa : AnalyticOn 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : - AnalyticOn 𝕜 (fun x ↦ (f x)⁻¹) s := +theorem AnalyticOnNhd.inv {f : E → 𝕝} {s : Set E} + (fa : AnalyticOnNhd 𝕜 f s) (f0 : ∀ x ∈ s, f x ≠ 0) : + AnalyticOnNhd 𝕜 (fun x ↦ (f x)⁻¹) s := fun x m ↦ (fa x m).inv (f0 x m) /-- `f x / g x` is analytic away from `g x = 0` -/ @@ -763,18 +878,21 @@ theorem AnalyticAt.div {f g : E → 𝕝} {x : E} AnalyticAt 𝕜 (fun x ↦ f x / g x) x := by simp_rw [div_eq_mul_inv]; exact fa.mul (ga.inv g0) -/-- `f x / g x` is analytic away from `g x = 0` -/ -theorem AnalyticWithinOn.div {f g : E → 𝕝} {s : Set E} - (fa : AnalyticWithinOn 𝕜 f s) (ga : AnalyticWithinOn 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : - AnalyticWithinOn 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ - (fa x m).div (ga x m) (g0 x m) - /-- `f x / g x` is analytic away from `g x = 0` -/ theorem AnalyticOn.div {f g : E → 𝕝} {s : Set E} (fa : AnalyticOn 𝕜 f s) (ga : AnalyticOn 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : AnalyticOn 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ (fa x m).div (ga x m) (g0 x m) +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.div := AnalyticOn.div + +/-- `f x / g x` is analytic away from `g x = 0` -/ +theorem AnalyticOnNhd.div {f g : E → 𝕝} {s : Set E} + (fa : AnalyticOnNhd 𝕜 f s) (ga : AnalyticOnNhd 𝕜 g s) (g0 : ∀ x ∈ s, g x ≠ 0) : + AnalyticOnNhd 𝕜 (fun x ↦ f x / g x) s := fun x m ↦ + (fa x m).div (ga x m) (g0 x m) + /-! ### Finite sums and products of analytic functions -/ @@ -797,16 +915,19 @@ theorem Finset.analyticAt_sum {f : α → E → F} {c : E} simp_rw [← analyticWithinAt_univ] at h ⊢ exact N.analyticWithinAt_sum h -/-- Finite sums of analytic functions are analytic -/ -theorem Finset.analyticWithinOn_sum {f : α → E → F} {s : Set E} - (N : Finset α) (h : ∀ n ∈ N, AnalyticWithinOn 𝕜 (f n) s) : - AnalyticWithinOn 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := - fun z zs ↦ N.analyticWithinAt_sum (fun n m ↦ h n m z zs) - /-- Finite sums of analytic functions are analytic -/ theorem Finset.analyticOn_sum {f : α → E → F} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOn 𝕜 (f n) s) : AnalyticOn 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := + fun z zs ↦ N.analyticWithinAt_sum (fun n m ↦ h n m z zs) + +@[deprecated (since := "2024-09-26")] +alias Finset.analyticWithinOn_sum := Finset.analyticOn_sum + +/-- Finite sums of analytic functions are analytic -/ +theorem Finset.analyticOnNhd_sum {f : α → E → F} {s : Set E} + (N : Finset α) (h : ∀ n ∈ N, AnalyticOnNhd 𝕜 (f n) s) : + AnalyticOnNhd 𝕜 (fun z ↦ ∑ n ∈ N, f n z) s := fun z zs ↦ N.analyticAt_sum (fun n m ↦ h n m z zs) /-- Finite products of analytic functions are analytic -/ @@ -827,14 +948,17 @@ theorem Finset.analyticAt_prod {A : Type*} [NormedCommRing A] [NormedAlgebra simp_rw [← analyticWithinAt_univ] at h ⊢ exact N.analyticWithinAt_prod h -/-- Finite products of analytic functions are analytic -/ -theorem Finset.analyticWithinOn_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] - {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticWithinOn 𝕜 (f n) s) : - AnalyticWithinOn 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := - fun z zs ↦ N.analyticWithinAt_prod (fun n m ↦ h n m z zs) - /-- Finite products of analytic functions are analytic -/ theorem Finset.analyticOn_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOn 𝕜 (f n) s) : AnalyticOn 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := + fun z zs ↦ N.analyticWithinAt_prod (fun n m ↦ h n m z zs) + +@[deprecated (since := "2024-09-26")] +alias Finset.analyticWithinOn_prod := Finset.analyticOn_prod + +/-- Finite products of analytic functions are analytic -/ +theorem Finset.analyticOnNhd_prod {A : Type*} [NormedCommRing A] [NormedAlgebra 𝕜 A] + {f : α → E → A} {s : Set E} (N : Finset α) (h : ∀ n ∈ N, AnalyticOnNhd 𝕜 (f n) s) : + AnalyticOnNhd 𝕜 (fun z ↦ ∏ n ∈ N, f n z) s := fun z zs ↦ N.analyticAt_prod (fun n m ↦ h n m z zs) diff --git a/Mathlib/Analysis/Analytic/Inverse.lean b/Mathlib/Analysis/Analytic/Inverse.lean index ccd47d8263a54..eadc577c91124 100644 --- a/Mathlib/Analysis/Analytic/Inverse.lean +++ b/Mathlib/Analysis/Analytic/Inverse.lean @@ -4,36 +4,43 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ import Mathlib.Analysis.Analytic.Composition +import Mathlib.Analysis.Analytic.Linear /-! # Inverse of analytic functions We construct the left and right inverse of a formal multilinear series with invertible linear term, -we prove that they coincide and study their properties (notably convergence). +we prove that they coincide and study their properties (notably convergence). We deduce that the +inverse of an analytic partial homeomorphism is analytic. ## Main statements -* `p.leftInv i`: the formal left inverse of the formal multilinear series `p`, - for `i : E ≃L[𝕜] F` which coincides with `p₁`. -* `p.rightInv i`: the formal right inverse of the formal multilinear series `p`, - for `i : E ≃L[𝕜] F` which coincides with `p₁`. -* `p.leftInv_comp` says that `p.leftInv i` is indeed a left inverse to `p` when `p₁ = i`. -* `p.rightInv_comp` says that `p.rightInv i` is indeed a right inverse to `p` when `p₁ = i`. +* `p.leftInv i x`: the formal left inverse of the formal multilinear series `p`, with constant + coefficient `x`, for `i : E ≃L[𝕜] F` which coincides with `p₁`. +* `p.rightInv i x`: the formal right inverse of the formal multilinear series `p`, with constant + coefficient `x`, for `i : E ≃L[𝕜] F` which coincides with `p₁`. +* `p.leftInv_comp` says that `p.leftInv i x` is indeed a left inverse to `p` when `p₁ = i`. +* `p.rightInv_comp` says that `p.rightInv i x` is indeed a right inverse to `p` when `p₁ = i`. * `p.leftInv_eq_rightInv`: the two inverses coincide. * `p.radius_rightInv_pos_of_radius_pos`: if a power series has a positive radius of convergence, then so does its inverse. +* `PartialHomeomorph.hasFPowerSeriesAt_symm` shows that, if a partial homeomorph has a power series + `p` at a point, with invertible linear part, then the inverse also has a power series at the + image point, given by `p.leftInv`. -/ -open scoped Topology +open scoped Topology ENNReal open Finset Filter -namespace FormalMultilinearSeries +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {G : Type*} [NormedAddCommGroup G] [NormedSpace 𝕜 G] -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] - [NormedSpace 𝕜 E] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] +namespace FormalMultilinearSeries /-! ### The left inverse of a formal multilinear series -/ @@ -51,27 +58,27 @@ term compensates the rest of the sum, using `i⁻¹` as an inverse to `p₁`. These formulas only make sense when the constant term `p₀` vanishes. The definition we give is general, but it ignores the value of `p₀`. -/ -noncomputable def leftInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : +noncomputable def leftInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : FormalMultilinearSeries 𝕜 F E - | 0 => 0 + | 0 => ContinuousMultilinearMap.uncurry0 𝕜 _ x | 1 => (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm | n + 2 => -∑ c : { c : Composition (n + 2) // c.length < n + 2 }, - (leftInv p i (c : Composition (n + 2)).length).compAlongComposition + (leftInv p i x (c : Composition (n + 2)).length).compAlongComposition (p.compContinuousLinearMap i.symm) c @[simp] -theorem leftInv_coeff_zero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.leftInv i 0 = 0 := by rw [leftInv] +theorem leftInv_coeff_zero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.leftInv i x 0 = ContinuousMultilinearMap.uncurry0 𝕜 _ x := by rw [leftInv] @[simp] -theorem leftInv_coeff_one (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.leftInv i 1 = (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm := by rw [leftInv] +theorem leftInv_coeff_one (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.leftInv i x 1 = (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm := by rw [leftInv] /-- The left inverse does not depend on the zeroth coefficient of a formal multilinear series. -/ -theorem leftInv_removeZero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.removeZero.leftInv i = p.leftInv i := by +theorem leftInv_removeZero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.removeZero.leftInv i x = p.leftInv i x := by ext1 n induction' n using Nat.strongRec' with n IH match n with @@ -87,14 +94,15 @@ theorem leftInv_removeZero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[ /-- The left inverse to a formal multilinear series is indeed a left inverse, provided its linear term is invertible. -/ -theorem leftInv_comp (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) - (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : (leftInv p i).comp p = id 𝕜 E := by - ext (n v) +theorem leftInv_comp (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) + (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : + (leftInv p i x).comp p = id 𝕜 E x := by + ext n v classical match n with | 0 => - simp only [leftInv_coeff_zero, ContinuousMultilinearMap.zero_apply, id_apply_ne_one, Ne, - not_false_iff, zero_ne_one, comp_coeff_zero'] + simp only [comp_coeff_zero', leftInv_coeff_zero, ContinuousMultilinearMap.uncurry0_apply, + id_apply_zero] | 1 => simp only [leftInv_coeff_one, comp_coeff_one, h, id_apply_one, ContinuousLinearEquiv.coe_apply, ContinuousLinearEquiv.symm_apply_apply, continuousMultilinearCurryFin1_symm_apply] @@ -111,16 +119,16 @@ theorem leftInv_comp (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) {Composition.ones (n + 2)} := by simp [Set.mem_toFinset (s := {c | Composition.length c < n + 2})] have C : - ((p.leftInv i (Composition.ones (n + 2)).length) + ((p.leftInv i x (Composition.ones (n + 2)).length) fun j : Fin (Composition.ones n.succ.succ).length => p 1 fun _ => v ((Fin.castLE (Composition.length_le _)) j)) = - p.leftInv i (n + 2) fun j : Fin (n + 2) => p 1 fun _ => v j := by + p.leftInv i x (n + 2) fun j : Fin (n + 2) => p 1 fun _ => v j := by apply FormalMultilinearSeries.congr _ (Composition.ones_length _) fun j hj1 hj2 => ?_ exact FormalMultilinearSeries.congr _ rfl fun k _ _ => by congr have D : - (p.leftInv i (n + 2) fun j : Fin (n + 2) => p 1 fun _ => v j) = + (p.leftInv i x (n + 2) fun j : Fin (n + 2) => p 1 fun _ => v j) = -∑ c ∈ {c : Composition (n + 2) | c.length < n + 2}.toFinset, - (p.leftInv i c.length) (p.applyComposition c v) := by + (p.leftInv i x c.length) (p.applyComposition c v) := by simp only [leftInv, ContinuousMultilinearMap.neg_apply, neg_inj, ContinuousMultilinearMap.sum_apply] convert @@ -128,7 +136,7 @@ theorem leftInv_comp (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (fun c : Composition (n + 2) => c.length < n + 2) (fun c : Composition (n + 2) => (ContinuousMultilinearMap.compAlongComposition - (p.compContinuousLinearMap (i.symm : F →L[𝕜] E)) c (p.leftInv i c.length)) + (p.compContinuousLinearMap (i.symm : F →L[𝕜] E)) c (p.leftInv i x c.length)) fun j : Fin (n + 2) => p 1 fun _ : Fin 1 => v j)).symm.trans _ simp only [compContinuousLinearMap_applyComposition, @@ -157,26 +165,26 @@ term compensates the rest of the sum, using `i⁻¹` as an inverse to `p₁`. These formulas only make sense when the constant term `p₀` vanishes. The definition we give is general, but it ignores the value of `p₀`. -/ -noncomputable def rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : +noncomputable def rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : FormalMultilinearSeries 𝕜 F E - | 0 => 0 + | 0 => ContinuousMultilinearMap.uncurry0 𝕜 _ x | 1 => (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm | n + 2 => - let q : FormalMultilinearSeries 𝕜 F E := fun k => if k < n + 2 then rightInv p i k else 0; + let q : FormalMultilinearSeries 𝕜 F E := fun k => if k < n + 2 then rightInv p i x k else 0; -(i.symm : F →L[𝕜] E).compContinuousMultilinearMap ((p.comp q) (n + 2)) @[simp] -theorem rightInv_coeff_zero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.rightInv i 0 = 0 := by rw [rightInv] +theorem rightInv_coeff_zero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.rightInv i x 0 = ContinuousMultilinearMap.uncurry0 𝕜 _ x := by rw [rightInv] @[simp] -theorem rightInv_coeff_one (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.rightInv i 1 = (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm := by rw [rightInv] +theorem rightInv_coeff_one (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.rightInv i x 1 = (continuousMultilinearCurryFin1 𝕜 F E).symm i.symm := by rw [rightInv] /-- The right inverse does not depend on the zeroth coefficient of a formal multilinear series. -/ -theorem rightInv_removeZero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) : - p.removeZero.rightInv i = p.rightInv i := by +theorem rightInv_removeZero (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) : + p.removeZero.rightInv i x = p.rightInv i x := by ext1 n induction' n using Nat.strongRec' with n IH match n with @@ -216,12 +224,12 @@ theorem comp_rightInv_aux1 {n : ℕ} (hn : 0 < n) (p : FormalMultilinearSeries simp [FormalMultilinearSeries.comp, A, Finset.sum_union B, C, -Set.toFinset_setOf, -add_right_inj, -Composition.single_length] -theorem comp_rightInv_aux2 (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (n : ℕ) +theorem comp_rightInv_aux2 (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) (n : ℕ) (v : Fin (n + 2) → F) : ∑ c ∈ {c : Composition (n + 2) | 1 < c.length}.toFinset, - p c.length (applyComposition (fun k : ℕ => ite (k < n + 2) (p.rightInv i k) 0) c v) = + p c.length (applyComposition (fun k : ℕ => ite (k < n + 2) (p.rightInv i x k) 0) c v) = ∑ c ∈ {c : Composition (n + 2) | 1 < c.length}.toFinset, - p c.length ((p.rightInv i).applyComposition c v) := by + p c.length ((p.rightInv i x).applyComposition c v) := by have N : 0 < n + 2 := by norm_num refine sum_congr rfl fun c hc => p.congr rfl fun j hj1 hj2 => ?_ have : ∀ k, c.blocksFun k < n + 2 := by @@ -232,14 +240,16 @@ theorem comp_rightInv_aux2 (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[ /-- The right inverse to a formal multilinear series is indeed a right inverse, provided its linear term is invertible and its constant term vanishes. -/ -theorem comp_rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) - (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) (h0 : p 0 = 0) : - p.comp (rightInv p i) = id 𝕜 F := by +theorem comp_rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) + (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : + p.comp (rightInv p i x) = id 𝕜 F (p 0 0) := by ext (n v) match n with | 0 => - simp only [h0, ContinuousMultilinearMap.zero_apply, id_apply_ne_one, Ne, not_false_iff, - zero_ne_one, comp_coeff_zero'] + simp only [comp_coeff_zero', Matrix.zero_empty, id_apply_zero] + congr + ext i + exact i.elim0 | 1 => simp only [comp_coeff_one, h, rightInv_coeff_one, ContinuousLinearEquiv.apply_symm_apply, id_apply_one, ContinuousLinearEquiv.coe_apply, continuousMultilinearCurryFin1_symm_apply] @@ -248,11 +258,12 @@ theorem comp_rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F simp [comp_rightInv_aux1 N, h, rightInv, lt_irrefl n, show n + 2 ≠ 1 by omega, ← sub_eq_add_neg, sub_eq_zero, comp_rightInv_aux2, -Set.toFinset_setOf] -theorem rightInv_coeff (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (n : ℕ) (hn : 2 ≤ n) : - p.rightInv i n = +theorem rightInv_coeff (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) + (n : ℕ) (hn : 2 ≤ n) : + p.rightInv i x n = -(i.symm : F →L[𝕜] E).compContinuousMultilinearMap (∑ c ∈ ({c | 1 < Composition.length c}.toFinset : Finset (Composition n)), - p.compAlongComposition (p.rightInv i) c) := by + p.compAlongComposition (p.rightInv i x) c) := by match n with | 0 => exact False.elim (zero_lt_two.not_le hn) | 1 => exact False.elim (one_lt_two.not_le hn) @@ -267,26 +278,15 @@ theorem rightInv_coeff (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] /-! ### Coincidence of the left and the right inverse -/ -private theorem leftInv_eq_rightInv_aux (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) - (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) (h0 : p 0 = 0) : - leftInv p i = rightInv p i := - calc - leftInv p i = (leftInv p i).comp (id 𝕜 F) := by simp - _ = (leftInv p i).comp (p.comp (rightInv p i)) := by rw [comp_rightInv p i h h0] - _ = ((leftInv p i).comp p).comp (rightInv p i) := by rw [comp_assoc] - _ = (id 𝕜 E).comp (rightInv p i) := by rw [leftInv_comp p i h] - _ = rightInv p i := by simp - -/-- The left inverse and the right inverse of a formal multilinear series coincide. This is not at -all obvious from their definition, but it follows from uniqueness of inverses (which comes from the -fact that composition is associative on formal multilinear series). -/ -theorem leftInv_eq_rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) - (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : leftInv p i = rightInv p i := +theorem leftInv_eq_rightInv (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) (x : E) + (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : + leftInv p i x = rightInv p i x := calc - leftInv p i = leftInv p.removeZero i := by rw [leftInv_removeZero] - _ = rightInv p.removeZero i := by - apply leftInv_eq_rightInv_aux _ _ (by simpa using h) (by simp) - _ = rightInv p i := by rw [rightInv_removeZero] + leftInv p i x = (leftInv p i x).comp (id 𝕜 F (p 0 0)) := by simp + _ = (leftInv p i x).comp (p.comp (rightInv p i x)) := by rw [comp_rightInv p i _ h] + _ = ((leftInv p i x).comp p).comp (rightInv p i x) := by rw [comp_assoc] + _ = (id 𝕜 E x).comp (rightInv p i x) := by rw [leftInv_comp p i _ h] + _ = rightInv p i x := by simp [id_comp' _ _ 0] /-! ### Convergence of the inverse of a power series @@ -423,17 +423,17 @@ theorem radius_right_inv_pos_of_radius_pos_aux1 (n : ℕ) (p : ℕ → ℝ) (hp expression for `∑_{k ‖p.rightInv i k‖) + radius_right_inv_pos_of_radius_pos_aux1 n (fun k => ‖p.rightInv i x k‖) (fun k => norm_nonneg _) hr ha /-- If a a formal multilinear series has a positive radius of convergence, then its right inverse also has a positive radius of convergence. -/ -theorem radius_rightInv_pos_of_radius_pos (p : FormalMultilinearSeries 𝕜 E F) (i : E ≃L[𝕜] F) - (hp : 0 < p.radius) : 0 < (p.rightInv i).radius := by +theorem radius_rightInv_pos_of_radius_pos + {p : FormalMultilinearSeries 𝕜 E F} {i : E ≃L[𝕜] F} {x : E} + (hp : 0 < p.radius) : 0 < (p.rightInv i x).radius := by obtain ⟨C, r, Cpos, rpos, ple⟩ : ∃ (C r : _) (_ : 0 < C) (_ : 0 < r), ∀ n : ℕ, ‖p n‖ ≤ C * r ^ n := le_mul_pow_of_radius_pos p hp @@ -508,7 +505,7 @@ theorem radius_rightInv_pos_of_radius_pos (p : FormalMultilinearSeries 𝕜 E F) exact ⟨a, ha.1, ha.2.1.le, ha.2.2.le⟩ -- check by induction that the partial sums are suitably bounded, using the choice of `a` and the -- inductive control from Lemma `radius_rightInv_pos_of_radius_pos_aux2`. - let S n := ∑ k ∈ Ico 1 n, a ^ k * ‖p.rightInv i k‖ + let S n := ∑ k ∈ Ico 1 n, a ^ k * ‖p.rightInv i x k‖ have IRec : ∀ n, 1 ≤ n → S n ≤ (I + 1) * a := by apply Nat.le_induction · simp only [S] @@ -536,21 +533,159 @@ theorem radius_rightInv_pos_of_radius_pos (p : FormalMultilinearSeries 𝕜 E F) _ ≤ (I + 1) * a := by gcongr -- conclude that all coefficients satisfy `aⁿ Qₙ ≤ (I + 1) a`. let a' : NNReal := ⟨a, apos.le⟩ - suffices H : (a' : ENNReal) ≤ (p.rightInv i).radius by + suffices H : (a' : ENNReal) ≤ (p.rightInv i x).radius by apply lt_of_lt_of_le _ H -- Prior to leanprover/lean4#2734, this was `exact_mod_cast apos`. simpa only [ENNReal.coe_pos] - apply le_radius_of_bound _ ((I + 1) * a) fun n => ?_ - by_cases hn : n = 0 - · have : ‖p.rightInv i n‖ = ‖p.rightInv i 0‖ := by congr <;> try rw [hn] - simp only [this, norm_zero, zero_mul, rightInv_coeff_zero] - positivity - · have one_le_n : 1 ≤ n := bot_lt_iff_ne_bot.2 hn - calc - ‖p.rightInv i n‖ * (a' : ℝ) ^ n = a ^ n * ‖p.rightInv i n‖ := mul_comm _ _ - _ ≤ ∑ k ∈ Ico 1 (n + 1), a ^ k * ‖p.rightInv i k‖ := - (haveI : ∀ k ∈ Ico 1 (n + 1), 0 ≤ a ^ k * ‖p.rightInv i k‖ := fun k _ => by positivity - single_le_sum this (by simp [one_le_n])) - _ ≤ (I + 1) * a := IRec (n + 1) (by norm_num) + apply le_radius_of_eventually_le _ ((I + 1) * a) + filter_upwards [Ici_mem_atTop 1] with n (hn : 1 ≤ n) + calc + ‖p.rightInv i x n‖ * (a' : ℝ) ^ n = a ^ n * ‖p.rightInv i x n‖ := mul_comm _ _ + _ ≤ ∑ k ∈ Ico 1 (n + 1), a ^ k * ‖p.rightInv i x k‖ := + (haveI : ∀ k ∈ Ico 1 (n + 1), 0 ≤ a ^ k * ‖p.rightInv i x k‖ := fun k _ => by positivity + single_le_sum this (by simp [hn])) + _ ≤ (I + 1) * a := IRec (n + 1) (by norm_num) + +/-- If a a formal multilinear series has a positive radius of convergence, then its left inverse +also has a positive radius of convergence. -/ +theorem radius_leftInv_pos_of_radius_pos + {p : FormalMultilinearSeries 𝕜 E F} {i : E ≃L[𝕜] F} {x : E} + (hp : 0 < p.radius) (h : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : + 0 < (p.leftInv i x).radius := by + rw [leftInv_eq_rightInv _ _ _ h] + exact radius_rightInv_pos_of_radius_pos hp end FormalMultilinearSeries + +/-! +### The inverse of an analytic partial homeomorphism is analytic +-/ + +open FormalMultilinearSeries List + +lemma HasFPowerSeriesAt.tendsto_partialSum_prod_of_comp + {f : E → G} {q : FormalMultilinearSeries 𝕜 F G} + {p : FormalMultilinearSeries 𝕜 E F} {x : E} + (hf : HasFPowerSeriesAt f (q.comp p) x) (hq : 0 < q.radius) (hp : 0 < p.radius) : + ∀ᶠ y in 𝓝 0, Tendsto (fun (a : ℕ × ℕ) ↦ q.partialSum a.1 (p.partialSum a.2 y + - p 0 (fun _ ↦ 0))) atTop (𝓝 (f (x + y))) := by + rcases hf with ⟨r0, h0⟩ + rcases q.comp_summable_nnreal p hq hp with ⟨r1, r1_pos : 0 < r1, hr1⟩ + let r : ℝ≥0∞ := min r0 r1 + have : EMetric.ball (0 : E) r ∈ 𝓝 0 := + EMetric.ball_mem_nhds 0 (lt_min h0.r_pos (by exact_mod_cast r1_pos)) + filter_upwards [this] with y hy + have hy0 : y ∈ EMetric.ball 0 r0 := EMetric.ball_subset_ball (min_le_left _ _) hy + have A : HasSum (fun i : Σ n, Composition n => q.compAlongComposition p i.2 fun _j => y) + (f (x + y)) := by + have cau : CauchySeq fun s : Finset (Σ n, Composition n) => + ∑ i ∈ s, q.compAlongComposition p i.2 fun _j => y := by + apply cauchySeq_finset_of_norm_bounded _ (NNReal.summable_coe.2 hr1) _ + simp only [coe_nnnorm, NNReal.coe_mul, NNReal.coe_pow] + rintro ⟨n, c⟩ + calc + ‖(compAlongComposition q p c) fun _j : Fin n => y‖ ≤ + ‖compAlongComposition q p c‖ * ∏ _j : Fin n, ‖y‖ := by + apply ContinuousMultilinearMap.le_opNorm + _ ≤ ‖compAlongComposition q p c‖ * (r1 : ℝ) ^ n := by + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + rw [Finset.prod_const, Finset.card_fin] + apply pow_le_pow_left (norm_nonneg _) + rw [EMetric.mem_ball, edist_eq_coe_nnnorm] at hy + have := le_trans (le_of_lt hy) (min_le_right _ _) + rwa [ENNReal.coe_le_coe, ← NNReal.coe_le_coe, coe_nnnorm] at this + apply HasSum.of_sigma (fun b ↦ hasSum_fintype _) ?_ cau + simpa [FormalMultilinearSeries.comp] using h0.hasSum hy0 + have B : Tendsto (fun (n : ℕ × ℕ) => ∑ i ∈ compPartialSumTarget 0 n.1 n.2, + q.compAlongComposition p i.2 fun _j => y) atTop (𝓝 (f (x + y))) := by + apply Tendsto.comp A compPartialSumTarget_tendsto_prod_atTop + have C : Tendsto (fun (n : ℕ × ℕ) => q.partialSum n.1 (∑ a ∈ Finset.Ico 1 n.2, p a fun _b ↦ y)) + atTop (𝓝 (f (x + y))) := by simpa [comp_partialSum] using B + apply C.congr' + filter_upwards [Ici_mem_atTop (0, 1)] + rintro ⟨-, n⟩ ⟨-, (hn : 1 ≤ n)⟩ + congr + rw [partialSum, eq_sub_iff_add_eq', Finset.range_eq_Ico, + Finset.sum_eq_sum_Ico_succ_bot hn] + congr with i + exact i.elim0 + +lemma HasFPowerSeriesAt.eventually_hasSum_of_comp {f : E → F} {g : F → G} + {q : FormalMultilinearSeries 𝕜 F G} {p : FormalMultilinearSeries 𝕜 E F} {x : E} + (hgf : HasFPowerSeriesAt (g ∘ f) (q.comp p) x) (hf : HasFPowerSeriesAt f p x) + (hq : 0 < q.radius) : + ∀ᶠ y in 𝓝 0, HasSum (fun n : ℕ => q n fun _ : Fin n => (f (x + y) - f x)) (g (f (x + y))) := by + have : ∀ᶠ y in 𝓝 (0 : E), f (x + y) - f x ∈ EMetric.ball 0 q.radius := by + have A : ContinuousAt (fun y ↦ f (x + y) - f x) 0 := by + apply ContinuousAt.sub _ continuousAt_const + exact hf.continuousAt.comp_of_eq (continuous_add_left x).continuousAt (by simp) + have B : EMetric.ball 0 q.radius ∈ 𝓝 (f (x + 0) - f x) := by + simpa using EMetric.ball_mem_nhds _ hq + exact A.preimage_mem_nhds B + filter_upwards [hgf.tendsto_partialSum_prod_of_comp hq (hf.radius_pos), + hf.tendsto_partialSum, this] with y hy h'y h''y + have L : Tendsto (fun n ↦ q.partialSum n (f (x + y) - f x)) atTop (𝓝 (g (f (x + y)))) := by + apply (closed_nhds_basis (g (f (x + y)))).tendsto_right_iff.2 + rintro u ⟨hu, u_closed⟩ + simp only [id_eq, eventually_atTop, ge_iff_le] + rcases mem_nhds_iff.1 hu with ⟨v, vu, v_open, hv⟩ + obtain ⟨a₀, b₀, hab⟩ : ∃ a₀ b₀, ∀ (a b : ℕ), a₀ ≤ a → b₀ ≤ b → + q.partialSum a (p.partialSum b y - (p 0) fun x ↦ 0) ∈ v := by + simpa using hy (v_open.mem_nhds hv) + refine ⟨a₀, fun a ha ↦ ?_⟩ + have : Tendsto (fun b ↦ q.partialSum a (p.partialSum b y - (p 0) fun x ↦ 0)) atTop + (𝓝 (q.partialSum a (f (x + y) - f x))) := by + have : ContinuousAt (q.partialSum a) (f (x + y) - f x) := + (partialSum_continuous q a).continuousAt + apply this.tendsto.comp + apply Tendsto.sub h'y + convert tendsto_const_nhds + exact (HasFPowerSeriesAt.coeff_zero hf fun _ ↦ 0).symm + apply u_closed.mem_of_tendsto this + filter_upwards [Ici_mem_atTop b₀] with b hb using vu (hab _ _ ha hb) + have C : CauchySeq (fun (s : Finset ℕ) ↦ ∑ n ∈ s, q n fun _ : Fin n => (f (x + y) - f x)) := by + have Z := q.summable_norm_apply (x := f (x + y) - f x) h''y + exact cauchySeq_finset_of_norm_bounded _ Z (fun i ↦ le_rfl) + exact tendsto_nhds_of_cauchySeq_of_subseq C tendsto_finset_range L + +/-- If a partial homeomorphism `f` is defined at `a` and has a power series expansion there with +invertible linear term, then `f.symm` has a power series expansion at `f a`, given by the inverse +of the initial power series. -/ +theorem PartialHomeomorph.hasFPowerSeriesAt_symm (f : PartialHomeomorph E F) {a : E} + {i : E ≃L[𝕜] F} (h0 : a ∈ f.source) {p : FormalMultilinearSeries 𝕜 E F} + (h : HasFPowerSeriesAt f p a) (hp : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i) : + HasFPowerSeriesAt f.symm (p.leftInv i a) (f a) := by + have A : HasFPowerSeriesAt (f.symm ∘ f) ((p.leftInv i a).comp p) a := by + have : HasFPowerSeriesAt (ContinuousLinearMap.id 𝕜 E) ((p.leftInv i a).comp p) a := by + rw [leftInv_comp _ _ _ hp] + exact (ContinuousLinearMap.id 𝕜 E).hasFPowerSeriesAt a + apply this.congr + filter_upwards [f.open_source.mem_nhds h0] with x hx using by simp [hx] + have B : ∀ᶠ (y : E) in 𝓝 0, HasSum (fun n ↦ (p.leftInv i a n) fun _ ↦ f (a + y) - f a) + (f.symm (f (a + y))) := by + simpa using A.eventually_hasSum_of_comp h (radius_leftInv_pos_of_radius_pos h.radius_pos hp) + have C : ∀ᶠ (y : E) in 𝓝 a, HasSum (fun n ↦ (p.leftInv i a n) fun _ ↦ f y - f a) + (f.symm (f y)) := by + rw [← sub_eq_zero_of_eq (a := a) rfl] at B + have : ContinuousAt (fun x ↦ x - a) a := by fun_prop + simpa using this.preimage_mem_nhds B + have D : ∀ᶠ (y : E) in 𝓝 (f.symm (f a)), + HasSum (fun n ↦ (p.leftInv i a n) fun _ ↦ f y - f a) y := by + simp only [h0, PartialHomeomorph.left_inv] + filter_upwards [C, f.open_source.mem_nhds h0] with x hx h'x + simpa [h'x] using hx + have E : ∀ᶠ z in 𝓝 (f a), HasSum (fun n ↦ (p.leftInv i a n) fun _ ↦ f (f.symm z) - f a) + (f.symm z) := by + have : ContinuousAt f.symm (f a) := f.continuousAt_symm (f.map_source h0) + exact this D + have F : ∀ᶠ z in 𝓝 (f a), HasSum (fun n ↦ (p.leftInv i a n) fun _ ↦ z - f a) (f.symm z) := by + filter_upwards [f.open_target.mem_nhds (f.map_source h0), E] with z hz h'z + simpa [hz] using h'z + rcases EMetric.mem_nhds_iff.1 F with ⟨r, r_pos, hr⟩ + refine ⟨min r (p.leftInv i a).radius, min_le_right _ _, + lt_min r_pos (radius_leftInv_pos_of_radius_pos h.radius_pos hp), fun {y} hy ↦ ?_⟩ + have : y + f a ∈ EMetric.ball (f a) r := by + simp only [EMetric.mem_ball, edist_eq_coe_nnnorm_sub, sub_zero, lt_min_iff, + add_sub_cancel_right] at hy ⊢ + exact hy.1 + simpa [add_comm] using hr this diff --git a/Mathlib/Analysis/Analytic/IsolatedZeros.lean b/Mathlib/Analysis/Analytic/IsolatedZeros.lean index 00ccc0c8bbeea..18aad9fb34b3e 100644 --- a/Mathlib/Analysis/Analytic/IsolatedZeros.lean +++ b/Mathlib/Analysis/Analytic/IsolatedZeros.lean @@ -20,7 +20,7 @@ useful in this setup. * `AnalyticAt.eventually_eq_zero_or_eventually_ne_zero` is the main statement that if a function is analytic at `z₀`, then either it is identically zero in a neighborhood of `z₀`, or it does not vanish in a punctured neighborhood of `z₀`. -* `AnalyticOn.eqOn_of_preconnected_of_frequently_eq` is the identity theorem for analytic +* `AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq` is the identity theorem for analytic functions: if a function `f` is analytic on a connected set `U` and is zero on a set with an accumulation point in `U` then `f` is identically `0` on `U`. -/ @@ -221,7 +221,7 @@ lemma order_eq_nat_iff (hf : AnalyticAt 𝕜 f z₀) (n : ℕ) : hf.order = ↑n end AnalyticAt -namespace AnalyticOn +namespace AnalyticOnNhd variable {U : Set 𝕜} @@ -229,13 +229,22 @@ variable {U : Set 𝕜} analytic on a connected set `U` and vanishes in arbitrary neighborhoods of a point `z₀ ∈ U`, then it is identically zero in `U`. For higher-dimensional versions requiring that the function vanishes in a neighborhood of `z₀`, -see `AnalyticOn.eqOn_zero_of_preconnected_of_eventuallyEq_zero`. -/ -theorem eqOn_zero_of_preconnected_of_frequently_eq_zero (hf : AnalyticOn 𝕜 f U) +see `AnalyticOnNhd.eqOn_zero_of_preconnected_of_eventuallyEq_zero`. -/ +theorem eqOn_zero_of_preconnected_of_frequently_eq_zero (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfw : ∃ᶠ z in 𝓝[≠] z₀, f z = 0) : EqOn f 0 U := hf.eqOn_zero_of_preconnected_of_eventuallyEq_zero hU h₀ ((hf z₀ h₀).frequently_zero_iff_eventually_zero.1 hfw) -theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) +theorem eqOn_zero_or_eventually_ne_zero_of_preconnected (hf : AnalyticOnNhd 𝕜 f U) + (hU : IsPreconnected U) : EqOn f 0 U ∨ ∀ᶠ x in codiscreteWithin U, f x ≠ 0 := by + simp only [or_iff_not_imp_right, ne_eq, eventually_iff, mem_codiscreteWithin, + disjoint_principal_right, not_forall] + rintro ⟨x, hx, hx2⟩ + refine hf.eqOn_zero_of_preconnected_of_frequently_eq_zero hU hx fun nh ↦ hx2 ?_ + filter_upwards [nh] with a ha + simp_all + +theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfz₀ : z₀ ∈ closure ({z | f z = 0} \ {z₀})) : EqOn f 0 U := hf.eqOn_zero_of_preconnected_of_frequently_eq_zero hU h₀ (mem_closure_ne_iff_frequently_within.mp hfz₀) @@ -244,15 +253,21 @@ theorem eqOn_zero_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hU analytic on a connected set `U` and coincide at points which accumulate to a point `z₀ ∈ U`, then they coincide globally in `U`. For higher-dimensional versions requiring that the functions coincide in a neighborhood of `z₀`, -see `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`. -/ -theorem eqOn_of_preconnected_of_frequently_eq (hf : AnalyticOn 𝕜 f U) (hg : AnalyticOn 𝕜 g U) +see `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`. -/ +theorem eqOn_of_preconnected_of_frequently_eq (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : EqOn f g U := by have hfg' : ∃ᶠ z in 𝓝[≠] z₀, (f - g) z = 0 := hfg.mono fun z h => by rw [Pi.sub_apply, h, sub_self] simpa [sub_eq_zero] using fun z hz => (hf.sub hg).eqOn_zero_of_preconnected_of_frequently_eq_zero hU h₀ hfg' hz -theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hg : AnalyticOn 𝕜 g U) +theorem eqOn_or_eventually_ne_of_preconnected (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) + (hU : IsPreconnected U) : EqOn f g U ∨ ∀ᶠ x in codiscreteWithin U, f x ≠ g x := + (eqOn_zero_or_eventually_ne_zero_of_preconnected (hf.sub hg) hU).imp + (fun h _ hx ↦ eq_of_sub_eq_zero (h hx)) + (by simp only [Pi.sub_apply, ne_eq, sub_eq_zero, imp_self]) + +theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOnNhd 𝕜 f U) (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) (h₀ : z₀ ∈ U) (hfg : z₀ ∈ closure ({z | f z = g z} \ {z₀})) : EqOn f g U := hf.eqOn_of_preconnected_of_frequently_eq hg hU h₀ (mem_closure_ne_iff_frequently_within.mp hfg) @@ -261,10 +276,13 @@ theorem eqOn_of_preconnected_of_mem_closure (hf : AnalyticOn 𝕜 f U) (hg : Ana field `𝕜` are analytic everywhere and coincide at points which accumulate to a point `z₀`, then they coincide globally. For higher-dimensional versions requiring that the functions coincide in a neighborhood of `z₀`, -see `AnalyticOn.eq_of_eventuallyEq`. -/ -theorem eq_of_frequently_eq [ConnectedSpace 𝕜] (hf : AnalyticOn 𝕜 f univ) (hg : AnalyticOn 𝕜 g univ) - (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : f = g := +see `AnalyticOnNhd.eq_of_eventuallyEq`. -/ +theorem eq_of_frequently_eq [ConnectedSpace 𝕜] (hf : AnalyticOnNhd 𝕜 f univ) + (hg : AnalyticOnNhd 𝕜 g univ) (hfg : ∃ᶠ z in 𝓝[≠] z₀, f z = g z) : f = g := funext fun x => eqOn_of_preconnected_of_frequently_eq hf hg isPreconnected_univ (mem_univ z₀) hfg (mem_univ x) -end AnalyticOn +@[deprecated (since := "2024-09-26")] +alias _root_.AnalyticOn.eq_of_frequently_eq := eq_of_frequently_eq + +end AnalyticOnNhd diff --git a/Mathlib/Analysis/Analytic/Linear.lean b/Mathlib/Analysis/Analytic/Linear.lean index ee4fa10f65092..e527cda45057c 100644 --- a/Mathlib/Analysis/Analytic/Linear.lean +++ b/Mathlib/Analysis/Analytic/Linear.lean @@ -44,15 +44,18 @@ protected theorem hasFPowerSeriesAt (f : E →L[𝕜] F) (x : E) : protected theorem analyticAt (f : E →L[𝕜] F) (x : E) : AnalyticAt 𝕜 f x := (f.hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd (f : E →L[𝕜] F) (s : Set E) : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := ContinuousLinearMap.analyticOn + /-- Reinterpret a bilinear map `f : E →L[𝕜] F →L[𝕜] G` as a multilinear map `(E × F) [×2]→L[𝕜] G`. This multilinear map is the second term in the formal multilinear series expansion of `uncurry f`. It is given by @@ -121,9 +124,17 @@ protected theorem analyticAt_bilinear (f : E →L[𝕜] F →L[𝕜] G) (x : E AnalyticAt 𝕜 (fun x : E × F => f x.1 x.2) x := (f.hasFPowerSeriesAt_bilinear x).analyticAt +protected theorem analyticWithinAt_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) (x : E × F) : + AnalyticWithinAt 𝕜 (fun x : E × F => f x.1 x.2) s x := + (f.analyticAt_bilinear x).analyticWithinAt + +protected theorem analyticOnNhd_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) : + AnalyticOnNhd 𝕜 (fun x : E × F => f x.1 x.2) s := + fun x _ ↦ f.analyticAt_bilinear x + protected theorem analyticOn_bilinear (f : E →L[𝕜] F →L[𝕜] G) (s : Set (E × F)) : AnalyticOn 𝕜 (fun x : E × F => f x.1 x.2) s := - fun x _ ↦ f.analyticAt_bilinear x + (f.analyticOnNhd_bilinear s).analyticOn end ContinuousLinearMap @@ -136,12 +147,15 @@ lemma analyticWithinAt_id : AnalyticWithinAt 𝕜 (id : E → E) s z := analyticAt_id.analyticWithinAt /-- `id` is entire -/ -theorem analyticOn_id : AnalyticOn 𝕜 (fun x : E ↦ x) s := +theorem analyticOnNhd_id : AnalyticOnNhd 𝕜 (fun x : E ↦ x) s := fun _ _ ↦ analyticAt_id -theorem analyticWithinOn_id : AnalyticWithinOn 𝕜 (fun x : E ↦ x) s := +theorem analyticOn_id : AnalyticOn 𝕜 (fun x : E ↦ x) s := fun _ _ ↦ analyticWithinAt_id +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_id := analyticOn_id + /-- `fst` is analytic -/ theorem analyticAt_fst : AnalyticAt 𝕜 (fun p : E × F ↦ p.fst) p := (ContinuousLinearMap.fst 𝕜 E F).analyticAt p @@ -157,19 +171,25 @@ theorem analyticWithinAt_snd : AnalyticWithinAt 𝕜 (fun p : E × F ↦ p.snd) analyticAt_snd.analyticWithinAt /-- `fst` is entire -/ -theorem analyticOn_fst : AnalyticOn 𝕜 (fun p : E × F ↦ p.fst) t := +theorem analyticOnNhd_fst : AnalyticOnNhd 𝕜 (fun p : E × F ↦ p.fst) t := fun _ _ ↦ analyticAt_fst -theorem analyticWithinOn_fst : AnalyticWithinOn 𝕜 (fun p : E × F ↦ p.fst) t := +theorem analyticOn_fst : AnalyticOn 𝕜 (fun p : E × F ↦ p.fst) t := fun _ _ ↦ analyticWithinAt_fst +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_fst := analyticOn_fst + /-- `snd` is entire -/ -theorem analyticOn_snd : AnalyticOn 𝕜 (fun p : E × F ↦ p.snd) t := +theorem analyticOnNhd_snd : AnalyticOnNhd 𝕜 (fun p : E × F ↦ p.snd) t := fun _ _ ↦ analyticAt_snd -theorem analyticWithinOn_snd : AnalyticWithinOn 𝕜 (fun p : E × F ↦ p.snd) t := +theorem analyticOn_snd : AnalyticOn 𝕜 (fun p : E × F ↦ p.snd) t := fun _ _ ↦ analyticWithinAt_snd +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_snd := analyticOn_snd + namespace ContinuousLinearEquiv variable (f : E ≃L[𝕜] F) (s : Set E) (x : E) @@ -177,15 +197,18 @@ variable (f : E ≃L[𝕜] F) (s : Set E) (x : E) protected theorem analyticAt : AnalyticAt 𝕜 f x := ((f : E →L[𝕜] F).hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := ContinuousLinearEquiv.analyticOn + end ContinuousLinearEquiv namespace LinearIsometryEquiv @@ -195,13 +218,16 @@ variable (f : E ≃ₗᵢ[𝕜] F) (s : Set E) (x : E) protected theorem analyticAt : AnalyticAt 𝕜 f x := ((f : E →L[𝕜] F).hasFPowerSeriesAt x).analyticAt -protected theorem analyticOn : AnalyticOn 𝕜 f s := +protected theorem analyticOnNhd : AnalyticOnNhd 𝕜 f s := fun x _ ↦ f.analyticAt x protected theorem analyticWithinAt (f : E →L[𝕜] F) (s : Set E) (x : E) : AnalyticWithinAt 𝕜 f s x := (f.analyticAt x).analyticWithinAt -protected theorem analyticWithinOn (f : E →L[𝕜] F) (s : Set E) : AnalyticWithinOn 𝕜 f s := +protected theorem analyticOn (f : E →L[𝕜] F) (s : Set E) : AnalyticOn 𝕜 f s := fun x _ ↦ f.analyticWithinAt _ x +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn := LinearIsometryEquiv.analyticOn + end LinearIsometryEquiv diff --git a/Mathlib/Analysis/Analytic/Meromorphic.lean b/Mathlib/Analysis/Analytic/Meromorphic.lean index 1a29b6bb5cff9..be73e28bbbfe1 100644 --- a/Mathlib/Analysis/Analytic/Meromorphic.lean +++ b/Mathlib/Analysis/Analytic/Meromorphic.lean @@ -59,8 +59,8 @@ lemma smul {f : 𝕜 → 𝕜} {g : 𝕜 → E} {x : 𝕜} (hf : MeromorphicAt f 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'] + rw [Pi.smul_apply', smul_eq_mul] + module lemma mul {f g : 𝕜 → 𝕜} {x : 𝕜} (hf : MeromorphicAt f x) (hg : MeromorphicAt g x) : MeromorphicAt (f * g) x := @@ -227,8 +227,8 @@ lemma iff_eventuallyEq_zpow_smul_analyticAt {f : 𝕜 → E} {x : 𝕜} : Meromo ∃ (n : ℤ) (g : 𝕜 → E), AnalyticAt 𝕜 g x ∧ ∀ᶠ z in 𝓝[≠] x, f z = (z - x) ^ n • g z := by refine ⟨fun ⟨n, hn⟩ ↦ ⟨-n, _, ⟨hn, eventually_nhdsWithin_iff.mpr ?_⟩⟩, ?_⟩ · filter_upwards with z hz - rw [← mul_smul, ← zpow_natCast, ← zpow_add₀ (sub_ne_zero.mpr hz), neg_add_cancel, - zpow_zero, one_smul] + match_scalars + field_simp [sub_ne_zero.mpr hz] · refine fun ⟨n, g, hg_an, hg_eq⟩ ↦ MeromorphicAt.congr ?_ (EventuallyEq.symm hg_eq) exact (((MeromorphicAt.id x).sub (.const _ x)).zpow _).smul hg_an.meromorphicAt @@ -237,10 +237,12 @@ end MeromorphicAt /-- Meromorphy of a function on a set. -/ def MeromorphicOn (f : 𝕜 → E) (U : Set 𝕜) : Prop := ∀ x ∈ U, MeromorphicAt f x -lemma AnalyticOn.meromorphicOn {f : 𝕜 → E} {U : Set 𝕜} (hf : AnalyticOn 𝕜 f U) : +lemma AnalyticOnNhd.meromorphicOn {f : 𝕜 → E} {U : Set 𝕜} (hf : AnalyticOnNhd 𝕜 f U) : MeromorphicOn f U := fun x hx ↦ (hf x hx).meromorphicAt +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.meromorphicOn := AnalyticOnNhd.meromorphicOn namespace MeromorphicOn diff --git a/Mathlib/Analysis/Analytic/Polynomial.lean b/Mathlib/Analysis/Analytic/Polynomial.lean index 74ea377c682ac..77e62fd5b542b 100644 --- a/Mathlib/Analysis/Analytic/Polynomial.lean +++ b/Mathlib/Analysis/Analytic/Polynomial.lean @@ -23,17 +23,28 @@ open Polynomial variable [NormedRing B] [NormedAlgebra 𝕜 B] [Algebra A B] {f : E → B} -theorem AnalyticAt.aeval_polynomial (hf : AnalyticAt 𝕜 f z) (p : A[X]) : - AnalyticAt 𝕜 (fun x ↦ aeval (f x) p) z := by +theorem AnalyticWithinAt.aeval_polynomial (hf : AnalyticWithinAt 𝕜 f s z) (p : A[X]) : + AnalyticWithinAt 𝕜 (fun x ↦ aeval (f x) p) s z := by refine p.induction_on (fun k ↦ ?_) (fun p q hp hq ↦ ?_) fun p i hp ↦ ?_ - · simp_rw [aeval_C]; apply analyticAt_const + · simp_rw [aeval_C]; apply analyticWithinAt_const · simp_rw [aeval_add]; exact hp.add hq · convert hp.mul hf simp_rw [pow_succ, aeval_mul, ← mul_assoc, aeval_X] +theorem AnalyticAt.aeval_polynomial (hf : AnalyticAt 𝕜 f z) (p : A[X]) : + AnalyticAt 𝕜 (fun x ↦ aeval (f x) p) z := by + rw [← analyticWithinAt_univ] at hf ⊢ + exact hf.aeval_polynomial p + +theorem AnalyticOnNhd.aeval_polynomial (hf : AnalyticOnNhd 𝕜 f s) (p : A[X]) : + AnalyticOnNhd 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ (hf x hx).aeval_polynomial p + theorem AnalyticOn.aeval_polynomial (hf : AnalyticOn 𝕜 f s) (p : A[X]) : AnalyticOn 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ (hf x hx).aeval_polynomial p +theorem AnalyticOnNhd.eval_polynomial {A} [NormedCommRing A] [NormedAlgebra 𝕜 A] (p : A[X]) : + AnalyticOnNhd 𝕜 (eval · p) Set.univ := analyticOnNhd_id.aeval_polynomial p + theorem AnalyticOn.eval_polynomial {A} [NormedCommRing A] [NormedAlgebra 𝕜 A] (p : A[X]) : AnalyticOn 𝕜 (eval · p) Set.univ := analyticOn_id.aeval_polynomial p @@ -51,27 +62,47 @@ theorem AnalyticAt.aeval_mvPolynomial (hf : ∀ i, AnalyticAt 𝕜 (f · i) z) ( · simp_rw [map_add]; exact hp.add hq · simp_rw [map_mul, aeval_X]; exact hp.mul (hf i) -theorem AnalyticOn.aeval_mvPolynomial (hf : ∀ i, AnalyticOn 𝕜 (f · i) s) (p : MvPolynomial σ A) : - AnalyticOn 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ .aeval_mvPolynomial (hf · x hx) p +theorem AnalyticOnNhd.aeval_mvPolynomial + (hf : ∀ i, AnalyticOnNhd 𝕜 (f · i) s) (p : MvPolynomial σ A) : + AnalyticOnNhd 𝕜 (fun x ↦ aeval (f x) p) s := fun x hx ↦ .aeval_mvPolynomial (hf · x hx) p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.aeval_mvPolynomial := AnalyticOnNhd.aeval_mvPolynomial -theorem AnalyticOn.eval_continuousLinearMap (f : E →L[𝕜] σ → B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f x) p) Set.univ := +theorem AnalyticOnNhd.eval_continuousLinearMap (f : E →L[𝕜] σ → B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f x) p) Set.univ := fun x _ ↦ .aeval_mvPolynomial (fun i ↦ ((ContinuousLinearMap.proj i).comp f).analyticAt x) p -theorem AnalyticOn.eval_continuousLinearMap' (f : σ → E →L[𝕜] B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f · x) p) Set.univ := +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_continuousLinearMap := AnalyticOnNhd.eval_continuousLinearMap + +theorem AnalyticOnNhd.eval_continuousLinearMap' (f : σ → E →L[𝕜] B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f · x) p) Set.univ := fun x _ ↦ .aeval_mvPolynomial (fun i ↦ (f i).analyticAt x) p +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_continuousLinearMap' := AnalyticOnNhd.eval_continuousLinearMap' + variable [CompleteSpace 𝕜] [T2Space E] [FiniteDimensional 𝕜 E] -theorem AnalyticOn.eval_linearMap (f : E →ₗ[𝕜] σ → B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f x) p) Set.univ := - AnalyticOn.eval_continuousLinearMap { f with cont := f.continuous_of_finiteDimensional } p +theorem AnalyticOnNhd.eval_linearMap (f : E →ₗ[𝕜] σ → B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f x) p) Set.univ := + AnalyticOnNhd.eval_continuousLinearMap { f with cont := f.continuous_of_finiteDimensional } p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_linearMap := AnalyticOnNhd.eval_linearMap + +theorem AnalyticOnNhd.eval_linearMap' (f : σ → E →ₗ[𝕜] B) (p : MvPolynomial σ B) : + AnalyticOnNhd 𝕜 (fun x ↦ eval (f · x) p) Set.univ := AnalyticOnNhd.eval_linearMap (.pi f) p + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_linearMap' := AnalyticOnNhd.eval_linearMap' -theorem AnalyticOn.eval_linearMap' (f : σ → E →ₗ[𝕜] B) (p : MvPolynomial σ B) : - AnalyticOn 𝕜 (fun x ↦ eval (f · x) p) Set.univ := AnalyticOn.eval_linearMap (.pi f) p +theorem AnalyticOnNhd.eval_mvPolynomial [Fintype σ] (p : MvPolynomial σ 𝕜) : + AnalyticOnNhd 𝕜 (eval · p) Set.univ := + AnalyticOnNhd.eval_linearMap (.id (R := 𝕜) (M := σ → 𝕜)) p -theorem AnalyticOn.eval_mvPolynomial [Fintype σ] (p : MvPolynomial σ 𝕜) : - AnalyticOn 𝕜 (eval · p) Set.univ := AnalyticOn.eval_linearMap (.id (R := 𝕜) (M := σ → 𝕜)) p +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.eval_mvPolynomial := AnalyticOnNhd.eval_mvPolynomial end MvPolynomial diff --git a/Mathlib/Analysis/Analytic/RadiusLiminf.lean b/Mathlib/Analysis/Analytic/RadiusLiminf.lean index 175d6acca7461..6aefcab0e900e 100644 --- a/Mathlib/Analysis/Analytic/RadiusLiminf.lean +++ b/Mathlib/Analysis/Analytic/RadiusLiminf.lean @@ -53,7 +53,7 @@ theorem radius_eq_liminf : refine H.mp ((eventually_gt_atTop 0).mono fun n hn₀ hn => (this _ hn₀).2 (NNReal.coe_le_coe.1 ?_)) push_cast - exact (le_abs_self _).trans (hn.trans (pow_le_one _ ha.1.le ha.2.le)) + exact (le_abs_self _).trans (hn.trans (pow_le_one₀ ha.1.le ha.2.le)) · refine p.le_radius_of_isBigO (IsBigO.of_bound 1 ?_) refine (eventually_lt_of_lt_liminf hr).mp ((eventually_gt_atTop 0).mono fun n hn₀ hn => ?_) simpa using NNReal.coe_le_coe.2 ((this _ hn₀).1 hn.le) diff --git a/Mathlib/Analysis/Analytic/Uniqueness.lean b/Mathlib/Analysis/Analytic/Uniqueness.lean index 088cf07ea867d..6c836c8afcab6 100644 --- a/Mathlib/Analysis/Analytic/Uniqueness.lean +++ b/Mathlib/Analysis/Analytic/Uniqueness.lean @@ -13,7 +13,7 @@ import Mathlib.Analysis.Analytic.ChangeOrigin # Uniqueness principle for analytic functions We show that two analytic functions which coincide around a point coincide on whole connected sets, -in `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`. +in `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`. -/ @@ -154,13 +154,14 @@ theorem HasFPowerSeriesOnBall.r_eq_top_of_exists {f : 𝕜 → E} {r : ℝ≥0 end Uniqueness -namespace AnalyticOn +namespace AnalyticOnNhd /-- If an analytic function vanishes around a point, then it is uniformly zero along a connected set. Superseded by `eqOn_zero_of_preconnected_of_locally_zero` which does not assume completeness of the target space. -/ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero_aux [CompleteSpace F] {f : E → F} {U : Set E} - (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : + (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) + {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : EqOn f 0 U := by /- Let `u` be the set of points around which `f` vanishes. It is clearly open. We have to show that its limit points in `U` still belong to it, from which the inclusion `U ⊆ u` will follow @@ -204,11 +205,12 @@ neighborhood of a point `z₀`, then it is uniformly zero along a connected set. version assuming only that the function vanishes at some points arbitrarily close to `z₀`, see `eqOn_zero_of_preconnected_of_frequently_eq_zero`. -/ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero {f : E → F} {U : Set E} - (hf : AnalyticOn 𝕜 f U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : + (hf : AnalyticOnNhd 𝕜 f U) (hU : IsPreconnected U) + {z₀ : E} (h₀ : z₀ ∈ U) (hfz₀ : f =ᶠ[𝓝 z₀] 0) : EqOn f 0 U := by let F' := UniformSpace.Completion F set e : F →L[𝕜] F' := UniformSpace.Completion.toComplL - have : AnalyticOn 𝕜 (e ∘ f) U := fun x hx => (e.analyticAt _).comp (hf x hx) + have : AnalyticOnNhd 𝕜 (e ∘ f) U := fun x hx => (e.analyticAt _).comp (hf x hx) have A : EqOn (e ∘ f) 0 U := by apply eqOn_zero_of_preconnected_of_eventuallyEq_zero_aux this hU h₀ filter_upwards [hfz₀] with x hx @@ -221,8 +223,8 @@ theorem eqOn_zero_of_preconnected_of_eventuallyEq_zero {f : E → F} {U : Set E} neighborhood of a point `z₀`, then they coincide globally along a connected set. For a one-dimensional version assuming only that the functions coincide at some points arbitrarily close to `z₀`, see `eqOn_of_preconnected_of_frequently_eq`. -/ -theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : AnalyticOn 𝕜 f U) - (hg : AnalyticOn 𝕜 g U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfg : f =ᶠ[𝓝 z₀] g) : +theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : AnalyticOnNhd 𝕜 f U) + (hg : AnalyticOnNhd 𝕜 g U) (hU : IsPreconnected U) {z₀ : E} (h₀ : z₀ ∈ U) (hfg : f =ᶠ[𝓝 z₀] g) : EqOn f g U := by have hfg' : f - g =ᶠ[𝓝 z₀] 0 := hfg.mono fun z h => by simp [h] simpa [sub_eq_zero] using fun z hz => @@ -232,9 +234,9 @@ theorem eqOn_of_preconnected_of_eventuallyEq {f g : E → F} {U : Set E} (hf : A coincide in a neighborhood of a point `z₀`, then they coincide everywhere. For a one-dimensional version assuming only that the functions coincide at some points arbitrarily close to `z₀`, see `eq_of_frequently_eq`. -/ -theorem eq_of_eventuallyEq {f g : E → F} [PreconnectedSpace E] (hf : AnalyticOn 𝕜 f univ) - (hg : AnalyticOn 𝕜 g univ) {z₀ : E} (hfg : f =ᶠ[𝓝 z₀] g) : f = g := +theorem eq_of_eventuallyEq {f g : E → F} [PreconnectedSpace E] (hf : AnalyticOnNhd 𝕜 f univ) + (hg : AnalyticOnNhd 𝕜 g univ) {z₀ : E} (hfg : f =ᶠ[𝓝 z₀] g) : f = g := funext fun x => eqOn_of_preconnected_of_eventuallyEq hf hg isPreconnected_univ (mem_univ z₀) hfg (mem_univ x) -end AnalyticOn +end AnalyticOnNhd diff --git a/Mathlib/Analysis/Analytic/Within.lean b/Mathlib/Analysis/Analytic/Within.lean index 7b1093877a659..7703eb9524ef0 100644 --- a/Mathlib/Analysis/Analytic/Within.lean +++ b/Mathlib/Analysis/Analytic/Within.lean @@ -11,7 +11,7 @@ import Mathlib.Analysis.Analytic.Constructions From `Mathlib.Analysis.Analytic.Basic`, we have the definitions 1. `AnalyticWithinAt 𝕜 f s x` means a power series at `x` converges to `f` on `𝓝[insert x s] x`. -2. `AnalyticWithinOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. +2. `AnalyticOn 𝕜 f s t` means `∀ x ∈ t, AnalyticWithinAt 𝕜 f s x`. This means there exists an extension of `f` which is analytic and agrees with `f` on `s ∪ {x}`, but `f` is allowed to be arbitrary elsewhere. @@ -56,10 +56,10 @@ lemma analyticWithinAt_of_singleton_mem {f : E → F} {s : Set E} {x : E} (h : { apply (hasFPowerSeriesOnBall_const (e := 0)).hasSum simp only [Metric.emetric_ball_top, mem_univ] }⟩ -/-- If `f` is `AnalyticWithinOn` near each point in a set, it is `AnalyticWithinOn` the set -/ -lemma analyticWithinOn_of_locally_analyticWithinOn {f : E → F} {s : Set E} - (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ AnalyticWithinOn 𝕜 f (s ∩ u)) : - AnalyticWithinOn 𝕜 f s := by +/-- If `f` is `AnalyticOn` near each point in a set, it is `AnalyticOn` the set -/ +lemma analyticOn_of_locally_analyticOn {f : E → F} {s : Set E} + (h : ∀ x ∈ s, ∃ u, IsOpen u ∧ x ∈ u ∧ AnalyticOn 𝕜 f (s ∩ u)) : + AnalyticOn 𝕜 f s := by intro x m rcases h x m with ⟨u, ou, xu, fu⟩ rcases Metric.mem_nhds_iff.mp (ou.mem_nhds xu) with ⟨r, r0, ru⟩ @@ -79,10 +79,13 @@ lemma analyticWithinOn_of_locally_analyticWithinOn {f : E → F} {s : Set E} simp only [Metric.mem_ball, dist_self_add_left, yr] · simp only [EMetric.mem_ball, yr] }⟩ -/-- On open sets, `AnalyticOn` and `AnalyticWithinOn` coincide -/ -lemma IsOpen.analyticWithinOn_iff_analyticOn {f : E → F} {s : Set E} (hs : IsOpen s) : - AnalyticWithinOn 𝕜 f s ↔ AnalyticOn 𝕜 f s := by - refine ⟨?_, AnalyticOn.analyticWithinOn⟩ +@[deprecated (since := "2024-09-26")] +alias analyticWithinOn_of_locally_analyticWithinOn := analyticOn_of_locally_analyticOn + +/-- On open sets, `AnalyticOnNhd` and `AnalyticOn` coincide -/ +lemma IsOpen.analyticOn_iff_analyticOnNhd {f : E → F} {s : Set E} (hs : IsOpen s) : + AnalyticOn 𝕜 f s ↔ AnalyticOnNhd 𝕜 f s := by + refine ⟨?_, AnalyticOnNhd.analyticOn⟩ intro hf x m rcases Metric.mem_nhds_iff.mp (hs.mem_nhds m) with ⟨r, r0, rs⟩ rcases hf x m with ⟨p, t, fp⟩ @@ -97,13 +100,16 @@ lemma IsOpen.analyticWithinOn_iff_analyticOn {f : E → F} {s : Set E} (hs : IsO apply rs simp only [Metric.mem_ball, dist_self_add_left, ym.1] }⟩ +@[deprecated (since := "2024-09-26")] +alias IsOpen.analyticWithinOn_iff_analyticOn := IsOpen.analyticOn_iff_analyticOnNhd + /-! ### Equivalence to analyticity of a local extension We show that `HasFPowerSeriesWithinOnBall`, `HasFPowerSeriesWithinAt`, and `AnalyticWithinAt` are equivalent to the existence of a local extension with full analyticity. We do not yet show a -result for `AnalyticWithinOn`, as this requires a bit more work to show that local extensions can +result for `AnalyticOn`, as this requires a bit more work to show that local extensions can be stitched together. -/ diff --git a/Mathlib/Analysis/Asymptotics/Asymptotics.lean b/Mathlib/Analysis/Asymptotics/Asymptotics.lean index fda3788c247e8..15ae960d1d41e 100644 --- a/Mathlib/Analysis/Asymptotics/Asymptotics.lean +++ b/Mathlib/Analysis/Asymptotics/Asymptotics.lean @@ -128,13 +128,13 @@ theorem isBigO_iff'' {g : α → E'''} : obtain ⟨c, ⟨hc_pos, hc⟩⟩ := h refine ⟨c⁻¹, ⟨by positivity, ?_⟩⟩ filter_upwards [hc] with x hx - rwa [inv_mul_le_iff (by positivity)] + rwa [inv_mul_le_iff₀ (by positivity)] case mpr => rw [isBigO_iff'] obtain ⟨c, ⟨hc_pos, hc⟩⟩ := h refine ⟨c⁻¹, ⟨by positivity, ?_⟩⟩ filter_upwards [hc] with x hx - rwa [← inv_inv c, inv_mul_le_iff (by positivity)] at hx + rwa [← inv_inv c, inv_mul_le_iff₀ (by positivity)] at hx theorem IsBigO.of_bound (c : ℝ) (h : ∀ᶠ x in l, ‖f x‖ ≤ c * ‖g x‖) : f =O[l] g := isBigO_iff.2 ⟨c, h⟩ @@ -251,7 +251,7 @@ theorem isLittleO_iff_nat_mul_le_aux (h₀ : (∀ x, 0 ≤ ‖f x‖) ∨ ∀ x, rcases exists_nat_gt ε⁻¹ with ⟨n, hn⟩ have hn₀ : (0 : ℝ) < n := (inv_pos.2 ε0).trans hn refine ((isBigOWith_inv hn₀).2 (H n)).bound.mono fun x hfg => ?_ - refine hfg.trans (mul_le_mul_of_nonneg_right (inv_le_of_inv_le ε0 hn.le) ?_) + refine hfg.trans (mul_le_mul_of_nonneg_right (inv_le_of_inv_le₀ ε0 hn.le) ?_) refine h₀.elim (fun hf => nonneg_of_mul_nonneg_right ((hf x).trans hfg) ?_) fun h => h x exact inv_pos.2 hn₀ @@ -1251,6 +1251,9 @@ theorem IsLittleO.trans_tendsto (hfg : f'' =o[l] g'') (hg : Tendsto g'' l (𝓝 Tendsto f'' l (𝓝 0) := hfg.isBigO.trans_tendsto hg +lemma isLittleO_id_one [One F''] [NeZero (1 : F'')] : (fun x : E'' => x) =o[𝓝 0] (1 : E'' → F'') := + isLittleO_id_const one_ne_zero + /-! ### Multiplication by a constant -/ @@ -1447,7 +1450,7 @@ theorem IsBigOWith.inv_rev {f : α → 𝕜} {g : α → 𝕜'} (h : IsBigOWith rcases eq_or_ne (f x) 0 with hx | hx · simp only [hx, h₀ hx, inv_zero, norm_zero, mul_zero, le_rfl] · have hc : 0 < c := pos_of_mul_pos_left ((norm_pos_iff.2 hx).trans_le hle) (norm_nonneg _) - replace hle := inv_le_inv_of_le (norm_pos_iff.2 hx) hle + replace hle := inv_anti₀ (norm_pos_iff.2 hx) hle simpa only [norm_inv, mul_inv, ← div_eq_inv_mul, div_le_iff₀ hc] using hle theorem IsBigO.inv_rev {f : α → 𝕜} {g : α → 𝕜'} (h : f =O[l] g) @@ -1700,7 +1703,7 @@ theorem isBigOWith_iff_exists_eq_mul (hc : 0 ≤ c) : · intro h use fun x => u x / v x refine ⟨Eventually.mono h.bound fun y hy => ?_, h.eventually_mul_div_cancel.symm⟩ - simpa using div_le_of_nonneg_of_le_mul (norm_nonneg _) hc hy + simpa using div_le_of_le_mul₀ (norm_nonneg _) hc hy · rintro ⟨φ, hφ, h⟩ exact isBigOWith_of_eq_mul φ hφ h @@ -1741,7 +1744,7 @@ theorem div_isBoundedUnder_of_isBigO {α : Type*} {l : Filter α} {f g : α → obtain ⟨c, h₀, hc⟩ := h.exists_nonneg refine ⟨c, eventually_map.2 (hc.bound.mono fun x hx => ?_)⟩ rw [norm_div] - exact div_le_of_nonneg_of_le_mul (norm_nonneg _) h₀ hx + exact div_le_of_le_mul₀ (norm_nonneg _) h₀ hx theorem isBigO_iff_div_isBoundedUnder {α : Type*} {l : Filter α} {f g : α → 𝕜} (hgf : ∀ᶠ x in l, g x = 0 → f x = 0) : @@ -1915,6 +1918,13 @@ theorem isBigO_atTop_iff_eventually_exists_pos {α : Type*} f =O[atTop] g ↔ ∀ᶠ n₀ in atTop, ∃ c > 0, ∀ n ≥ n₀, c * ‖f n‖ ≤ ‖g n‖ := by simp_rw [isBigO_iff'', ← exists_prop, Subtype.exists', exists_eventually_atTop] +lemma isBigO_mul_iff_isBigO_div {f g h : α → 𝕜} (hf : ∀ᶠ x in l, f x ≠ 0) : + (fun x ↦ f x * g x) =O[l] h ↔ g =O[l] (fun x ↦ h x / f x) := by + rw [isBigO_iff', isBigO_iff'] + refine ⟨fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩, fun ⟨c, hc, H⟩ ↦ ⟨c, hc, ?_⟩⟩ <;> + · refine H.congr <| Eventually.mp hf <| Eventually.of_forall fun x hx ↦ ?_ + rw [norm_mul, norm_div, ← mul_div_assoc, le_div_iff₀' (norm_pos_iff.mpr hx)] + end Asymptotics open Asymptotics diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean index d1e7e6f1539c8..180ca90ca5288 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Instances.lean @@ -218,7 +218,7 @@ lemma QuasispectrumRestricts.isSelfAdjoint (a : A) (ha : QuasispectrumRestricts instance IsSelfAdjoint.instNonUnitalContinuousFunctionalCalculus : NonUnitalContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop) := QuasispectrumRestricts.cfc (q := IsStarNormal) (p := IsSelfAdjoint) Complex.reCLM - Complex.isometry_ofReal.uniformEmbedding (.zero _) + Complex.isometry_ofReal.isUniformEmbedding (.zero _) (fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_quasispectrumRestricts) end SelfAdjointNonUnital @@ -264,7 +264,7 @@ lemma SpectrumRestricts.isSelfAdjoint (a : A) (ha : SpectrumRestricts a Complex. instance IsSelfAdjoint.instContinuousFunctionalCalculus : ContinuousFunctionalCalculus ℝ (IsSelfAdjoint : A → Prop) := SpectrumRestricts.cfc (q := IsStarNormal) (p := IsSelfAdjoint) Complex.reCLM - Complex.isometry_ofReal.uniformEmbedding (.zero _) + Complex.isometry_ofReal.isUniformEmbedding (.zero _) (fun _ ↦ isSelfAdjoint_iff_isStarNormal_and_spectrumRestricts) lemma IsSelfAdjoint.spectrum_nonempty {A : Type*} [Ring A] [StarRing A] @@ -313,7 +313,7 @@ open NNReal in instance Nonneg.instNonUnitalContinuousFunctionalCalculus : NonUnitalContinuousFunctionalCalculus ℝ≥0 (fun x : A ↦ 0 ≤ x) := QuasispectrumRestricts.cfc (q := IsSelfAdjoint) ContinuousMap.realToNNReal - uniformEmbedding_subtype_val le_rfl + isUniformEmbedding_subtype_val le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_quasispectrumRestricts) open NNReal in @@ -359,7 +359,7 @@ open NNReal in instance Nonneg.instContinuousFunctionalCalculus : ContinuousFunctionalCalculus ℝ≥0 (fun x : A ↦ 0 ≤ x) := SpectrumRestricts.cfc (q := IsSelfAdjoint) ContinuousMap.realToNNReal - uniformEmbedding_subtype_val le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_spectrumRestricts) + isUniformEmbedding_subtype_val le_rfl (fun _ ↦ nonneg_iff_isSelfAdjoint_and_spectrumRestricts) end Nonneg @@ -605,14 +605,14 @@ variable {A : Type*} [TopologicalSpace A] [Ring A] [StarRing A] [Algebra ℂ A] lemma cfcHom_real_eq_restrict {a : A} (ha : IsSelfAdjoint a) : cfcHom ha = ha.spectrumRestricts.starAlgHom (cfcHom ha.isStarNormal) (f := Complex.reCLM) := - ha.spectrumRestricts.cfcHom_eq_restrict Complex.isometry_ofReal.uniformEmbedding + ha.spectrumRestricts.cfcHom_eq_restrict _ Complex.isometry_ofReal.isUniformEmbedding ha ha.isStarNormal lemma cfc_real_eq_complex {a : A} (f : ℝ → ℝ) (ha : IsSelfAdjoint a := by cfc_tac) : cfc f a = cfc (fun x ↦ f x.re : ℂ → ℂ) a := by replace ha : IsSelfAdjoint a := ha -- hack to avoid issues caused by autoParam exact ha.spectrumRestricts.cfc_eq_restrict (f := Complex.reCLM) - Complex.isometry_ofReal.uniformEmbedding ha ha.isStarNormal f + Complex.isometry_ofReal.isUniformEmbedding ha ha.isStarNormal f end RealEqComplex @@ -626,14 +626,14 @@ variable {A : Type*} [TopologicalSpace A] [NonUnitalRing A] [StarRing A] [Module lemma cfcₙHom_real_eq_restrict {a : A} (ha : IsSelfAdjoint a) : cfcₙHom ha = (ha.quasispectrumRestricts.2).nonUnitalStarAlgHom (cfcₙHom ha.isStarNormal) (f := Complex.reCLM) := - ha.quasispectrumRestricts.2.cfcₙHom_eq_restrict Complex.isometry_ofReal.uniformEmbedding + ha.quasispectrumRestricts.2.cfcₙHom_eq_restrict _ Complex.isometry_ofReal.isUniformEmbedding ha ha.isStarNormal lemma cfcₙ_real_eq_complex {a : A} (f : ℝ → ℝ) (ha : IsSelfAdjoint a := by cfc_tac) : cfcₙ f a = cfcₙ (fun x ↦ f x.re : ℂ → ℂ) a := by replace ha : IsSelfAdjoint a := ha -- hack to avoid issues caused by autoParam exact ha.quasispectrumRestricts.2.cfcₙ_eq_restrict (f := Complex.reCLM) - Complex.isometry_ofReal.uniformEmbedding ha ha.isStarNormal f + Complex.isometry_ofReal.isUniformEmbedding ha ha.isStarNormal f end RealEqComplexNonUnital @@ -650,13 +650,13 @@ variable {A : Type*} [TopologicalSpace A] [Ring A] [PartialOrder A] [StarRing A] lemma cfcHom_nnreal_eq_restrict {a : A} (ha : 0 ≤ a) : cfcHom ha = (SpectrumRestricts.nnreal_of_nonneg ha).starAlgHom (cfcHom (IsSelfAdjoint.of_nonneg ha)) := by - apply (SpectrumRestricts.nnreal_of_nonneg ha).cfcHom_eq_restrict uniformEmbedding_subtype_val + apply (SpectrumRestricts.nnreal_of_nonneg ha).cfcHom_eq_restrict _ isUniformEmbedding_subtype_val lemma cfc_nnreal_eq_real {a : A} (f : ℝ≥0 → ℝ≥0) (ha : 0 ≤ a := by cfc_tac) : cfc f a = cfc (fun x ↦ f x.toNNReal : ℝ → ℝ) a := by replace ha : 0 ≤ a := ha -- hack to avoid issues caused by autoParam - apply (SpectrumRestricts.nnreal_of_nonneg ha).cfc_eq_restrict - uniformEmbedding_subtype_val ha (.of_nonneg ha) + apply (SpectrumRestricts.nnreal_of_nonneg ha).cfc_eq_restrict _ + isUniformEmbedding_subtype_val ha (.of_nonneg ha) end NNRealEqReal @@ -674,14 +674,14 @@ variable {A : Type*} [TopologicalSpace A] [NonUnitalRing A] [PartialOrder A] [St lemma cfcₙHom_nnreal_eq_restrict {a : A} (ha : 0 ≤ a) : cfcₙHom ha = (QuasispectrumRestricts.nnreal_of_nonneg ha).nonUnitalStarAlgHom (cfcₙHom (IsSelfAdjoint.of_nonneg ha)) := by - apply (QuasispectrumRestricts.nnreal_of_nonneg ha).cfcₙHom_eq_restrict - uniformEmbedding_subtype_val + apply (QuasispectrumRestricts.nnreal_of_nonneg ha).cfcₙHom_eq_restrict _ + isUniformEmbedding_subtype_val lemma cfcₙ_nnreal_eq_real {a : A} (f : ℝ≥0 → ℝ≥0) (ha : 0 ≤ a := by cfc_tac) : cfcₙ f a = cfcₙ (fun x ↦ f x.toNNReal : ℝ → ℝ) a := by replace ha : 0 ≤ a := ha -- hack to avoid issues caused by autoParam - apply (QuasispectrumRestricts.nnreal_of_nonneg ha).cfcₙ_eq_restrict - uniformEmbedding_subtype_val ha (.of_nonneg ha) + apply (QuasispectrumRestricts.nnreal_of_nonneg ha).cfcₙ_eq_restrict _ + isUniformEmbedding_subtype_val ha (.of_nonneg ha) end NNRealEqRealNonUnital diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean index 6a52fbf1fd1e4..361cdc8aefebc 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/NonUnital.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Algebra.Algebra.Quasispectrum -import Mathlib.Topology.ContinuousFunction.Compact -import Mathlib.Topology.ContinuousFunction.ContinuousMapZero +import Mathlib.Topology.ContinuousMap.Compact +import Mathlib.Topology.ContinuousMap.ContinuousMapZero import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital import Mathlib.Topology.UniformSpace.CompactConvergence @@ -421,7 +421,7 @@ lemma cfcₙ_comp (g f : R → R) (a : A) ext simp rw [cfcₙ_apply .., cfcₙ_apply f a, - cfcₙ_apply _ (by convert hg) (ha := cfcₙHom_predicate (show p a from ha) _) , + cfcₙ_apply _ _ (by convert hg) (ha := cfcₙHom_predicate (show p a from ha) _), ← cfcₙHom_comp _ _] swap · exact ⟨.mk _ <| hf.restrict.codRestrict fun x ↦ by rw [sp_eq]; use x.1; simp, Subtype.ext hf0⟩ @@ -692,7 +692,7 @@ lemma closedEmbedding_cfcₙHom_of_cfcHom {a : A} (ha : p a) : let f : C(spectrum R a, σₙ R a) := ⟨_, continuous_inclusion <| spectrum_subset_quasispectrum R a⟩ refine (cfcHom_closedEmbedding ha).comp <| - (UniformInducing.uniformEmbedding ⟨?_⟩).toClosedEmbedding + (IsUniformInducing.isUniformEmbedding ⟨?_⟩).toClosedEmbedding have := uniformSpace_eq_inf_precomp_of_cover (β := R) f (0 : C(Unit, σₙ R a)) (map_continuous f).isProperMap (map_continuous 0).isProperMap <| by simp only [← Subtype.val_injective.image_injective.eq_iff, f, ContinuousMap.coe_mk, diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean index 0a89ab198431c..8536353d9475b 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Order.lean @@ -7,7 +7,7 @@ Authors: Frédéric Dupuis import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Instances import Mathlib.Analysis.CStarAlgebra.Unitization import Mathlib.Analysis.SpecialFunctions.ContinuousFunctionalCalculus.Rpow -import Mathlib.Topology.ContinuousFunction.StarOrdered +import Mathlib.Topology.ContinuousMap.StarOrdered /-! # Facts about star-ordered rings that depend on the continuous functional calculus diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean index 9a2bf73293ea6..cf36028a7922e 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Restrict.lean @@ -84,17 +84,17 @@ variable [CompleteSpace R] lemma closedEmbedding_starAlgHom {a : A} {φ : C(spectrum S a, S) →⋆ₐ[S] A} (hφ : ClosedEmbedding φ) {f : C(S, R)} (h : SpectrumRestricts a f) - (halg : UniformEmbedding (algebraMap R S)) : + (halg : IsUniformEmbedding (algebraMap R S)) : ClosedEmbedding (h.starAlgHom φ) := - hφ.comp <| UniformEmbedding.toClosedEmbedding <| .comp - (ContinuousMap.uniformEmbedding_comp _ halg) - (UniformEquiv.arrowCongr h.homeomorph.symm (.refl _) |>.uniformEmbedding) + hφ.comp <| IsUniformEmbedding.toClosedEmbedding <| .comp + (ContinuousMap.isUniformEmbedding_comp _ halg) + (UniformEquiv.arrowCongr h.homeomorph.symm (.refl _) |>.isUniformEmbedding) /-- Given a `ContinuousFunctionalCalculus S q`. If we form the predicate `p` for `a : A` characterized by: `q a` and the spectrum of `a` restricts to the scalar subring `R` via `f : C(S, R)`, then we can get a restricted functional calculus `ContinuousFunctionalCalculus R p`. -/ -protected theorem cfc (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) (h0 : p 0) +protected theorem cfc (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) (h0 : p 0) (h : ∀ a, p a ↔ q a ∧ SpectrumRestricts a f) : ContinuousFunctionalCalculus R p where predicate_zero := h0 @@ -133,14 +133,14 @@ protected theorem cfc (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) ( variable [ContinuousFunctionalCalculus R p] [UniqueContinuousFunctionalCalculus R A] -lemma cfcHom_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) +lemma cfcHom_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) (hqa : q a) (h : SpectrumRestricts a f) : cfcHom hpa = h.starAlgHom (cfcHom hqa) := by apply cfcHom_eq_of_continuous_of_map_id · exact h.closedEmbedding_starAlgHom (cfcHom_closedEmbedding hqa) halg |>.continuous · exact h.starAlgHom_id (cfcHom_id hqa) -lemma cfc_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) +lemma cfc_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) (hqa : q a) (h : SpectrumRestricts a f) (g : R → R) : cfc g a = cfc (fun x ↦ algebraMap R S (g (f x))) a := by by_cases hg : ContinuousOn g (spectrum R a) @@ -218,12 +218,12 @@ variable [CompleteSpace R] lemma closedEmbedding_nonUnitalStarAlgHom {a : A} {φ : C(σₙ S a, S)₀ →⋆ₙₐ[S] A} (hφ : ClosedEmbedding φ) {f : C(S, R)} (h : QuasispectrumRestricts a f) - (halg : UniformEmbedding (algebraMap R S)) : + (halg : IsUniformEmbedding (algebraMap R S)) : ClosedEmbedding (h.nonUnitalStarAlgHom φ) := by have : h.homeomorph.symm 0 = 0 := Subtype.ext (map_zero <| algebraMap _ _) - refine hφ.comp <| UniformEmbedding.toClosedEmbedding <| .comp - (ContinuousMapZero.uniformEmbedding_comp _ halg) - (UniformEquiv.arrowCongrLeft₀ h.homeomorph.symm this |>.uniformEmbedding) + refine hφ.comp <| IsUniformEmbedding.toClosedEmbedding <| .comp + (ContinuousMapZero.isUniformEmbedding_comp _ halg) + (UniformEquiv.arrowCongrLeft₀ h.homeomorph.symm this |>.isUniformEmbedding) variable [IsScalarTower R A A] [SMulCommClass R A A] @@ -231,7 +231,7 @@ variable [IsScalarTower R A A] [SMulCommClass R A A] characterized by: `q a` and the quasispectrum of `a` restricts to the scalar subring `R` via `f : C(S, R)`, then we can get a restricted functional calculus `NonUnitalContinuousFunctionalCalculus R p`. -/ -protected theorem cfc (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) (h0 : p 0) +protected theorem cfc (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) (h0 : p 0) (h : ∀ a, p a ↔ q a ∧ QuasispectrumRestricts a f) : NonUnitalContinuousFunctionalCalculus R p where predicate_zero := h0 @@ -275,15 +275,15 @@ protected theorem cfc (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) ( variable [NonUnitalContinuousFunctionalCalculus R p] variable [UniqueNonUnitalContinuousFunctionalCalculus R A] -lemma cfcₙHom_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) {a : A} +lemma cfcₙHom_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) (hqa : q a) (h : QuasispectrumRestricts a f) : cfcₙHom hpa = h.nonUnitalStarAlgHom (cfcₙHom hqa) := by apply cfcₙHom_eq_of_continuous_of_map_id · exact h.closedEmbedding_nonUnitalStarAlgHom (cfcₙHom_closedEmbedding hqa) halg |>.continuous · exact h.nonUnitalStarAlgHom_id (cfcₙHom_id hqa) -lemma cfcₙ_eq_restrict (f : C(S, R)) (halg : UniformEmbedding (algebraMap R S)) {a : A} (hpa : p a) - (hqa : q a) (h : QuasispectrumRestricts a f) (g : R → R) : +lemma cfcₙ_eq_restrict (f : C(S, R)) (halg : IsUniformEmbedding (algebraMap R S)) {a : A} + (hpa : p a) (hqa : q a) (h : QuasispectrumRestricts a f) (g : R → R) : cfcₙ g a = cfcₙ (fun x ↦ algebraMap R S (g (f x))) a := by by_cases hg : ContinuousOn g (σₙ R a) ∧ g 0 = 0 · obtain ⟨hg, hg0⟩ := hg diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean index e5c7cea5ca34e..155a1b6dd519c 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unique.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Analysis.Normed.Algebra.Spectrum import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.NonUnital -import Mathlib.Topology.ContinuousFunction.StoneWeierstrass +import Mathlib.Topology.ContinuousMap.StoneWeierstrass /-! # Uniqueness of the continuous functional calculus @@ -428,9 +428,9 @@ open scoped ContinuousMapZero variable {F R S A B : Type*} {p : A → Prop} {q : B → Prop} [CommSemiring R] [Nontrivial R] [StarRing R] [MetricSpace R] [TopologicalSemiring R] [ContinuousStar R] [CommRing S] [Algebra R S] - [Ring A] [StarRing A] [TopologicalSpace A] [Module R A] + [NonUnitalRing A] [StarRing A] [TopologicalSpace A] [Module R A] [IsScalarTower R A A] [SMulCommClass R A A] - [Ring B] [StarRing B] [TopologicalSpace B] [Module R B] + [NonUnitalRing B] [StarRing B] [TopologicalSpace B] [Module R B] [IsScalarTower R B B] [SMulCommClass R B B] [Module S A] [Module S B] [IsScalarTower R S A] [IsScalarTower R S B] [NonUnitalContinuousFunctionalCalculus R p] [NonUnitalContinuousFunctionalCalculus R q] diff --git a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean index e64b9cdf7d629..8b6473cba0de3 100644 --- a/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean +++ b/Mathlib/Analysis/CStarAlgebra/ContinuousFunctionalCalculus/Unital.lean @@ -7,7 +7,7 @@ import Mathlib.Algebra.Algebra.Quasispectrum import Mathlib.Algebra.Algebra.Spectrum import Mathlib.Algebra.Order.Star.Basic import Mathlib.Topology.Algebra.Polynomial -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Tactic.ContinuousFunctionalCalculus /-! @@ -723,7 +723,7 @@ noncomputable def cfcUnits (hf' : ∀ x ∈ spectrum R a, f x ≠ 0) lemma cfcUnits_pow (hf' : ∀ x ∈ spectrum R a, f x ≠ 0) (n : ℕ) (hf : ContinuousOn f (spectrum R a) := by cfc_cont_tac) (ha : p a := by cfc_tac) : (cfcUnits f a hf') ^ n = - cfcUnits (forall₂_imp (fun _ _ ↦ pow_ne_zero n) hf') (hf := hf.pow n) := by + cfcUnits _ _ (forall₂_imp (fun _ _ ↦ pow_ne_zero n) hf') (hf := hf.pow n) := by ext cases n with | zero => simp [cfc_const_one R a] @@ -778,7 +778,7 @@ lemma cfcUnits_zpow (hf' : ∀ x ∈ spectrum R a, f x ≠ 0) (n : ℤ) | negSucc n => simp only [zpow_negSucc, ← inv_pow] ext - exact cfc_pow (hf := hf.inv₀ hf') _ |>.symm + exact cfc_pow (hf := hf.inv₀ hf') .. |>.symm lemma cfc_zpow (a : Aˣ) (n : ℤ) (ha : p a := by cfc_tac) : cfc (fun x : R ↦ x ^ n) (a : A) = ↑(a ^ n) := by diff --git a/Mathlib/Analysis/CStarAlgebra/GelfandDuality.lean b/Mathlib/Analysis/CStarAlgebra/GelfandDuality.lean index c3e2791a52a09..af17ea013e3fc 100644 --- a/Mathlib/Analysis/CStarAlgebra/GelfandDuality.lean +++ b/Mathlib/Analysis/CStarAlgebra/GelfandDuality.lean @@ -6,11 +6,11 @@ Authors: Jireh Loreaux import Mathlib.Analysis.CStarAlgebra.Spectrum import Mathlib.Analysis.Normed.Group.Quotient import Mathlib.Analysis.Normed.Algebra.Basic -import Mathlib.Topology.ContinuousFunction.Units -import Mathlib.Topology.ContinuousFunction.Compact +import Mathlib.Topology.ContinuousMap.Units +import Mathlib.Topology.ContinuousMap.Compact import Mathlib.Topology.Algebra.Algebra -import Mathlib.Topology.ContinuousFunction.Ideals -import Mathlib.Topology.ContinuousFunction.StoneWeierstrass +import Mathlib.Topology.ContinuousMap.Ideals +import Mathlib.Topology.ContinuousMap.StoneWeierstrass /-! # Gelfand Duality diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean b/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean index 3da87eed2efbe..a94e81711816a 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Defs.lean @@ -269,7 +269,7 @@ lemma norm_eq_csSup [CompleteSpace A] (v : E) : let instNACG : NormedAddCommGroup E := NormedAddCommGroup.ofCore normedSpaceCore let instNS : NormedSpace ℂ E := .ofCore normedSpaceCore refine Eq.symm <| IsGreatest.csSup_eq ⟨⟨‖v‖⁻¹ • v, ?_, ?_⟩, ?_⟩ - · simpa only [norm_smul, norm_inv, norm_norm] using inv_mul_le_one_of_le le_rfl (by positivity) + · simpa only [norm_smul, norm_inv, norm_norm] using inv_mul_le_one_of_le₀ le_rfl (by positivity) · simp [norm_smul, ← norm_sq_eq, pow_two, ← mul_assoc] · rintro - ⟨w, hw, rfl⟩ calc _ ≤ ‖w‖ * ‖v‖ := norm_inner_le E diff --git a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean index afee7eea2b49e..82554bb415dee 100644 --- a/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean +++ b/Mathlib/Analysis/CStarAlgebra/Module/Synonym.lean @@ -167,7 +167,8 @@ instance [u : UniformSpace E] : UniformSpace (C⋆ᵐᵒᵈ E) := u.comap <| equ instance [Bornology E] : Bornology (C⋆ᵐᵒᵈ E) := Bornology.induced <| equiv E /-- `WithCStarModule.equiv` as a uniform equivalence between `C⋆ᵐᵒᵈ E` and `E`. -/ -def uniformEquiv [UniformSpace E] : C⋆ᵐᵒᵈ E ≃ᵤ E := equiv E |>.toUniformEquivOfUniformInducing ⟨rfl⟩ +def uniformEquiv [UniformSpace E] : C⋆ᵐᵒᵈ E ≃ᵤ E := + equiv E |>.toUniformEquivOfIsUniformInducing ⟨rfl⟩ instance [UniformSpace E] [CompleteSpace E] : CompleteSpace (C⋆ᵐᵒᵈ E) := uniformEquiv.completeSpace_iff.mpr inferInstance diff --git a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean index 248d3fa9e31ac..3c84852d4f405 100644 --- a/Mathlib/Analysis/CStarAlgebra/Multiplier.lean +++ b/Mathlib/Analysis/CStarAlgebra/Multiplier.lean @@ -534,11 +534,15 @@ instance instNormedSpace : NormedSpace 𝕜 𝓜(𝕜, A) := instance instNormedAlgebra : NormedAlgebra 𝕜 𝓜(𝕜, A) := { DoubleCentralizer.instAlgebra, DoubleCentralizer.instNormedSpace with } -theorem uniformEmbedding_toProdMulOpposite : UniformEmbedding (@toProdMulOpposite 𝕜 A _ _ _ _ _) := - uniformEmbedding_comap toProdMulOpposite_injective +theorem isUniformEmbedding_toProdMulOpposite : + IsUniformEmbedding (toProdMulOpposite (𝕜 := 𝕜) (A := A)) := + isUniformEmbedding_comap toProdMulOpposite_injective + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toProdMulOpposite := isUniformEmbedding_toProdMulOpposite instance [CompleteSpace A] : CompleteSpace 𝓜(𝕜, A) := by - rw [completeSpace_iff_isComplete_range uniformEmbedding_toProdMulOpposite.toUniformInducing] + rw [completeSpace_iff_isComplete_range isUniformEmbedding_toProdMulOpposite.isUniformInducing] apply IsClosed.isComplete simp only [range_toProdMulOpposite, Set.setOf_forall] refine isClosed_iInter fun x => isClosed_iInter fun y => isClosed_eq ?_ ?_ diff --git a/Mathlib/Analysis/CStarAlgebra/Spectrum.lean b/Mathlib/Analysis/CStarAlgebra/Spectrum.lean index c34a1be9cfe71..6d91e465acfeb 100644 --- a/Mathlib/Analysis/CStarAlgebra/Spectrum.lean +++ b/Mathlib/Analysis/CStarAlgebra/Spectrum.lean @@ -78,7 +78,7 @@ theorem unitary.spectrum_subset_circle (u : unitary E) : rw [← inv_inv (unitary.toUnits u), ← spectrum.map_inv, Set.mem_inv] at hk have : ‖k‖⁻¹ ≤ ‖(↑(unitary.toUnits u)⁻¹ : E)‖ := by simpa only [norm_inv] using norm_le_norm_of_mem hk - simpa using inv_le_of_inv_le (norm_pos_iff.mpr hnk) this + simpa using inv_le_of_inv_le₀ (norm_pos_iff.mpr hnk) this theorem spectrum.subset_circle_of_unitary {u : E} (h : u ∈ unitary E) : spectrum 𝕜 u ⊆ Metric.sphere 0 1 := @@ -263,9 +263,9 @@ end NonUnitalStarAlgHom namespace StarAlgEquiv -variable {F A B : Type*} [NormedRing A] [NormedSpace ℂ A] [SMulCommClass ℂ A A] +variable {F A B : Type*} [NonUnitalNormedRing A] [NormedSpace ℂ A] [SMulCommClass ℂ A A] variable [IsScalarTower ℂ A A] [CompleteSpace A] [StarRing A] [CStarRing A] [StarModule ℂ A] -variable [NormedRing B] [NormedSpace ℂ B] [SMulCommClass ℂ B B] [IsScalarTower ℂ B B] +variable [NonUnitalNormedRing B] [NormedSpace ℂ B] [SMulCommClass ℂ B B] [IsScalarTower ℂ B B] variable [CompleteSpace B] [StarRing B] [CStarRing B] [StarModule ℂ B] [EquivLike F A B] variable [NonUnitalAlgEquivClass F ℂ A B] [StarHomClass F A B] diff --git a/Mathlib/Analysis/CStarAlgebra/Unitization.lean b/Mathlib/Analysis/CStarAlgebra/Unitization.lean index d664e50c7c219..7a5bdee2eef6e 100644 --- a/Mathlib/Analysis/CStarAlgebra/Unitization.lean +++ b/Mathlib/Analysis/CStarAlgebra/Unitization.lean @@ -72,7 +72,7 @@ instance CStarRing.instRegularNormedAlgebra : RegularNormedAlgebra 𝕜 E where · simpa only [mem_closedBall_zero_iff, norm_smul, one_mul, norm_star] using (NNReal.le_inv_iff_mul_le ha.ne').1 (one_mul ‖a‖₊⁻¹ ▸ hk₂.le : ‖k‖₊ ≤ ‖a‖₊⁻¹) · simp only [map_smul, nnnorm_smul, mul_apply', mul_smul_comm, CStarRing.nnnorm_self_mul_star] - rwa [← NNReal.div_lt_iff (mul_pos ha ha).ne', div_eq_mul_inv, mul_inv, ← mul_assoc] + rwa [← div_lt_iff₀ (mul_pos ha ha), div_eq_mul_inv, mul_inv, ← mul_assoc] section CStarProperty diff --git a/Mathlib/Analysis/Calculus/BumpFunction/Convolution.lean b/Mathlib/Analysis/Calculus/BumpFunction/Convolution.lean index 6640b13a2e378..4b70bd94ec863 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/Convolution.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/Convolution.lean @@ -115,7 +115,7 @@ theorem ae_convolution_tendsto_right_of_locallyIntegrable tendsto_nhdsWithin_iff.2 ⟨hφ, Eventually.of_forall (fun i ↦ (φ i).rOut_pos)⟩ have := (h₀.comp (Besicovitch.tendsto_filterAt μ x₀)).comp hφ' simp only [Function.comp] at this - apply tendsto_integral_smul_of_tendsto_average_norm_sub (K ^ (FiniteDimensional.finrank ℝ G)) this + apply tendsto_integral_smul_of_tendsto_average_norm_sub (K ^ (Module.finrank ℝ G)) this · filter_upwards with i using hg.integrableOn_isCompact (isCompact_closedBall _ _) · apply tendsto_const_nhds.congr (fun i ↦ ?_) diff --git a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean index a246268057e33..d0f390973978c 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/FiniteDimension.lean @@ -25,7 +25,7 @@ the indicator function of `closedBall 0 1` with a function as above with `s = ba noncomputable section -open Set Metric TopologicalSpace Function Asymptotics MeasureTheory FiniteDimensional +open Set Metric TopologicalSpace Function Asymptotics MeasureTheory Module ContinuousLinearMap Filter MeasureTheory.Measure Bornology open scoped Pointwise Topology NNReal Convolution diff --git a/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean b/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean index 1846ced215ae9..fd3e53a98f231 100644 --- a/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean +++ b/Mathlib/Analysis/Calculus/BumpFunction/Normed.lean @@ -16,7 +16,7 @@ In this file we define `ContDiffBump.normed f μ` to be the bump function `f` no noncomputable section -open Function Filter Set Metric MeasureTheory FiniteDimensional Measure +open Function Filter Set Metric MeasureTheory Module Measure open scoped Topology namespace ContDiffBump @@ -97,7 +97,7 @@ variable (μ) theorem measure_closedBall_le_integral : (μ (closedBall c f.rIn)).toReal ≤ ∫ x, f x ∂μ := by calc (μ (closedBall c f.rIn)).toReal = ∫ x in closedBall c f.rIn, 1 ∂μ := by simp - _ = ∫ x in closedBall c f.rIn, f x ∂μ := setIntegral_congr measurableSet_closedBall + _ = ∫ x in closedBall c f.rIn, f x ∂μ := setIntegral_congr_fun measurableSet_closedBall (fun x hx ↦ (one_of_mem_closedBall f hx).symm) _ ≤ ∫ x, f x ∂μ := setIntegral_le_integral f.integrable (Eventually.of_forall (fun x ↦ f.nonneg)) diff --git a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean index f9cc1aee3a4f1..56efdab13165b 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Basic.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Basic.lean @@ -781,15 +781,20 @@ theorem ContDiff.comp₃ {g : E₁ × E₂ × E₃ → G} {f₁ : F → E₁} {f ContDiff 𝕜 n fun x => g (f₁ x, f₂ x, f₃ x) := hg.comp₂ hf₁ <| hf₂.prod hf₃ -theorem ContDiff.comp_contDiff_on₂ {g : E₁ × E₂ → G} {f₁ : F → E₁} {f₂ : F → E₂} {s : Set F} +theorem ContDiff.comp_contDiffOn₂ {g : E₁ × E₂ → G} {f₁ : F → E₁} {f₂ : F → E₂} {s : Set F} (hg : ContDiff 𝕜 n g) (hf₁ : ContDiffOn 𝕜 n f₁ s) (hf₂ : ContDiffOn 𝕜 n f₂ s) : ContDiffOn 𝕜 n (fun x => g (f₁ x, f₂ x)) s := hg.comp_contDiffOn <| hf₁.prod hf₂ -theorem ContDiff.comp_contDiff_on₃ {g : E₁ × E₂ × E₃ → G} {f₁ : F → E₁} {f₂ : F → E₂} {f₃ : F → E₃} +@[deprecated (since := "2024-10-10")] alias ContDiff.comp_contDiff_on₂ := ContDiff.comp_contDiffOn₂ + +theorem ContDiff.comp_contDiffOn₃ {g : E₁ × E₂ × E₃ → G} {f₁ : F → E₁} {f₂ : F → E₂} {f₃ : F → E₃} {s : Set F} (hg : ContDiff 𝕜 n g) (hf₁ : ContDiffOn 𝕜 n f₁ s) (hf₂ : ContDiffOn 𝕜 n f₂ s) (hf₃ : ContDiffOn 𝕜 n f₃ s) : ContDiffOn 𝕜 n (fun x => g (f₁ x, f₂ x, f₃ x)) s := - hg.comp_contDiff_on₂ hf₁ <| hf₂.prod hf₃ + hg.comp_contDiffOn₂ hf₁ <| hf₂.prod hf₃ + +@[deprecated (since := "2024-10-10")] alias ContDiff.comp_contDiff_on₃ := ContDiff.comp_contDiffOn₃ + end NAry @@ -802,7 +807,7 @@ theorem ContDiff.clm_comp {g : X → F →L[𝕜] G} {f : X → E →L[𝕜] F} theorem ContDiffOn.clm_comp {g : X → F →L[𝕜] G} {f : X → E →L[𝕜] F} {s : Set X} (hg : ContDiffOn 𝕜 n g s) (hf : ContDiffOn 𝕜 n f s) : ContDiffOn 𝕜 n (fun x => (g x).comp (f x)) s := - (isBoundedBilinearMap_comp (𝕜 := 𝕜) (E := E) (F := F) (G := G)).contDiff.comp_contDiff_on₂ hg hf + (isBoundedBilinearMap_comp (𝕜 := 𝕜) (E := E) (F := F) (G := G)).contDiff.comp_contDiffOn₂ hg hf theorem ContDiff.clm_apply {f : E → F →L[𝕜] G} {g : E → F} {n : ℕ∞} (hf : ContDiff 𝕜 n f) (hg : ContDiff 𝕜 n g) : ContDiff 𝕜 n fun x => (f x) (g x) := @@ -810,7 +815,7 @@ theorem ContDiff.clm_apply {f : E → F →L[𝕜] G} {g : E → F} {n : ℕ∞} theorem ContDiffOn.clm_apply {f : E → F →L[𝕜] G} {g : E → F} {n : ℕ∞} (hf : ContDiffOn 𝕜 n f s) (hg : ContDiffOn 𝕜 n g s) : ContDiffOn 𝕜 n (fun x => (f x) (g x)) s := - isBoundedBilinearMap_apply.contDiff.comp_contDiff_on₂ hf hg + isBoundedBilinearMap_apply.contDiff.comp_contDiffOn₂ hf hg -- Porting note: In Lean 3 we had to give implicit arguments in proofs like the following, -- to speed up elaboration. In Lean 4 this isn't necessary anymore. diff --git a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean index 75f2e43860603..08ff13d596c47 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Bounds.lean @@ -107,10 +107,10 @@ theorem ContinuousLinearMap.norm_iteratedFDerivWithin_le_of_bilinear_aux {Du Eu (hs y hy) rw [← norm_iteratedFDerivWithin_fderivWithin hs hx, J] have A : ContDiffOn 𝕜 n (fun y => B.precompR Du (f y) (fderivWithin 𝕜 g s y)) s := - (B.precompR Du).isBoundedBilinearMap.contDiff.comp_contDiff_on₂ + (B.precompR Du).isBoundedBilinearMap.contDiff.comp_contDiffOn₂ (hf.of_le (Nat.cast_le.2 (Nat.le_succ n))) (hg.fderivWithin hs In) have A' : ContDiffOn 𝕜 n (fun y => B.precompL Du (fderivWithin 𝕜 f s y) (g y)) s := - (B.precompL Du).isBoundedBilinearMap.contDiff.comp_contDiff_on₂ (hf.fderivWithin hs In) + (B.precompL Du).isBoundedBilinearMap.contDiff.comp_contDiffOn₂ (hf.fderivWithin hs In) (hg.of_le (Nat.cast_le.2 (Nat.le_succ n))) rw [iteratedFDerivWithin_add_apply' A A' hs hx] apply (norm_add_le _ _).trans ((add_le_add I1 I2).trans (le_of_eq ?_)) @@ -449,7 +449,7 @@ theorem norm_iteratedFDerivWithin_comp_le_aux {Fu Gu : Type u} [NormedAddCommGro exact Nat.add_sub_of_le (Finset.mem_range_succ_iff.1 hi) _ ≤ ∑ i ∈ Finset.range (n + 1), (n ! : ℝ) * 1 * C * D ^ (n + 1) * 1 := by gcongr with i - apply inv_le_one + apply inv_le_one_of_one_le₀ simpa only [Nat.one_le_cast] using (n - i).factorial_pos _ = (n + 1)! * C * D ^ (n + 1) := by simp only [mul_assoc, mul_one, Finset.sum_const, Finset.card_range, nsmul_eq_mul, diff --git a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean index ff7ff85e3d49e..8ab71d0fee09d 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/Defs.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/Defs.lean @@ -222,7 +222,7 @@ protected theorem ContDiffWithinAt.insert (h : ContDiffWithinAt 𝕜 n f s x) : /-- If a function is `C^n` within a set at a point, with `n ≥ 1`, then it is differentiable within this set at this point. -/ -theorem ContDiffWithinAt.differentiable_within_at' (h : ContDiffWithinAt 𝕜 n f s x) (hn : 1 ≤ n) : +theorem ContDiffWithinAt.differentiableWithinAt' (h : ContDiffWithinAt 𝕜 n f s x) (hn : 1 ≤ n) : DifferentiableWithinAt 𝕜 f (insert x s) x := by rcases h 1 hn with ⟨u, hu, p, H⟩ rcases mem_nhdsWithin.1 hu with ⟨t, t_open, xt, tu⟩ @@ -230,9 +230,12 @@ theorem ContDiffWithinAt.differentiable_within_at' (h : ContDiffWithinAt 𝕜 n exact (differentiableWithinAt_inter (IsOpen.mem_nhds t_open xt)).1 <| ((H.mono tu).differentiableOn le_rfl) x ⟨mem_insert x s, xt⟩ +@[deprecated (since := "2024-10-10")] +alias ContDiffWithinAt.differentiable_within_at' := ContDiffWithinAt.differentiableWithinAt' + theorem ContDiffWithinAt.differentiableWithinAt (h : ContDiffWithinAt 𝕜 n f s x) (hn : 1 ≤ n) : DifferentiableWithinAt 𝕜 f s x := - (h.differentiable_within_at' hn).mono (subset_insert x s) + (h.differentiableWithinAt' hn).mono (subset_insert x s) /-- A function is `C^(n + 1)` on a domain iff locally, it has a derivative which is `C^n`. -/ theorem contDiffWithinAt_succ_iff_hasFDerivWithinAt {n : ℕ} : @@ -347,7 +350,7 @@ protected theorem ContDiffWithinAt.eventually {n : ℕ} (h : ContDiffWithinAt ∀ᶠ y in 𝓝[insert x s] x, ContDiffWithinAt 𝕜 n f s y := by rcases h.contDiffOn le_rfl with ⟨u, hu, _, hd⟩ have : ∀ᶠ y : E in 𝓝[insert x s] x, u ∈ 𝓝[insert x s] y ∧ y ∈ u := - (eventually_nhdsWithin_nhdsWithin.2 hu).and hu + (eventually_eventually_nhdsWithin.2 hu).and hu refine this.mono fun y hy => (hd y hy.2).mono_of_mem ?_ exact nhdsWithin_mono y (subset_insert _ _) hy.1 diff --git a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean index bce65e8bbdf7d..6bc8d6009890d 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FTaylorSeries.lean @@ -18,7 +18,7 @@ arbitrary choice in the definition. We also define a predicate `HasFTaylorSeriesUpTo` (and its localized version `HasFTaylorSeriesUpToOn`), saying that a sequence of multilinear maps is *a* sequence of -derivatives of `f`. Contrary to `iteratedFDerivWithin`, it accomodates well the +derivatives of `f`. Contrary to `iteratedFDerivWithin`, it accommodates well the non-uniqueness of derivatives. ## Main definitions and results diff --git a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean index 7b0d3e391e4fd..5b3ed3d9a9e4f 100644 --- a/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean +++ b/Mathlib/Analysis/Calculus/ContDiff/FiniteDimension.lean @@ -24,7 +24,7 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {D : Type uD} [NormedAddC section FiniteDimensional -open Function FiniteDimensional +open Function Module variable [CompleteSpace 𝕜] diff --git a/Mathlib/Analysis/Calculus/Deriv/Abs.lean b/Mathlib/Analysis/Calculus/Deriv/Abs.lean new file mode 100644 index 0000000000000..a5f01ae326dcf --- /dev/null +++ b/Mathlib/Analysis/Calculus/Deriv/Abs.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2024 Etienne Marion. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Etienne Marion +-/ +import Mathlib.Analysis.Calculus.Deriv.Add +import Mathlib.Analysis.InnerProductSpace.Calculus + +/-! +# Derivative of the absolute value + +This file compiles basic derivability properties of the absolute value, and is largely inspired +from `Mathlib.Analysis.InnerProductSpace.Calculus`, which is the analogous file for norms derived +from an inner product space. + +## Tags + +absolute value, derivative +-/ + +open Filter Real Set + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable {n : ℕ∞} {f : E → ℝ} {f' : E →L[ℝ] ℝ} {s : Set E} {x : E} + +theorem contDiffAt_abs {x : ℝ} (hx : x ≠ 0) : ContDiffAt ℝ n (|·|) x := contDiffAt_norm ℝ hx + +theorem ContDiffAt.abs (hf : ContDiffAt ℝ n f x) (h₀ : f x ≠ 0) : + ContDiffAt ℝ n (fun x ↦ |f x|) x := hf.norm ℝ h₀ + +theorem contDiffWithinAt_abs {x : ℝ} (hx : x ≠ 0) (s : Set ℝ) : + ContDiffWithinAt ℝ n (|·|) s x := (contDiffAt_abs hx).contDiffWithinAt + +theorem ContDiffWithinAt.abs (hf : ContDiffWithinAt ℝ n f s x) (h₀ : f x ≠ 0) : + ContDiffWithinAt ℝ n (fun y ↦ |f y|) s x := + (contDiffAt_abs h₀).comp_contDiffWithinAt x hf + +theorem contDiffOn_abs {s : Set ℝ} (hs : ∀ x ∈ s, x ≠ 0) : + ContDiffOn ℝ n (|·|) s := fun x hx ↦ contDiffWithinAt_abs (hs x hx) s + +theorem ContDiffOn.abs (hf : ContDiffOn ℝ n f s) (h₀ : ∀ x ∈ s, f x ≠ 0) : + ContDiffOn ℝ n (fun y ↦ |f y|) s := fun x hx ↦ (hf x hx).abs (h₀ x hx) + +theorem ContDiff.abs (hf : ContDiff ℝ n f) (h₀ : ∀ x, f x ≠ 0) : ContDiff ℝ n fun y ↦ |f y| := + contDiff_iff_contDiffAt.2 fun x ↦ hf.contDiffAt.abs (h₀ x) + +theorem hasStrictDerivAt_abs_neg {x : ℝ} (hx : x < 0) : + HasStrictDerivAt (|·|) (-1) x := + (hasStrictDerivAt_neg x).congr_of_eventuallyEq <| + EqOn.eventuallyEq_of_mem (fun _ hy ↦ (abs_of_neg (mem_Iio.1 hy)).symm) (Iio_mem_nhds hx) + +theorem hasDerivAt_abs_neg {x : ℝ} (hx : x < 0) : + HasDerivAt (|·|) (-1) x := (hasStrictDerivAt_abs_neg hx).hasDerivAt + +theorem hasStrictDerivAt_abs_pos {x : ℝ} (hx : 0 < x) : + HasStrictDerivAt (|·|) 1 x := + (hasStrictDerivAt_id x).congr_of_eventuallyEq <| + EqOn.eventuallyEq_of_mem (fun _ hy ↦ (abs_of_pos (mem_Iio.1 hy)).symm) (Ioi_mem_nhds hx) + +theorem hasDerivAt_abs_pos {x : ℝ} (hx : 0 < x) : + HasDerivAt (|·|) 1 x := (hasStrictDerivAt_abs_pos hx).hasDerivAt + +theorem hasStrictDerivAt_abs {x : ℝ} (hx : x ≠ 0) : + HasStrictDerivAt (|·|) (SignType.sign x : ℝ) x := by + obtain hx | hx := hx.lt_or_lt + · simpa [hx] using hasStrictDerivAt_abs_neg hx + · simpa [hx] using hasStrictDerivAt_abs_pos hx + +theorem hasDerivAt_abs {x : ℝ} (hx : x ≠ 0) : + HasDerivAt (|·|) (SignType.sign x : ℝ) x := (hasStrictDerivAt_abs hx).hasDerivAt + +theorem HasStrictFDerivAt.abs_of_neg (hf : HasStrictFDerivAt f f' x) + (h₀ : f x < 0) : HasStrictFDerivAt (fun x ↦ |f x|) (-f') x := by + convert (hasStrictDerivAt_abs_neg h₀).hasStrictFDerivAt.comp x hf using 1 + ext y + simp + +theorem HasFDerivAt.abs_of_neg (hf : HasFDerivAt f f' x) + (h₀ : f x < 0) : HasFDerivAt (fun x ↦ |f x|) (-f') x := by + convert (hasDerivAt_abs_neg h₀).hasFDerivAt.comp x hf using 1 + ext y + simp + +theorem HasStrictFDerivAt.abs_of_pos (hf : HasStrictFDerivAt f f' x) + (h₀ : 0 < f x) : HasStrictFDerivAt (fun x ↦ |f x|) f' x := by + convert (hasStrictDerivAt_abs_pos h₀).hasStrictFDerivAt.comp x hf using 1 + ext y + simp + +theorem HasFDerivAt.abs_of_pos (hf : HasFDerivAt f f' x) + (h₀ : 0 < f x) : HasFDerivAt (fun x ↦ |f x|) f' x := by + convert (hasDerivAt_abs_pos h₀).hasFDerivAt.comp x hf using 1 + ext y + simp + +theorem HasStrictFDerivAt.abs (hf : HasStrictFDerivAt f f' x) + (h₀ : f x ≠ 0) : HasStrictFDerivAt (fun x ↦ |f x|) ((SignType.sign (f x) : ℝ) • f') x := by + convert (hasStrictDerivAt_abs h₀).hasStrictFDerivAt.comp x hf using 1 + ext y + simp [mul_comm] + +theorem HasFDerivAt.abs (hf : HasFDerivAt f f' x) + (h₀ : f x ≠ 0) : HasFDerivAt (fun x ↦ |f x|) ((SignType.sign (f x) : ℝ) • f') x := by + convert (hasDerivAt_abs h₀).hasFDerivAt.comp x hf using 1 + ext y + simp [mul_comm] + +theorem hasDerivWithinAt_abs_neg (s : Set ℝ) {x : ℝ} (hx : x < 0) : + HasDerivWithinAt (|·|) (-1) s x := (hasDerivAt_abs_neg hx).hasDerivWithinAt + +theorem hasDerivWithinAt_abs_pos (s : Set ℝ) {x : ℝ} (hx : 0 < x) : + HasDerivWithinAt (|·|) 1 s x := (hasDerivAt_abs_pos hx).hasDerivWithinAt + +theorem hasDerivWithinAt_abs (s : Set ℝ) {x : ℝ} (hx : x ≠ 0) : + HasDerivWithinAt (|·|) (SignType.sign x : ℝ) s x := (hasDerivAt_abs hx).hasDerivWithinAt + +theorem HasFDerivWithinAt.abs_of_neg (hf : HasFDerivWithinAt f f' s x) + (h₀ : f x < 0) : HasFDerivWithinAt (fun x ↦ |f x|) (-f') s x := by + convert (hasDerivAt_abs_neg h₀).comp_hasFDerivWithinAt x hf using 1 + simp + +theorem HasFDerivWithinAt.abs_of_pos (hf : HasFDerivWithinAt f f' s x) + (h₀ : 0 < f x) : HasFDerivWithinAt (fun x ↦ |f x|) f' s x := by + convert (hasDerivAt_abs_pos h₀).comp_hasFDerivWithinAt x hf using 1 + simp + +theorem HasFDerivWithinAt.abs (hf : HasFDerivWithinAt f f' s x) + (h₀ : f x ≠ 0) : HasFDerivWithinAt (fun x ↦ |f x|) ((SignType.sign (f x) : ℝ) • f') s x := + (hasDerivAt_abs h₀).comp_hasFDerivWithinAt x hf + +theorem differentiableAt_abs_neg {x : ℝ} (hx : x < 0) : + DifferentiableAt ℝ (|·|) x := (hasDerivAt_abs_neg hx).differentiableAt + +theorem differentiableAt_abs_pos {x : ℝ} (hx : 0 < x) : + DifferentiableAt ℝ (|·|) x := (hasDerivAt_abs_pos hx).differentiableAt + +theorem differentiableAt_abs {x : ℝ} (hx : x ≠ 0) : + DifferentiableAt ℝ (|·|) x := (hasDerivAt_abs hx).differentiableAt + +theorem DifferentiableAt.abs_of_neg (hf : DifferentiableAt ℝ f x) (h₀ : f x < 0) : + DifferentiableAt ℝ (fun x ↦ |f x|) x := (differentiableAt_abs_neg h₀).comp x hf + +theorem DifferentiableAt.abs_of_pos (hf : DifferentiableAt ℝ f x) (h₀ : 0 < f x) : + DifferentiableAt ℝ (fun x ↦ |f x|) x := (differentiableAt_abs_pos h₀).comp x hf + +theorem DifferentiableAt.abs (hf : DifferentiableAt ℝ f x) (h₀ : f x ≠ 0) : + DifferentiableAt ℝ (fun x ↦ |f x|) x := (differentiableAt_abs h₀).comp x hf + +theorem differentiableWithinAt_abs_neg (s : Set ℝ) {x : ℝ} (hx : x < 0) : + DifferentiableWithinAt ℝ (|·|) s x := (differentiableAt_abs_neg hx).differentiableWithinAt + +theorem differentiableWithinAt_abs_pos (s : Set ℝ) {x : ℝ} (hx : 0 < x) : + DifferentiableWithinAt ℝ (|·|) s x := (differentiableAt_abs_pos hx).differentiableWithinAt + +theorem differentiableWithinAt_abs (s : Set ℝ) {x : ℝ} (hx : x ≠ 0) : + DifferentiableWithinAt ℝ (|·|) s x := (differentiableAt_abs hx).differentiableWithinAt + +theorem DifferentiableWithinAt.abs_of_neg (hf : DifferentiableWithinAt ℝ f s x) (h₀ : f x < 0) : + DifferentiableWithinAt ℝ (fun x ↦ |f x|) s x := + (differentiableAt_abs_neg h₀).comp_differentiableWithinAt x hf + +theorem DifferentiableWithinAt.abs_of_pos (hf : DifferentiableWithinAt ℝ f s x) (h₀ : 0 < f x) : + DifferentiableWithinAt ℝ (fun x ↦ |f x|) s x := + (differentiableAt_abs_pos h₀).comp_differentiableWithinAt x hf + +theorem DifferentiableWithinAt.abs (hf : DifferentiableWithinAt ℝ f s x) (h₀ : f x ≠ 0) : + DifferentiableWithinAt ℝ (fun x ↦ |f x|) s x := + (differentiableAt_abs h₀).comp_differentiableWithinAt x hf + +theorem differentiableOn_abs {s : Set ℝ} (hs : ∀ x ∈ s, x ≠ 0) : DifferentiableOn ℝ (|·|) s := + fun x hx ↦ differentiableWithinAt_abs s (hs x hx) + +theorem DifferentiableOn.abs (hf : DifferentiableOn ℝ f s) (h₀ : ∀ x ∈ s, f x ≠ 0) : + DifferentiableOn ℝ (fun x ↦ |f x|) s := + fun x hx ↦ (hf x hx).abs (h₀ x hx) + +theorem Differentiable.abs (hf : Differentiable ℝ f) (h₀ : ∀ x, f x ≠ 0) : + Differentiable ℝ (fun x ↦ |f x|) := fun x ↦ (hf x).abs (h₀ x) + +theorem not_differentiableAt_abs_zero : ¬ DifferentiableAt ℝ (abs : ℝ → ℝ) 0 := by + intro h + have h₁ : deriv abs (0 : ℝ) = 1 := + (uniqueDiffOn_Ici _ _ Set.left_mem_Ici).eq_deriv _ h.hasDerivAt.hasDerivWithinAt <| + (hasDerivWithinAt_id _ _).congr_of_mem (fun _ h ↦ abs_of_nonneg h) Set.left_mem_Ici + have h₂ : deriv abs (0 : ℝ) = -1 := + (uniqueDiffOn_Iic _ _ Set.right_mem_Iic).eq_deriv _ h.hasDerivAt.hasDerivWithinAt <| + (hasDerivWithinAt_neg _ _).congr_of_mem (fun _ h ↦ abs_of_nonpos h) Set.right_mem_Iic + linarith + +theorem deriv_abs_neg {x : ℝ} (hx : x < 0) : deriv (|·|) x = -1 := (hasDerivAt_abs_neg hx).deriv + +theorem deriv_abs_pos {x : ℝ} (hx : 0 < x) : deriv (|·|) x = 1 := (hasDerivAt_abs_pos hx).deriv + +theorem deriv_abs_zero : deriv (|·|) (0 : ℝ) = 0 := + deriv_zero_of_not_differentiableAt not_differentiableAt_abs_zero + +theorem deriv_abs (x : ℝ) : deriv (|·|) x = SignType.sign x := by + obtain rfl | hx := eq_or_ne x 0 + · simpa using deriv_abs_zero + · simpa [hx] using (hasDerivAt_abs hx).deriv diff --git a/Mathlib/Analysis/Calculus/Deriv/Add.lean b/Mathlib/Analysis/Calculus/Deriv/Add.lean index 6f51814995811..169722bc11409 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Add.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Add.lean @@ -247,16 +247,6 @@ theorem differentiable_neg : Differentiable 𝕜 (Neg.neg : 𝕜 → 𝕜) := theorem differentiableOn_neg : DifferentiableOn 𝕜 (Neg.neg : 𝕜 → 𝕜) s := DifferentiableOn.neg differentiableOn_id -theorem not_differentiableAt_abs_zero : ¬ DifferentiableAt ℝ (abs : ℝ → ℝ) 0 := by - intro h - have h₁ : deriv abs (0 : ℝ) = 1 := - (uniqueDiffOn_Ici _ _ Set.left_mem_Ici).eq_deriv _ h.hasDerivAt.hasDerivWithinAt <| - (hasDerivWithinAt_id _ _).congr_of_mem (fun _ h ↦ abs_of_nonneg h) Set.left_mem_Ici - have h₂ : deriv abs (0 : ℝ) = -1 := - (uniqueDiffOn_Iic _ _ Set.right_mem_Iic).eq_deriv _ h.hasDerivAt.hasDerivWithinAt <| - (hasDerivWithinAt_neg _ _).congr_of_mem (fun _ h ↦ abs_of_nonpos h) Set.right_mem_Iic - linarith - lemma differentiableAt_comp_neg {a : 𝕜} : DifferentiableAt 𝕜 (fun x ↦ f (-x)) a ↔ DifferentiableAt 𝕜 f (-a) := by refine ⟨fun H ↦ ?_, fun H ↦ H.comp a differentiable_neg.differentiableAt⟩ diff --git a/Mathlib/Analysis/Calculus/Deriv/Basic.lean b/Mathlib/Analysis/Calculus/Deriv/Basic.lean index edda887e12373..5ed888191d0e0 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Basic.lean @@ -416,7 +416,7 @@ theorem norm_deriv_eq_norm_fderiv : ‖deriv f x‖ = ‖fderiv 𝕜 f x‖ := b theorem DifferentiableAt.derivWithin (h : DifferentiableAt 𝕜 f x) (hxs : UniqueDiffWithinAt 𝕜 s x) : derivWithin f s x = deriv f x := by - unfold derivWithin deriv + unfold _root_.derivWithin deriv rw [h.fderivWithin hxs] theorem HasDerivWithinAt.deriv_eq_zero (hd : HasDerivWithinAt f 0 s x) diff --git a/Mathlib/Analysis/Calculus/Deriv/Mul.lean b/Mathlib/Analysis/Calculus/Deriv/Mul.lean index 64628ceb448d0..8577c4b84784c 100644 --- a/Mathlib/Analysis/Calculus/Deriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/Deriv/Mul.lean @@ -169,7 +169,6 @@ lemma deriv_const_smul' {f : 𝕜 → F} {x : 𝕜} {R : Type*} [Field R] [Modul · simp only [zero_smul, deriv_const'] · have H : ¬DifferentiableAt 𝕜 (fun y ↦ c • f y) x := by contrapose! hf - change DifferentiableAt 𝕜 (fun y ↦ f y) x conv => enter [2, y]; rw [← inv_smul_smul₀ hc (f y)] exact DifferentiableAt.const_smul hf c⁻¹ rw [deriv_zero_of_not_differentiableAt hf, deriv_zero_of_not_differentiableAt H, smul_zero] @@ -324,22 +323,26 @@ end HasDeriv variable {ι : Type*} {𝔸' : Type*} [NormedCommRing 𝔸'] [NormedAlgebra 𝕜 𝔸'] {u : Finset ι} {f : ι → 𝕜 → 𝔸'} {f' : ι → 𝔸'} +@[fun_prop] theorem DifferentiableAt.finset_prod (hd : ∀ i ∈ u, DifferentiableAt 𝕜 (f i) x) : DifferentiableAt 𝕜 (∏ i ∈ u, f i ·) x := by classical exact (HasDerivAt.finset_prod (fun i hi ↦ DifferentiableAt.hasDerivAt (hd i hi))).differentiableAt +@[fun_prop] theorem DifferentiableWithinAt.finset_prod (hd : ∀ i ∈ u, DifferentiableWithinAt 𝕜 (f i) s x) : DifferentiableWithinAt 𝕜 (∏ i ∈ u, f i ·) s x := by classical exact (HasDerivWithinAt.finset_prod (fun i hi ↦ DifferentiableWithinAt.hasDerivWithinAt (hd i hi))).differentiableWithinAt +@[fun_prop] theorem DifferentiableOn.finset_prod (hd : ∀ i ∈ u, DifferentiableOn 𝕜 (f i) s) : DifferentiableOn 𝕜 (∏ i ∈ u, f i ·) s := fun x hx ↦ .finset_prod (fun i hi ↦ hd i hi x hx) +@[fun_prop] theorem Differentiable.finset_prod (hd : ∀ i ∈ u, Differentiable 𝕜 (f i)) : Differentiable 𝕜 (∏ i ∈ u, f i ·) := fun x ↦ .finset_prod (fun i hi ↦ hd i hi x) @@ -362,19 +365,21 @@ theorem HasStrictDerivAt.div_const (hc : HasStrictDerivAt c c' x) (d : 𝕜') : HasStrictDerivAt (fun x => c x / d) (c' / d) x := by simpa only [div_eq_mul_inv] using hc.mul_const d⁻¹ +@[fun_prop] theorem DifferentiableWithinAt.div_const (hc : DifferentiableWithinAt 𝕜 c s x) (d : 𝕜') : DifferentiableWithinAt 𝕜 (fun x => c x / d) s x := (hc.hasDerivWithinAt.div_const _).differentiableWithinAt -@[simp] +@[simp, fun_prop] theorem DifferentiableAt.div_const (hc : DifferentiableAt 𝕜 c x) (d : 𝕜') : DifferentiableAt 𝕜 (fun x => c x / d) x := (hc.hasDerivAt.div_const _).differentiableAt +@[fun_prop] theorem DifferentiableOn.div_const (hc : DifferentiableOn 𝕜 c s) (d : 𝕜') : DifferentiableOn 𝕜 (fun x => c x / d) s := fun x hx => (hc x hx).div_const d -@[simp] +@[simp, fun_prop] theorem Differentiable.div_const (hc : Differentiable 𝕜 c) (d : 𝕜') : Differentiable 𝕜 fun x => c x / d := fun x => (hc x).div_const d diff --git a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean index ef38ec6312a71..80735fc0538cf 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Analytic.lean @@ -4,10 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Analysis.Analytic.CPolynomial +import Mathlib.Analysis.Analytic.Inverse import Mathlib.Analysis.Analytic.Within import Mathlib.Analysis.Calculus.Deriv.Basic import Mathlib.Analysis.Calculus.ContDiff.Defs import Mathlib.Analysis.Calculus.FDeriv.Add +import Mathlib.Analysis.Calculus.FDeriv.Prod +import Mathlib.Analysis.Normed.Module.Completion /-! # Frechet derivatives of analytic functions. @@ -17,11 +20,50 @@ Also the special case in terms of `deriv` when the domain is 1-dimensional. As an application, we show that continuous multilinear maps are smooth. We also compute their iterated derivatives, in `ContinuousMultilinearMap.iteratedFDeriv_eq`. + +## Main definitions and results + +* `AnalyticAt.differentiableAt` : an analytic function at a point is differentiable there. +* `AnalyticOnNhd.fderiv` : in a complete space, if a function is analytic on a + neighborhood of a set `s`, so is its derivative. +* `AnalyticOnNhd.fderiv_of_isOpen` : if a function is analytic on a neighborhood of an + open set `s`, so is its derivative. +* `AnalyticOn.fderivWithin` : if a function is analytic on a set of unique differentiability, + so is its derivative within this set. +* `PartialHomeomorph.analyticAt_symm` : if a partial homeomorphism `f` is analytic at a + point `f.symm a`, with invertible derivative, then its inverse is analytic at `a`. + +## Comments on completeness + +Some theorems need a complete space, some don't, for the following reason. + +(1) If a function is analytic at a point `x`, then it is differentiable there (with derivative given +by the first term in the power series). There is no issue of convergence here. + +(2) If a function has a power series on a ball `B (x, r)`, there is no guarantee that the power +series for the derivative will converge at `y ≠ x`, if the space is not complete. So, to deduce +that `f` is differentiable at `y`, one needs completeness in general. + +(3) However, if a function `f` has a power series on a ball `B (x, r)`, and is a priori known to be +differentiable at some point `y ≠ x`, then the power series for the derivative of `f` will +automatically converge at `y`, towards the given derivative: this follows from the facts that this +is true in the completion (thanks to the previous point) and that the map to the completion is +an embedding. + +(4) Therefore, if one assumes `AnalyticOn 𝕜 f s` where `s` is an open set, then `f` is analytic +therefore differentiable at every point of `s`, by (1), so by (3) the power series for its +derivative converges on whole balls. Therefore, the derivative of `f` is also analytic on `s`. The +same holds if `s` is merely a set with unique differentials. + +(5) However, this does not work for `AnalyticOnNhd 𝕜 f s`, as we don't get for free +differentiability at points in a neighborhood of `s`. Therefore, the theorem that deduces +`AnalyticOnNhd 𝕜 (fderiv 𝕜 f) s` from `AnalyticOnNhd 𝕜 f s` requires completeness of the space. + -/ open Filter Asymptotics Set -open scoped ENNReal +open scoped ENNReal Topology universe u v @@ -34,26 +76,58 @@ section fderiv variable {p : FormalMultilinearSeries 𝕜 E F} {r : ℝ≥0∞} variable {f : E → F} {x : E} {s : Set E} -theorem HasFPowerSeriesAt.hasStrictFDerivAt (h : HasFPowerSeriesAt f p x) : - HasStrictFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p 1)) x := by +/-- A function which is analytic within a set is strictly differentiable there. Since we +don't have a predicate `HasStrictFDerivWithinAt`, we spell out what it would mean. -/ +theorem HasFPowerSeriesWithinAt.hasStrictFDerivWithinAt (h : HasFPowerSeriesWithinAt f p s x) : + (fun y ↦ f y.1 - f y.2 - ((continuousMultilinearCurryFin1 𝕜 E F) (p 1)) (y.1 - y.2)) + =o[𝓝[insert x s ×ˢ insert x s] (x, x)] fun y ↦ y.1 - y.2 := by refine h.isBigO_image_sub_norm_mul_norm_sub.trans_isLittleO (IsLittleO.of_norm_right ?_) refine isLittleO_iff_exists_eq_mul.2 ⟨fun y => ‖y - (x, x)‖, ?_, EventuallyEq.rfl⟩ + apply Tendsto.mono_left _ nhdsWithin_le_nhds refine (continuous_id.sub continuous_const).norm.tendsto' _ _ ?_ rw [_root_.id, sub_self, norm_zero] +theorem HasFPowerSeriesAt.hasStrictFDerivAt (h : HasFPowerSeriesAt f p x) : + HasStrictFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p 1)) x := by + simpa only [Set.insert_eq_of_mem, Set.mem_univ, Set.univ_prod_univ, nhdsWithin_univ] + using (h.hasFPowerSeriesWithinAt (s := Set.univ)).hasStrictFDerivWithinAt + +theorem HasFPowerSeriesWithinAt.hasFDerivWithinAt (h : HasFPowerSeriesWithinAt f p s x) : + HasFDerivWithinAt f (continuousMultilinearCurryFin1 𝕜 E F (p 1)) (insert x s) x := by + rw [HasFDerivWithinAt, hasFDerivAtFilter_iff_isLittleO, isLittleO_iff] + intro c hc + have : Tendsto (fun y ↦ (y, x)) (𝓝[insert x s] x) (𝓝[insert x s ×ˢ insert x s] (x, x)) := by + rw [nhdsWithin_prod_eq] + exact Tendsto.prod_mk tendsto_id (tendsto_const_nhdsWithin (by simp)) + exact this (isLittleO_iff.1 h.hasStrictFDerivWithinAt hc) + theorem HasFPowerSeriesAt.hasFDerivAt (h : HasFPowerSeriesAt f p x) : HasFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p 1)) x := h.hasStrictFDerivAt.hasFDerivAt +theorem HasFPowerSeriesWithinAt.differentiableWithinAt (h : HasFPowerSeriesWithinAt f p s x) : + DifferentiableWithinAt 𝕜 f (insert x s) x := + h.hasFDerivWithinAt.differentiableWithinAt + theorem HasFPowerSeriesAt.differentiableAt (h : HasFPowerSeriesAt f p x) : DifferentiableAt 𝕜 f x := h.hasFDerivAt.differentiableAt +theorem AnalyticWithinAt.differentiableWithinAt (h : AnalyticWithinAt 𝕜 f s x) : + DifferentiableWithinAt 𝕜 f (insert x s) x := by + obtain ⟨p, hp⟩ := h + exact hp.differentiableWithinAt + theorem AnalyticAt.differentiableAt : AnalyticAt 𝕜 f x → DifferentiableAt 𝕜 f x | ⟨_, hp⟩ => hp.differentiableAt theorem AnalyticAt.differentiableWithinAt (h : AnalyticAt 𝕜 f x) : DifferentiableWithinAt 𝕜 f s x := h.differentiableAt.differentiableWithinAt +theorem HasFPowerSeriesWithinAt.fderivWithin_eq + (h : HasFPowerSeriesWithinAt f p s x) (hu : UniqueDiffWithinAt 𝕜 (insert x s) x) : + fderivWithin 𝕜 f (insert x s) x = continuousMultilinearCurryFin1 𝕜 E F (p 1) := + h.hasFDerivWithinAt.fderivWithin hu + theorem HasFPowerSeriesAt.fderiv_eq (h : HasFPowerSeriesAt f p x) : fderiv 𝕜 f x = continuousMultilinearCurryFin1 𝕜 E F (p 1) := h.hasFDerivAt.fderiv @@ -64,25 +138,61 @@ theorem AnalyticAt.hasStrictFDerivAt (h : AnalyticAt 𝕜 f x) : rw [hp.fderiv_eq] exact hp.hasStrictFDerivAt +theorem HasFPowerSeriesWithinOnBall.differentiableOn [CompleteSpace F] + (h : HasFPowerSeriesWithinOnBall f p s x r) : + DifferentiableOn 𝕜 f (insert x s ∩ EMetric.ball x r) := by + intro y hy + have Z := (h.analyticWithinAt_of_mem hy).differentiableWithinAt + rcases eq_or_ne y x with rfl | hy + · exact Z.mono inter_subset_left + · apply (Z.mono (subset_insert _ _)).mono_of_mem + suffices s ∈ 𝓝[insert x s] y from nhdsWithin_mono _ inter_subset_left this + rw [nhdsWithin_insert_of_ne hy] + exact self_mem_nhdsWithin + theorem HasFPowerSeriesOnBall.differentiableOn [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) : DifferentiableOn 𝕜 f (EMetric.ball x r) := fun _ hy => (h.analyticAt_of_mem hy).differentiableWithinAt -theorem AnalyticOn.differentiableOn (h : AnalyticOn 𝕜 f s) : DifferentiableOn 𝕜 f s := fun y hy => - (h y hy).differentiableWithinAt +theorem AnalyticOn.differentiableOn (h : AnalyticOn 𝕜 f s) : DifferentiableOn 𝕜 f s := + fun y hy ↦ (h y hy).differentiableWithinAt.mono (by simp) + +theorem AnalyticOnNhd.differentiableOn (h : AnalyticOnNhd 𝕜 f s) : DifferentiableOn 𝕜 f s := + fun y hy ↦ (h y hy).differentiableWithinAt + +theorem HasFPowerSeriesWithinOnBall.hasFDerivWithinAt [CompleteSpace F] + (h : HasFPowerSeriesWithinOnBall f p s x r) + {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) (h'y : x + y ∈ insert x s) : + HasFDerivWithinAt f (continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1)) + (insert x s) (x + y) := by + rcases eq_or_ne y 0 with rfl | h''y + · convert (h.changeOrigin hy h'y).hasFPowerSeriesWithinAt.hasFDerivWithinAt + simp + · have Z := (h.changeOrigin hy h'y).hasFPowerSeriesWithinAt.hasFDerivWithinAt + apply (Z.mono (subset_insert _ _)).mono_of_mem + rw [nhdsWithin_insert_of_ne] + · exact self_mem_nhdsWithin + · simpa using h''y theorem HasFPowerSeriesOnBall.hasFDerivAt [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) : HasFDerivAt f (continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1)) (x + y) := (h.changeOrigin hy).hasFPowerSeriesAt.hasFDerivAt +theorem HasFPowerSeriesWithinOnBall.fderivWithin_eq [CompleteSpace F] + (h : HasFPowerSeriesWithinOnBall f p s x r) + {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) (h'y : x + y ∈ insert x s) (hu : UniqueDiffOn 𝕜 (insert x s)) : + fderivWithin 𝕜 f (insert x s) (x + y) = + continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin y 1) := + (h.hasFDerivWithinAt hy h'y).fderivWithin (hu _ h'y) + theorem HasFPowerSeriesOnBall.fderiv_eq [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x 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 power series on a ball, then so does its derivative. -/ -theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] (h : HasFPowerSeriesOnBall f p x r) : +protected theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] + (h : HasFPowerSeriesOnBall f p x r) : HasFPowerSeriesOnBall (fderiv 𝕜 f) p.derivSeries x r := by refine .congr (f := fun z ↦ continuousMultilinearCurryFin1 𝕜 E F (p.changeOrigin (z - x) 1)) ?_ fun z hz ↦ ?_ @@ -94,33 +204,76 @@ theorem HasFPowerSeriesOnBall.fderiv [CompleteSpace F] (h : HasFPowerSeriesOnBal rw [← h.fderiv_eq, add_sub_cancel] simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz +/-- If a function has a power series within a set on a ball, then so does its derivative. -/ +protected theorem HasFPowerSeriesWithinOnBall.fderivWithin [CompleteSpace F] + (h : HasFPowerSeriesWithinOnBall f p s x r) (hu : UniqueDiffOn 𝕜 (insert x s)) : + HasFPowerSeriesWithinOnBall (fderivWithin 𝕜 f (insert x s)) p.derivSeries s 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_hasFPowerSeriesWithinOnBall ?_ + apply HasFPowerSeriesOnBall.hasFPowerSeriesWithinOnBall + 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.fderivWithin_eq _ _ hu, add_sub_cancel] + · simpa only [edist_eq_coe_nnnorm_sub, EMetric.mem_ball] using hz.2 + · simpa using hz.1 + /-- If a function is analytic on a set `s`, so is its Fréchet derivative. -/ -theorem AnalyticOn.fderiv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) : - AnalyticOn 𝕜 (fderiv 𝕜 f) s := by - intro y hy - rcases h y hy with ⟨p, r, hp⟩ +protected theorem AnalyticAt.fderiv [CompleteSpace F] (h : AnalyticAt 𝕜 f x) : + AnalyticAt 𝕜 (fderiv 𝕜 f) x := by + rcases h with ⟨p, r, hp⟩ exact hp.fderiv.analyticAt -/-- If a function is analytic on a set `s`, so are its successive Fréchet derivative. -/ -theorem AnalyticOn.iteratedFDeriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (iteratedFDeriv 𝕜 n f) s := by +/-- If a function is analytic on a set `s`, so is its Fréchet derivative. See also +`AnalyticOnNhd.fderiv_of_isOpen`, removing the completeness assumption but requiring the set +to be open. -/ +protected theorem AnalyticOnNhd.fderiv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (fderiv 𝕜 f) s := + fun y hy ↦ AnalyticAt.fderiv (h y hy) + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.fderiv := AnalyticOnNhd.fderiv + +/-- If a function is analytic on a set `s`, so are its successive Fréchet derivative. See also +`AnalyticOnNhd.iteratedFDeruv_of_isOpen`, removing the completeness assumption but requiring the set +to be open.-/ +protected theorem AnalyticOnNhd.iteratedFDeriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (iteratedFDeriv 𝕜 n f) s := by induction n with | zero => rw [iteratedFDeriv_zero_eq_comp] - exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_analyticOn h + exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F).comp_analyticOnNhd h | succ n IH => 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 ?g IH.fderiv + convert ContinuousLinearMap.comp_analyticOnNhd ?g IH.fderiv case g => exact ↑(continuousMultilinearCurryLeftEquiv 𝕜 (fun _ : Fin (n + 1) ↦ E) F).symm simp +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.iteratedFDeriv := AnalyticOnNhd.iteratedFDeriv + +/-- If a function is analytic on a neighborhood of a set `s`, then it has a Taylor series given +by the sequence of its derivatives. Note that, if the function were just analytic on `s`, then +one would have to use instead the sequence of derivatives inside the set, as in +`AnalyticOn.hasFTaylorSeriesUpToOn`. -/ +lemma AnalyticOnNhd.hasFTaylorSeriesUpToOn [CompleteSpace F] + (n : ℕ∞) (h : AnalyticOnNhd 𝕜 f s) : + HasFTaylorSeriesUpToOn n f (ftaylorSeries 𝕜 f) s := by + refine ⟨fun x _hx ↦ rfl, fun m _hm x hx ↦ ?_, fun m _hm x hx ↦ ?_⟩ + · apply HasFDerivAt.hasFDerivWithinAt + exact ((h.iteratedFDeriv m x hx).differentiableAt).hasFDerivAt + · apply (DifferentiableAt.continuousAt (𝕜 := 𝕜) ?_).continuousWithinAt + exact (h.iteratedFDeriv m x hx).differentiableAt + /-- An analytic function is infinitely differentiable. -/ -theorem AnalyticOn.contDiffOn [CompleteSpace F] (h : AnalyticOn 𝕜 f s) {n : ℕ∞} : +protected theorem AnalyticOnNhd.contDiffOn [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := let t := { x | AnalyticAt 𝕜 f x } suffices ContDiffOn 𝕜 n f t from this.mono h - have H : AnalyticOn 𝕜 f t := fun _x hx ↦ hx + have H : AnalyticOnNhd 𝕜 f t := fun _x hx ↦ hx have t_open : IsOpen t := isOpen_analyticAt 𝕜 f contDiffOn_of_continuousOn_differentiableOn (fun m _ ↦ (H.iteratedFDeriv m).continuousOn.congr @@ -128,20 +281,150 @@ theorem AnalyticOn.contDiffOn [CompleteSpace F] (h : AnalyticOn 𝕜 f s) {n : (fun m _ ↦ (H.iteratedFDeriv m).differentiableOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) +/-- An analytic function on the whole space is infinitely differentiable there. -/ +theorem AnalyticOnNhd.contDiff [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f univ) {n : ℕ∞} : + ContDiff 𝕜 n f := by + rw [← contDiffOn_univ] + exact h.contDiffOn + theorem AnalyticAt.contDiffAt [CompleteSpace F] (h : AnalyticAt 𝕜 f x) {n : ℕ∞} : ContDiffAt 𝕜 n f x := by - obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOn + obtain ⟨s, hs, hf⟩ := h.exists_mem_nhds_analyticOnNhd exact hf.contDiffOn.contDiffAt hs -lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set E} {x : E} +protected lemma AnalyticWithinAt.contDiffWithinAt [CompleteSpace F] {f : E → F} {s : Set E} {x : E} (h : AnalyticWithinAt 𝕜 f s x) {n : ℕ∞} : ContDiffWithinAt 𝕜 n f s x := by rcases h.exists_analyticAt with ⟨g, fx, fg, hg⟩ exact hg.contDiffAt.contDiffWithinAt.congr (fg.mono (subset_insert _ _)) fx -lemma AnalyticWithinOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} - (h : AnalyticWithinOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := +protected lemma AnalyticOn.contDiffOn [CompleteSpace F] {f : E → F} {s : Set E} + (h : AnalyticOn 𝕜 f s) {n : ℕ∞} : ContDiffOn 𝕜 n f s := fun x m ↦ (h x m).contDiffWithinAt +@[deprecated (since := "2024-09-26")] +alias AnalyticWithinOn.contDiffOn := AnalyticOn.contDiffOn + +lemma AnalyticWithinAt.exists_hasFTaylorSeriesUpToOn [CompleteSpace F] + (n : ℕ∞) (h : AnalyticWithinAt 𝕜 f s x) : + ∃ u ∈ 𝓝[insert x s] x, ∃ (p : E → FormalMultilinearSeries 𝕜 E F), + HasFTaylorSeriesUpToOn n f p u ∧ ∀ i, AnalyticOn 𝕜 (fun x ↦ p x i) u := by + rcases h.exists_analyticAt with ⟨g, -, fg, hg⟩ + rcases hg.exists_mem_nhds_analyticOnNhd with ⟨v, vx, hv⟩ + refine ⟨insert x s ∩ v, inter_mem_nhdsWithin _ vx, ftaylorSeries 𝕜 g, ?_, fun i ↦ ?_⟩ + · suffices HasFTaylorSeriesUpToOn n g (ftaylorSeries 𝕜 g) (insert x s ∩ v) from + this.congr (fun y hy ↦ fg hy.1) + exact AnalyticOnNhd.hasFTaylorSeriesUpToOn _ (hv.mono Set.inter_subset_right) + · exact (hv.iteratedFDeriv i).analyticOn.mono Set.inter_subset_right + +/-- If a function has a power series `p` within a set of unique differentiability, inside a ball, +and is differentiable at a point, then the derivative series of `p` is summable at a point, with +sum the given differential. Note that this theorem does not require completeness of the space.-/ +theorem HasFPowerSeriesWithinOnBall.hasSum_derivSeries_of_hasFDerivWithinAt + (h : HasFPowerSeriesWithinOnBall f p s x r) + {f' : E →L[𝕜] F} + {y : E} (hy : (‖y‖₊ : ℝ≥0∞) < r) (h'y : x + y ∈ insert x s) + (hf' : HasFDerivWithinAt f f' (insert x s) (x + y)) + (hu : UniqueDiffOn 𝕜 (insert x s)) : + HasSum (fun n ↦ p.derivSeries n (fun _ ↦ y)) f' := by + /- In the completion of the space, the derivative series is summable, and its sum is a derivative + of the function. Therefore, by uniqueness of derivatives, its sum is the image of `f'` under + the canonical embedding. As this is an embedding, it means that there was also convergence in + the original space, to `f'`. -/ + let F' := UniformSpace.Completion F + let a : F →L[𝕜] F' := UniformSpace.Completion.toComplL + let b : (E →L[𝕜] F) →ₗᵢ[𝕜] (E →L[𝕜] F') := UniformSpace.Completion.toComplₗᵢ.postcomp + rw [← b.embedding.hasSum_iff] + have : HasFPowerSeriesWithinOnBall (a ∘ f) (a.compFormalMultilinearSeries p) s x r := + a.comp_hasFPowerSeriesWithinOnBall h + have Z := (this.fderivWithin hu).hasSum h'y (by simpa [edist_eq_coe_nnnorm] using hy) + have : fderivWithin 𝕜 (a ∘ f) (insert x s) (x + y) = a ∘L f' := by + apply HasFDerivWithinAt.fderivWithin _ (hu _ h'y) + exact a.hasFDerivAt.comp_hasFDerivWithinAt (x + y) hf' + rw [this] at Z + convert Z with n + ext v + simp only [FormalMultilinearSeries.derivSeries, + ContinuousLinearMap.compFormalMultilinearSeries_apply, + FormalMultilinearSeries.changeOriginSeries, + ContinuousLinearMap.compContinuousMultilinearMap_coe, ContinuousLinearEquiv.coe_coe, + LinearIsometryEquiv.coe_coe, Function.comp_apply, ContinuousMultilinearMap.sum_apply, map_sum, + ContinuousLinearMap.coe_sum', Finset.sum_apply, + Matrix.zero_empty] + rfl + +/-- If a function is analytic within a set with unique differentials, then so is its derivative. +Note that this theorem does not require completeness of the space. -/ +protected theorem AnalyticOn.fderivWithin (h : AnalyticOn 𝕜 f s) (hu : UniqueDiffOn 𝕜 s) : + AnalyticOn 𝕜 (fderivWithin 𝕜 f s) s := by + intro x hx + rcases h x hx with ⟨p, r, hr⟩ + refine ⟨p.derivSeries, r, ?_⟩ + refine ⟨hr.r_le.trans p.radius_le_radius_derivSeries, hr.r_pos, fun {y} hy h'y ↦ ?_⟩ + apply hr.hasSum_derivSeries_of_hasFDerivWithinAt (by simpa [edist_eq_coe_nnnorm] using h'y) hy + · rw [insert_eq_of_mem hx] at hy ⊢ + apply DifferentiableWithinAt.hasFDerivWithinAt + exact h.differentiableOn _ hy + · rwa [insert_eq_of_mem hx] + +/-- If a function is analytic on a set `s`, so are its successive Fréchet derivative within this +set. Note that this theorem does not require completeness of the space. -/ +protected theorem AnalyticOn.iteratedFDerivWithin (h : AnalyticOn 𝕜 f s) + (hu : UniqueDiffOn 𝕜 s) (n : ℕ) : + AnalyticOn 𝕜 (iteratedFDerivWithin 𝕜 n f s) s := by + induction n with + | zero => + rw [iteratedFDerivWithin_zero_eq_comp] + exact ((continuousMultilinearCurryFin0 𝕜 E F).symm : F →L[𝕜] E[×0]→L[𝕜] F) + |>.comp_analyticOn h + | succ n IH => + rw [iteratedFDerivWithin_succ_eq_comp_left] + apply AnalyticOnNhd.comp_analyticOn _ (IH.fderivWithin hu) (mapsTo_univ _ _) + apply LinearIsometryEquiv.analyticOnNhd + +lemma AnalyticOn.hasFTaylorSeriesUpToOn {n : ℕ∞} + (h : AnalyticOn 𝕜 f s) (hu : UniqueDiffOn 𝕜 s) : + HasFTaylorSeriesUpToOn n f (ftaylorSeriesWithin 𝕜 f s) s := by + refine ⟨fun x _hx ↦ rfl, fun m _hm x hx ↦ ?_, fun m _hm x hx ↦ ?_⟩ + · have := (h.iteratedFDerivWithin hu m x hx).differentiableWithinAt.hasFDerivWithinAt + rwa [insert_eq_of_mem hx] at this + · exact (h.iteratedFDerivWithin hu m x hx).continuousWithinAt + +lemma AnalyticOn.exists_hasFTaylorSeriesUpToOn + (h : AnalyticOn 𝕜 f s) (hu : UniqueDiffOn 𝕜 s) : + ∃ (p : E → FormalMultilinearSeries 𝕜 E F), + HasFTaylorSeriesUpToOn ⊤ f p s ∧ ∀ i, AnalyticOn 𝕜 (fun x ↦ p x i) s := + ⟨ftaylorSeriesWithin 𝕜 f s, h.hasFTaylorSeriesUpToOn hu, h.iteratedFDerivWithin hu⟩ + +theorem AnalyticOnNhd.fderiv_of_isOpen (h : AnalyticOnNhd 𝕜 f s) (hs : IsOpen s) : + AnalyticOnNhd 𝕜 (fderiv 𝕜 f) s := by + rw [← hs.analyticOn_iff_analyticOnNhd] at h ⊢ + exact (h.fderivWithin hs.uniqueDiffOn).congr (fun x hx ↦ (fderivWithin_of_isOpen hs hx).symm) + +theorem AnalyticOnNhd.iteratedFDeriv_of_isOpen (h : AnalyticOnNhd 𝕜 f s) (hs : IsOpen s) (n : ℕ) : + AnalyticOnNhd 𝕜 (iteratedFDeriv 𝕜 n f) s := by + rw [← hs.analyticOn_iff_analyticOnNhd] at h ⊢ + exact (h.iteratedFDerivWithin hs.uniqueDiffOn n).congr + (fun x hx ↦ (iteratedFDerivWithin_of_isOpen n hs hx).symm) + +/-- If a partial homeomorphism `f` is analytic at a point `a`, with invertible derivative, then +its inverse is analytic at `f a`. -/ +theorem PartialHomeomorph.analyticAt_symm' (f : PartialHomeomorph E F) {a : E} + {i : E ≃L[𝕜] F} (h0 : a ∈ f.source) (h : AnalyticAt 𝕜 f a) (h' : fderiv 𝕜 f a = i) : + AnalyticAt 𝕜 f.symm (f a) := by + rcases h with ⟨p, hp⟩ + have : p 1 = (continuousMultilinearCurryFin1 𝕜 E F).symm i := by simp [← h', hp.fderiv_eq] + exact (f.hasFPowerSeriesAt_symm h0 hp this).analyticAt + +/-- If a partial homeomorphism `f` is analytic at a point `f.symm a`, with invertible derivative, +then its inverse is analytic at `a`. -/ +theorem PartialHomeomorph.analyticAt_symm (f : PartialHomeomorph E F) {a : F} + {i : E ≃L[𝕜] F} (h0 : a ∈ f.target) (h : AnalyticAt 𝕜 f (f.symm a)) + (h' : fderiv 𝕜 f (f.symm a) = i) : + AnalyticAt 𝕜 f.symm a := by + have : a = f (f.symm a) := by simp [h0] + rw [this] + exact f.analyticAt_symm' (by simp [h0]) h h' + end fderiv section deriv @@ -161,17 +444,29 @@ protected theorem HasFPowerSeriesAt.deriv (h : HasFPowerSeriesAt f p x) : deriv f x = p 1 fun _ => 1 := h.hasDerivAt.deriv -/-- If a function is analytic on a set `s`, so is its derivative. -/ -theorem AnalyticOn.deriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) : AnalyticOn 𝕜 (deriv f) s := - (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_analyticOn h.fderiv +/-- If a function is analytic on a set `s` in a complete space, so is its derivative. -/ +protected theorem AnalyticOnNhd.deriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) : + AnalyticOnNhd 𝕜 (deriv f) s := + (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_analyticOnNhd h.fderiv + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.deriv := AnalyticOnNhd.deriv + +/-- If a function is analytic on an open set `s`, so is its derivative. -/ +theorem AnalyticOnNhd.deriv_of_isOpen (h : AnalyticOnNhd 𝕜 f s) (hs : IsOpen s) : + AnalyticOnNhd 𝕜 (deriv f) s := + (ContinuousLinearMap.apply 𝕜 F (1 : 𝕜)).comp_analyticOnNhd (h.fderiv_of_isOpen hs) /-- If a function is analytic on a set `s`, so are its successive derivatives. -/ -theorem AnalyticOn.iterated_deriv [CompleteSpace F] (h : AnalyticOn 𝕜 f s) (n : ℕ) : - AnalyticOn 𝕜 (_root_.deriv^[n] f) s := by +theorem AnalyticOnNhd.iterated_deriv [CompleteSpace F] (h : AnalyticOnNhd 𝕜 f s) (n : ℕ) : + AnalyticOnNhd 𝕜 (_root_.deriv^[n] f) s := by induction n with | zero => exact h | succ n IH => simpa only [Function.iterate_succ', Function.comp_apply] using IH.deriv +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.iterated_deriv := AnalyticOnNhd.iterated_deriv + end deriv section fderiv @@ -258,7 +553,7 @@ theorem CPolynomialOn.contDiffOn (h : CPolynomialOn 𝕜 f s) {n : ℕ∞} : 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 m _ ↦ (H.iteratedFDeriv m).analyticOnNhd.differentiableOn.congr fun _ hx ↦ iteratedFDerivWithin_of_isOpen _ t_open hx) theorem CPolynomialAt.contDiffAt (h : CPolynomialAt 𝕜 f x) {n : ℕ∞} : @@ -341,6 +636,30 @@ protected theorem hasFDerivAt [DecidableEq ι] : HasFDerivAt f (f.linearDeriv x) convert f.hasFiniteFPowerSeriesOnBall.hasFDerivAt (y := x) ENNReal.coe_lt_top rw [zero_add] +/-- Given `f` a multilinear map, then the derivative of `x ↦ f (g₁ x, ..., gₙ x)` at `x` applied +to a vector `v` is given by `∑ i, f (g₁ x, ..., g'ᵢ v, ..., gₙ x)`. Version inside a set. -/ +theorem _root_.HasFDerivWithinAt.multilinear_comp + [DecidableEq ι] {G : Type*} [NormedAddCommGroup G] [NormedSpace 𝕜 G] + {g : ∀ i, G → E i} {g' : ∀ i, G →L[𝕜] E i} {s : Set G} {x : G} + (hg : ∀ i, HasFDerivWithinAt (g i) (g' i) s x) : + HasFDerivWithinAt (fun x ↦ f (fun i ↦ g i x)) + ((∑ i : ι, (f.toContinuousLinearMap (fun j ↦ g j x) i) ∘L (g' i))) s x := by + convert (f.hasFDerivAt (fun j ↦ g j x)).comp_hasFDerivWithinAt x (hasFDerivWithinAt_pi.2 hg) + ext v + simp [linearDeriv] + +/-- Given `f` a multilinear map, then the derivative of `x ↦ f (g₁ x, ..., gₙ x)` at `x` applied +to a vector `v` is given by `∑ i, f (g₁ x, ..., g'ᵢ v, ..., gₙ x)`. -/ +theorem _root_.HasFDerivAt.multilinear_comp + [DecidableEq ι] {G : Type*} [NormedAddCommGroup G] [NormedSpace 𝕜 G] + {g : ∀ i, G → E i} {g' : ∀ i, G →L[𝕜] E i} {x : G} + (hg : ∀ i, HasFDerivAt (g i) (g' i) x) : + HasFDerivAt (fun x ↦ f (fun i ↦ g i x)) + ((∑ i : ι, (f.toContinuousLinearMap (fun j ↦ g j x) i) ∘L (g' i))) x := by + convert (f.hasFDerivAt (fun j ↦ g j x)).comp x (hasFDerivAt_pi.2 hg) + ext v + simp [linearDeriv] + /-- Technical lemma used in the proof of `hasFTaylorSeriesUpTo_iteratedFDeriv`, to compare sums over embedding of `Fin k` and `Fin (k + 1)`. -/ private lemma _root_.Equiv.succ_embeddingFinSucc_fst_symm_apply {ι : Type*} [DecidableEq ι] @@ -495,3 +814,73 @@ theorem hasSum_iteratedFDeriv [CharZero 𝕜] {y : E} (hy : y ∈ EMetric.ball 0 mul_inv_cancel₀ <| cast_ne_zero.mpr n.factorial_ne_zero, one_smul] end HasFPowerSeriesOnBall + +/-! +### Derivative of a linear map into multilinear maps +-/ + +namespace ContinuousLinearMap + +variable {ι : Type*} {G : ι → Type*} [∀ i, NormedAddCommGroup (G i)] [∀ i, NormedSpace 𝕜 (G i)] + [Fintype ι] {H : Type*} [NormedAddCommGroup H] + [NormedSpace 𝕜 H] + +theorem hasFDerivAt_uncurry_of_multilinear [DecidableEq ι] + (f : E →L[𝕜] ContinuousMultilinearMap 𝕜 G F) (v : E × Π i, G i) : + HasFDerivAt (fun (p : E × Π i, G i) ↦ f p.1 p.2) + ((f.flipMultilinear v.2) ∘L (.fst _ _ _) + + ∑ i : ι, ((f v.1).toContinuousLinearMap v.2 i) ∘L (.proj _) ∘L (.snd _ _ _)) v := by + convert HasFDerivAt.multilinear_comp (f.continuousMultilinearMapOption) + (g := fun (_ : Option ι) p ↦ p) (g' := fun _ ↦ ContinuousLinearMap.id _ _) (x := v) + (fun _ ↦ hasFDerivAt_id _) + have I : f.continuousMultilinearMapOption.toContinuousLinearMap (fun _ ↦ v) none = + (f.flipMultilinear v.2) ∘L (.fst _ _ _) := by + simp [ContinuousMultilinearMap.toContinuousLinearMap, continuousMultilinearMapOption] + apply ContinuousLinearMap.ext (fun w ↦ ?_) + simp + have J : ∀ (i : ι), f.continuousMultilinearMapOption.toContinuousLinearMap (fun _ ↦ v) (some i) + = ((f v.1).toContinuousLinearMap v.2 i) ∘L (.proj _) ∘L (.snd _ _ _) := by + intro i + apply ContinuousLinearMap.ext (fun w ↦ ?_) + simp only [ContinuousMultilinearMap.toContinuousLinearMap, continuousMultilinearMapOption, + coe_mk', MultilinearMap.toLinearMap_apply, ContinuousMultilinearMap.coe_coe, + MultilinearMap.coe_mkContinuous, MultilinearMap.coe_mk, ne_eq, reduceCtorEq, + not_false_eq_true, Function.update_noteq, coe_comp', coe_snd', Function.comp_apply, + proj_apply] + congr + ext j + rcases eq_or_ne j i with rfl | hij + · simp + · simp [hij] + simp [I, J] + +/-- Given `f` a linear map into multilinear maps, then the derivative +of `x ↦ f (a x) (b₁ x, ..., bₙ x)` at `x` applied to a vector `v` is given by +`f (a' v) (b₁ x, ...., bₙ x) + ∑ i, f a (b₁ x, ..., b'ᵢ v, ..., bₙ x)`. Version inside a set. -/ +theorem _root_.HasFDerivWithinAt.linear_multilinear_comp + [DecidableEq ι] {a : H → E} {a' : H →L[𝕜] E} + {b : ∀ i, H → G i} {b' : ∀ i, H →L[𝕜] G i} {s : Set H} {x : H} + (ha : HasFDerivWithinAt a a' s x) (hb : ∀ i, HasFDerivWithinAt (b i) (b' i) s x) + (f : E →L[𝕜] ContinuousMultilinearMap 𝕜 G F) : + HasFDerivWithinAt (fun y ↦ f (a y) (fun i ↦ b i y)) + ((f.flipMultilinear (fun i ↦ b i x)) ∘L a' + + ∑ i, ((f (a x)).toContinuousLinearMap (fun j ↦ b j x) i) ∘L (b' i)) s x := by + convert (hasFDerivAt_uncurry_of_multilinear f (a x, fun i ↦ b i x)).comp_hasFDerivWithinAt x + (ha.prod (hasFDerivWithinAt_pi.mpr hb)) + ext v + simp + +/-- Given `f` a linear map into multilinear maps, then the derivative +of `x ↦ f (a x) (b₁ x, ..., bₙ x)` at `x` applied to a vector `v` is given by +`f (a' v) (b₁ x, ...., bₙ x) + ∑ i, f a (b₁ x, ..., b'ᵢ v, ..., bₙ x)`. -/ +theorem _root_.HasFDerivAt.linear_multilinear_comp [DecidableEq ι] {a : H → E} {a' : H →L[𝕜] E} + {b : ∀ i, H → G i} {b' : ∀ i, H →L[𝕜] G i} {x : H} + (ha : HasFDerivAt a a' x) (hb : ∀ i, HasFDerivAt (b i) (b' i) x) + (f : E →L[𝕜] ContinuousMultilinearMap 𝕜 G F) : + HasFDerivAt (fun y ↦ f (a y) (fun i ↦ b i y)) + ((f.flipMultilinear (fun i ↦ b i x)) ∘L a' + + ∑ i, ((f (a x)).toContinuousLinearMap (fun j ↦ b j x) i) ∘L (b' i)) x := by + simp_rw [← hasFDerivWithinAt_univ] at ha hb ⊢ + exact HasFDerivWithinAt.linear_multilinear_comp ha hb f + +end ContinuousLinearMap diff --git a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean index f156437148642..88e55627bf87e 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Basic.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Basic.lean @@ -895,7 +895,7 @@ theorem Filter.EventuallyEq.fderivWithin_eq (hs : f₁ =ᶠ[𝓝[s] x] f) (hx : 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_eventually_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) diff --git a/Mathlib/Analysis/Calculus/FDeriv/Comp.lean b/Mathlib/Analysis/Calculus/FDeriv/Comp.lean index beaf6fad6b9fe..410d6d1cf3e69 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Comp.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Comp.lean @@ -172,7 +172,7 @@ theorem Differentiable.comp_differentiableOn {g : F → G} (hg : Differentiable protected theorem HasStrictFDerivAt.comp {g : F → G} {g' : F →L[𝕜] G} (hg : HasStrictFDerivAt g g' (f x)) (hf : HasStrictFDerivAt f f' x) : HasStrictFDerivAt (fun x => g (f x)) (g'.comp f') x := - ((hg.comp_tendsto (hf.continuousAt.prod_map' hf.continuousAt)).trans_isBigO + ((hg.comp_tendsto (hf.continuousAt.prodMap' hf.continuousAt)).trans_isBigO hf.isBigO_sub).triangle <| by simpa only [g'.map_sub, f'.coe_comp'] using (g'.isBigO_comp _ _).trans_isLittleO hf diff --git a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean index 1c6738f520fcc..ac47ac267e108 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Equiv.lean @@ -339,7 +339,7 @@ inverse function. -/ theorem HasStrictFDerivAt.of_local_left_inverse {f : E → F} {f' : E ≃L[𝕜] F} {g : F → E} {a : F} (hg : ContinuousAt g a) (hf : HasStrictFDerivAt f (f' : E →L[𝕜] F) (g a)) (hfg : ∀ᶠ y in 𝓝 a, f (g y) = y) : HasStrictFDerivAt g (f'.symm : F →L[𝕜] E) a := by - replace hg := hg.prod_map' hg + replace hg := hg.prodMap' hg replace hfg := hfg.prod_mk_nhds hfg have : (fun p : F × F => g p.1 - g p.2 - f'.symm (p.1 - p.2)) =O[𝓝 (a, a)] fun p : F × F => @@ -355,7 +355,7 @@ theorem HasStrictFDerivAt.of_local_left_inverse {f : E → F} {f' : E ≃L[𝕜] · refine (hf.isBigO_sub_rev.comp_tendsto hg).congr' (Eventually.of_forall fun _ => rfl) (hfg.mono ?_) rintro p ⟨hp1, hp2⟩ - simp only [(· ∘ ·), hp1, hp2] + simp only [(· ∘ ·), hp1, hp2, Prod.map] /-- If `f (g y) = y` for `y` in some neighborhood of `a`, `g` is continuous at `a`, and `f` has an invertible derivative `f'` at `g a`, then `g` has the derivative `f'⁻¹` at `a`. diff --git a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean index 3066b3ab3c333..28e1539f0e516 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Measurable.lean @@ -303,7 +303,7 @@ theorem D_subset_differentiable_set {K : Set (E →L[𝕜] F)} (hK : IsComplete · simp [y_pos] have yzero : 0 < ‖y‖ := norm_pos_iff.mpr y_pos have y_lt : ‖y‖ < (1 / 2) ^ (n e + 1) := by simpa using mem_ball_iff_norm.1 hy - have yone : ‖y‖ ≤ 1 := le_trans y_lt.le (pow_le_one _ (by norm_num) (by norm_num)) + have yone : ‖y‖ ≤ 1 := le_trans y_lt.le (pow_le_one₀ (by norm_num) (by norm_num)) -- define the scale `k`. obtain ⟨k, hk, h'k⟩ : ∃ k : ℕ, (1 / 2) ^ (k + 1) < ‖y‖ ∧ ‖y‖ ≤ (1 / 2) ^ k := exists_nat_pow_near_of_lt_one yzero yone (by norm_num : (0 : ℝ) < 1 / 2) @@ -638,7 +638,7 @@ theorem D_subset_differentiable_set {K : Set F} (hK : IsComplete K) : · simp only [sub_self, zero_smul, norm_zero, mul_zero, le_rfl] have yzero : 0 < y - x := sub_pos.2 xy have y_le : y - x ≤ (1 / 2) ^ (n e + 1) := by linarith [hy.2] - have yone : y - x ≤ 1 := le_trans y_le (pow_le_one _ (by norm_num) (by norm_num)) + have yone : y - x ≤ 1 := le_trans y_le (pow_le_one₀ (by norm_num) (by norm_num)) -- define the scale `k`. obtain ⟨k, hk, h'k⟩ : ∃ k : ℕ, (1 / 2) ^ (k + 1) < y - x ∧ y - x ≤ (1 / 2) ^ k := exists_nat_pow_near_of_lt_one yzero yone (by norm_num : (0 : ℝ) < 1 / 2) diff --git a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean index d867ef086d9c7..990bb02bd9599 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Mul.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Mul.lean @@ -573,10 +573,10 @@ theorem hasStrictFDerivAt_list_prod_finRange' {n : ℕ} {x : Fin n → 𝔸} : theorem hasStrictFDerivAt_list_prod_attach' [DecidableEq ι] {l : List ι} {x : {i // i ∈ l} → 𝔸} : HasStrictFDerivAt (𝕜 := 𝕜) (fun x ↦ (l.attach.map x).prod) (∑ i : Fin l.length, ((l.attach.take i).map x).prod • - smulRight (proj l.attach[i.cast l.length_attach.symm]) + smulRight (proj l.attach[i.cast List.length_attach.symm]) ((l.attach.drop (.succ i)).map x).prod) x := hasStrictFDerivAt_list_prod'.congr_fderiv <| Eq.symm <| - Finset.sum_equiv (finCongr l.length_attach.symm) (by simp) (by simp) + Finset.sum_equiv (finCongr List.length_attach.symm) (by simp) (by simp) @[fun_prop] theorem hasFDerivAt_list_prod' [Fintype ι] {l : List ι} {x : ι → 𝔸'} : @@ -596,7 +596,7 @@ theorem hasFDerivAt_list_prod_finRange' {n : ℕ} {x : Fin n → 𝔸} : theorem hasFDerivAt_list_prod_attach' [DecidableEq ι] {l : List ι} {x : {i // i ∈ l} → 𝔸} : HasFDerivAt (𝕜 := 𝕜) (fun x ↦ (l.attach.map x).prod) (∑ i : Fin l.length, ((l.attach.take i).map x).prod • - smulRight (proj l.attach[i.cast l.length_attach.symm]) + smulRight (proj l.attach[i.cast List.length_attach.symm]) ((l.attach.drop (.succ i)).map x).prod) x := hasStrictFDerivAt_list_prod_attach'.hasFDerivAt @@ -648,7 +648,7 @@ theorem HasStrictFDerivAt.list_prod' {l : List ι} {x : E} smulRight (f' l[i]) ((l.drop (.succ i)).map (f · x)).prod) x := by simp only [← List.finRange_map_get l, List.map_map] refine .congr_fderiv (hasStrictFDerivAt_list_prod_finRange'.comp x - (hasStrictFDerivAt_pi.mpr fun i ↦ h l[i] (l.getElem_mem ..))) ?_ + (hasStrictFDerivAt_pi.mpr fun i ↦ h l[i] (List.getElem_mem ..))) ?_ ext m simp [← List.map_map] @@ -663,7 +663,7 @@ theorem HasFDerivAt.list_prod' {l : List ι} {x : E} smulRight (f' l[i]) ((l.drop (.succ i)).map (f · x)).prod) x := by simp only [← List.finRange_map_get l, List.map_map] refine .congr_fderiv (hasFDerivAt_list_prod_finRange'.comp x - (hasFDerivAt_pi.mpr fun i ↦ h l[i] (l.getElem_mem i i.isLt))) ?_ + (hasFDerivAt_pi.mpr fun i ↦ h l[i] (List.getElem_mem i.isLt))) ?_ ext m simp [← List.map_map] diff --git a/Mathlib/Analysis/Calculus/FDeriv/Norm.lean b/Mathlib/Analysis/Calculus/FDeriv/Norm.lean new file mode 100644 index 0000000000000..b43a36ea81d3a --- /dev/null +++ b/Mathlib/Analysis/Calculus/FDeriv/Norm.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2024 Etienne Marion. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Etienne Marion +-/ +import Mathlib.Analysis.Calculus.Deriv.Abs +import Mathlib.Analysis.Calculus.LineDeriv.Basic + +/-! +# Differentiability of the norm in a real normed vector space + +This file provides basic results about the differentiability of the norm in a real vector space. +Most are of the following kind: if the norm has some differentiability property +(`DifferentiableAt`, `ContDiffAt`, `HasStrictFDerivAt`, `HasFDerivAt`) at `x`, then so it has +at `t • x` when `t ≠ 0`. + +## Main statements + +* `ContDiffAt.contDiffAt_norm_smul`: If the norm is continuously differentiable up to order `n` + at `x`, then so it is at `t • x` when `t ≠ 0`. +* `differentiableAt_norm_smul`: If `t ≠ 0`, the norm is differentiable at `x` if and only if + it is at `t • x`. +* `HasFDerivAt.hasFDerivAt_norm_smul`: If the norm has a Fréchet derivative `f` at `x` and `t ≠ 0`, + then it has `(SignType t) • f` as a Fréchet derivative at `t · x`. +* `fderiv_norm_smul` : `fderiv ℝ (‖·‖) (t • x) = (SignType.sign t : ℝ) • (fderiv ℝ (‖·‖) x)`, + this holds without any differentiability assumptions. +* `DifferentiableAt.fderiv_norm_self`: if the norm is differentiable at `x`, + then `fderiv ℝ (‖·‖) x x = ‖x‖`. +* `norm_fderiv_norm`: if the norm is differentiable at `x` then the operator norm of its derivative + is `1` (on a non trivial space). + +## Tags + +differentiability, norm + +-/ + +open ContinuousLinearMap Filter NNReal Real Set + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] +variable {n : ℕ∞} {f : E →L[ℝ] ℝ} {x : E} {t : ℝ} + +variable (E) in +theorem not_differentiableAt_norm_zero [Nontrivial E] : + ¬DifferentiableAt ℝ (‖·‖) (0 : E) := by + obtain ⟨x, hx⟩ := NormedSpace.exists_lt_norm ℝ E 0 + intro h + have : DifferentiableAt ℝ (fun t : ℝ ↦ ‖t • x‖) 0 := DifferentiableAt.comp _ (by simpa) (by simp) + have : DifferentiableAt ℝ (|·|) (0 : ℝ) := by + simp_rw [norm_smul, norm_eq_abs] at this + have aux : abs = fun t ↦ (1 / ‖x‖) * (|t| * ‖x‖) := by field_simp + rw [aux] + exact this.const_mul _ + exact not_differentiableAt_abs_zero this + +theorem ContDiffAt.contDiffAt_norm_smul (ht : t ≠ 0) (h : ContDiffAt ℝ n (‖·‖) x) : + ContDiffAt ℝ n (‖·‖) (t • x) := by + have h1 : ContDiffAt ℝ n (fun y ↦ t⁻¹ • y) (t • x) := (contDiff_const_smul t⁻¹).contDiffAt + have h2 : ContDiffAt ℝ n (fun y ↦ |t| * ‖y‖) x := h.const_smul |t| + conv at h2 => enter [4]; rw [← one_smul ℝ x, ← inv_mul_cancel₀ ht, mul_smul] + convert h2.comp (t • x) h1 using 1 + ext y + simp only [Function.comp_apply] + rw [norm_smul, ← mul_assoc, norm_eq_abs, ← abs_mul, mul_inv_cancel₀ ht, abs_one, one_mul] + +theorem contDiffAt_norm_smul_iff (ht : t ≠ 0) : + ContDiffAt ℝ n (‖·‖) x ↔ ContDiffAt ℝ n (‖·‖) (t • x) where + mp h := h.contDiffAt_norm_smul ht + mpr hd := by + convert hd.contDiffAt_norm_smul (inv_ne_zero ht) + rw [smul_smul, inv_mul_cancel₀ ht, one_smul] + +theorem ContDiffAt.contDiffAt_norm_of_smul (h : ContDiffAt ℝ n (‖·‖) (t • x)) : + ContDiffAt ℝ n (‖·‖) x := by + obtain rfl | hn : n = 0 ∨ 1 ≤ n := by + rw [← ENat.lt_one_iff_eq_zero] + exact lt_or_le .. + · rw [contDiffAt_zero] + exact ⟨univ, univ_mem, continuous_norm.continuousOn⟩ + obtain rfl | ht := eq_or_ne t 0 + · by_cases hE : Nontrivial E + · rw [zero_smul] at h + exact (mt (ContDiffAt.differentiableAt · hn)) (not_differentiableAt_norm_zero E) h |>.elim + · rw [not_nontrivial_iff_subsingleton] at hE + rw [eq_const_of_subsingleton (‖·‖) 0] + exact contDiffAt_const + · exact contDiffAt_norm_smul_iff ht |>.2 h + +theorem HasStrictFDerivAt.hasStrictFDerivAt_norm_smul + (ht : t ≠ 0) (h : HasStrictFDerivAt (‖·‖) f x) : + HasStrictFDerivAt (‖·‖) ((SignType.sign t : ℝ) • f) (t • x) := by + have h1 : HasStrictFDerivAt (fun y ↦ t⁻¹ • y) (t⁻¹ • ContinuousLinearMap.id ℝ E) (t • x) := + hasStrictFDerivAt_id (t • x) |>.const_smul t⁻¹ + have h2 : HasStrictFDerivAt (fun y ↦ |t| * ‖y‖) (|t| • f) x := h.const_smul |t| + conv at h2 => enter [3]; rw [← one_smul ℝ x, ← inv_mul_cancel₀ ht, mul_smul] + convert h2.comp (t • x) h1 with y + · rw [norm_smul, ← mul_assoc, norm_eq_abs, ← abs_mul, mul_inv_cancel₀ ht, abs_one, one_mul] + ext y + simp only [coe_smul', Pi.smul_apply, smul_eq_mul, comp_smulₛₗ, map_inv₀, RingHom.id_apply, + comp_id] + rw [eq_inv_mul_iff_mul_eq₀ ht, ← mul_assoc, self_mul_sign] + +theorem HasStrictFDerivAt.hasStrictDerivAt_norm_smul_neg + (ht : t < 0) (h : HasStrictFDerivAt (‖·‖) f x) : + HasStrictFDerivAt (‖·‖) (-f) (t • x) := by + simpa [ht] using h.hasStrictFDerivAt_norm_smul ht.ne + +theorem HasStrictFDerivAt.hasStrictDerivAt_norm_smul_pos + (ht : 0 < t) (h : HasStrictFDerivAt (‖·‖) f x) : + HasStrictFDerivAt (‖·‖) f (t • x) := by + simpa [ht] using h.hasStrictFDerivAt_norm_smul ht.ne' + +theorem HasFDerivAt.hasFDerivAt_norm_smul + (ht : t ≠ 0) (h : HasFDerivAt (‖·‖) f x) : + HasFDerivAt (‖·‖) ((SignType.sign t : ℝ) • f) (t • x) := by + have h1 : HasFDerivAt (fun y ↦ t⁻¹ • y) (t⁻¹ • ContinuousLinearMap.id ℝ E) (t • x) := + hasFDerivAt_id (t • x) |>.const_smul t⁻¹ + have h2 : HasFDerivAt (fun y ↦ |t| * ‖y‖) (|t| • f) x := h.const_smul |t| + conv at h2 => enter [3]; rw [← one_smul ℝ x, ← inv_mul_cancel₀ ht, mul_smul] + convert h2.comp (t • x) h1 using 2 with y + · simp only [Function.comp_apply] + rw [norm_smul, ← mul_assoc, norm_eq_abs, ← abs_mul, mul_inv_cancel₀ ht, abs_one, one_mul] + · ext y + simp only [coe_smul', Pi.smul_apply, smul_eq_mul, comp_smulₛₗ, map_inv₀, RingHom.id_apply, + comp_id] + rw [eq_inv_mul_iff_mul_eq₀ ht, ← mul_assoc, self_mul_sign] + +theorem HasFDerivAt.hasFDerivAt_norm_smul_neg + (ht : t < 0) (h : HasFDerivAt (‖·‖) f x) : + HasFDerivAt (‖·‖) (-f) (t • x) := by + simpa [ht] using h.hasFDerivAt_norm_smul ht.ne + +theorem HasFDerivAt.hasFDerivAt_norm_smul_pos + (ht : 0 < t) (h : HasFDerivAt (‖·‖) f x) : + HasFDerivAt (‖·‖) f (t • x) := by + simpa [ht] using h.hasFDerivAt_norm_smul ht.ne' + +theorem differentiableAt_norm_smul (ht : t ≠ 0) : + DifferentiableAt ℝ (‖·‖) x ↔ DifferentiableAt ℝ (‖·‖) (t • x) where + mp hd := (hd.hasFDerivAt.hasFDerivAt_norm_smul ht).differentiableAt + mpr hd := by + convert (hd.hasFDerivAt.hasFDerivAt_norm_smul (inv_ne_zero ht)).differentiableAt + rw [smul_smul, inv_mul_cancel₀ ht, one_smul] + +theorem DifferentiableAt.differentiableAt_norm_of_smul (h : DifferentiableAt ℝ (‖·‖) (t • x)) : + DifferentiableAt ℝ (‖·‖) x := by + obtain rfl | ht := eq_or_ne t 0 + · by_cases hE : Nontrivial E + · rw [zero_smul] at h + exact not_differentiableAt_norm_zero E h |>.elim + · rw [not_nontrivial_iff_subsingleton] at hE + exact (hasFDerivAt_of_subsingleton _ _).differentiableAt + · exact differentiableAt_norm_smul ht |>.2 h + +theorem DifferentiableAt.fderiv_norm_self {x : E} (h : DifferentiableAt ℝ (‖·‖) x) : + fderiv ℝ (‖·‖) x x = ‖x‖ := by + rw [← h.lineDeriv_eq_fderiv, lineDeriv] + have this (t : ℝ) : ‖x + t • x‖ = |1 + t| * ‖x‖ := by + rw [← norm_eq_abs, ← norm_smul, add_smul, one_smul] + simp_rw [this] + rw [deriv_mul_const] + · conv_lhs => enter [1, 1]; change _root_.abs ∘ (fun t ↦ 1 + t) + rw [deriv.comp, deriv_abs, deriv_const_add] + · simp + · exact differentiableAt_abs (by norm_num) + · exact differentiableAt_id.const_add _ + · exact (differentiableAt_abs (by norm_num)).comp _ (differentiableAt_id.const_add _) + +variable (x t) in +theorem fderiv_norm_smul : + fderiv ℝ (‖·‖) (t • x) = (SignType.sign t : ℝ) • (fderiv ℝ (‖·‖) x) := by + by_cases hE : Nontrivial E + · by_cases hd : DifferentiableAt ℝ (‖·‖) x + · obtain rfl | ht := eq_or_ne t 0 + · simp only [zero_smul, _root_.sign_zero, SignType.coe_zero] + exact fderiv_zero_of_not_differentiableAt <| not_differentiableAt_norm_zero E + · rw [(hd.hasFDerivAt.hasFDerivAt_norm_smul ht).fderiv] + · rw [fderiv_zero_of_not_differentiableAt hd, fderiv_zero_of_not_differentiableAt] + · simp + · exact mt DifferentiableAt.differentiableAt_norm_of_smul hd + · rw [not_nontrivial_iff_subsingleton] at hE + simp_rw [(hasFDerivAt_of_subsingleton _ _).fderiv, smul_zero] + +theorem fderiv_norm_smul_pos (ht : 0 < t) : + fderiv ℝ (‖·‖) (t • x) = fderiv ℝ (‖·‖) x := by + simp [fderiv_norm_smul, ht] + +theorem fderiv_norm_smul_neg (ht : t < 0) : + fderiv ℝ (‖·‖) (t • x) = -fderiv ℝ (‖·‖) x := by + simp [fderiv_norm_smul, ht] + +theorem norm_fderiv_norm [Nontrivial E] (h : DifferentiableAt ℝ (‖·‖) x) : + ‖fderiv ℝ (‖·‖) x‖ = 1 := by + have : x ≠ 0 := fun hx ↦ not_differentiableAt_norm_zero E (hx ▸ h) + refine le_antisymm (NNReal.coe_one ▸ norm_fderiv_le_of_lipschitz ℝ lipschitzWith_one_norm) ?_ + apply le_of_mul_le_mul_right _ (norm_pos_iff.2 this) + calc + 1 * ‖x‖ = fderiv ℝ (‖·‖) x x := by rw [one_mul, h.fderiv_norm_self] + _ ≤ ‖fderiv ℝ (‖·‖) x x‖ := le_norm_self _ + _ ≤ ‖fderiv ℝ (‖·‖) x‖ * ‖x‖ := le_opNorm _ _ diff --git a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean index 1835d8c1d6fa5..399dada358cca 100644 --- a/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean +++ b/Mathlib/Analysis/Calculus/FDeriv/Symmetric.lean @@ -97,8 +97,8 @@ theorem Convex.taylor_approx_two_segment {v w : E} (hv : x + v ∈ interior s) rw [← smul_smul] apply s_conv.interior.add_smul_mem this _ ht rw [add_assoc] at hw - rw [add_assoc, ← smul_add] - exact s_conv.add_smul_mem_interior xs hw ⟨hpos, h_lt_1.le⟩ + convert s_conv.add_smul_mem_interior xs hw ⟨hpos, h_lt_1.le⟩ using 1 + module -- define a function `g` on `[0,1]` (identified with `[v, v + w]`) such that `g 1 - g 0` is the -- quantity to be estimated. We will check that its derivative is given by an explicit -- expression `g'`, that we can bound. Then the desired bound for `g 1 - g 0` follows from the @@ -139,14 +139,14 @@ theorem Convex.taylor_approx_two_segment {v w : E} (hv : x + v ∈ interior s) calc ‖g' t‖ = ‖(f' (x + h • v + (t * h) • w) - f' x - f'' (h • v + (t * h) • w)) (h • w)‖ := by rw [hg'] - have : h * (t * h) = t * (h * h) := by ring - simp only [ContinuousLinearMap.coe_sub', ContinuousLinearMap.map_add, pow_two, - ContinuousLinearMap.add_apply, Pi.smul_apply, smul_sub, smul_add, smul_smul, ← sub_sub, - ContinuousLinearMap.coe_smul', Pi.sub_apply, ContinuousLinearMap.map_smul, this] + congrm ‖?_‖ + simp only [ContinuousLinearMap.sub_apply, ContinuousLinearMap.add_apply, + ContinuousLinearMap.smul_apply, map_add, map_smul] + module _ ≤ ‖f' (x + h • v + (t * h) • w) - f' x - f'' (h • v + (t * h) • w)‖ * ‖h • w‖ := (ContinuousLinearMap.le_opNorm _ _) _ ≤ ε * ‖h • v + (t * h) • w‖ * ‖h • w‖ := by - apply mul_le_mul_of_nonneg_right _ (norm_nonneg _) + gcongr have H : x + h • v + (t * h) • w ∈ Metric.ball x δ ∩ interior s := by refine ⟨?_, xt_mem t ⟨ht.1, ht.2.le⟩⟩ rw [add_assoc, add_mem_ball_iff_norm] @@ -157,7 +157,7 @@ theorem Convex.taylor_approx_two_segment {v w : E} (hv : x + v ∈ interior s) apply (norm_add_le _ _).trans gcongr simp only [norm_smul, Real.norm_eq_abs, abs_mul, abs_of_nonneg, ht.1, hpos.le, mul_assoc] - exact mul_le_of_le_one_left (mul_nonneg hpos.le (norm_nonneg _)) ht.2.le + exact mul_le_of_le_one_left (by positivity) ht.2.le _ = ε * ((‖v‖ + ‖w‖) * ‖w‖) * h ^ 2 := by simp only [norm_smul, Real.norm_eq_abs, abs_mul, abs_of_nonneg, hpos.le]; ring -- conclude using the mean value inequality @@ -169,8 +169,8 @@ theorem Convex.taylor_approx_two_segment {v w : E} (hv : x + v ∈ interior s) simp only [g, Nat.one_ne_zero, add_zero, one_mul, zero_div, zero_mul, sub_zero, zero_smul, Ne, not_false_iff, zero_pow, reduceCtorEq] abel - · simp only [Real.norm_eq_abs, abs_mul, add_nonneg (norm_nonneg v) (norm_nonneg w), abs_of_nonneg, - hpos.le, mul_assoc, norm_nonneg, abs_pow] + · simp (discharger := positivity) only [Real.norm_eq_abs, abs_mul, abs_of_nonneg, abs_pow] + ring /-- One can get `f'' v w` as the limit of `h ^ (-2)` times the alternate sum of the values of `f` along the vertices of a quadrilateral with sides `h v` and `h w` based at `x`. @@ -183,40 +183,27 @@ theorem Convex.isLittleO_alternate_sum_square {v w : E} (h4v : x + (4 : ℝ) • fun h => h ^ 2 := by have A : (1 : ℝ) / 2 ∈ Ioc (0 : ℝ) 1 := ⟨by norm_num, by norm_num⟩ have B : (1 : ℝ) / 2 ∈ Icc (0 : ℝ) 1 := ⟨by norm_num, by norm_num⟩ - have C : ∀ w : E, (2 : ℝ) • w = 2 • w := fun w => by simp only [two_smul] have h2v2w : x + (2 : ℝ) • v + (2 : ℝ) • w ∈ interior s := by convert s_conv.interior.add_smul_sub_mem h4v h4w B using 1 - simp only [smul_sub, smul_smul, one_div, add_sub_add_left_eq_sub, mul_add, add_smul] - norm_num - simp only [show (4 : ℝ) = (2 : ℝ) + (2 : ℝ) by norm_num, _root_.add_smul] - abel + module have h2vww : x + (2 • v + w) + w ∈ interior s := by convert h2v2w using 1 - simp only [two_smul] - abel + module have h2v : x + (2 : ℝ) • v ∈ interior s := by convert s_conv.add_smul_sub_mem_interior xs h4v A using 1 - simp only [smul_smul, one_div, add_sub_cancel_left, add_right_inj] - norm_num + module have h2w : x + (2 : ℝ) • w ∈ interior s := by convert s_conv.add_smul_sub_mem_interior xs h4w A using 1 - simp only [smul_smul, one_div, add_sub_cancel_left, add_right_inj] - norm_num + module have hvw : x + (v + w) ∈ interior s := by convert s_conv.add_smul_sub_mem_interior xs h2v2w A using 1 - simp only [smul_smul, one_div, add_sub_cancel_left, add_right_inj, smul_add, smul_sub] - norm_num - abel + module have h2vw : x + (2 • v + w) ∈ interior s := by convert s_conv.interior.add_smul_sub_mem h2v h2v2w B using 1 - simp only [smul_add, smul_sub, smul_smul, ← C] - norm_num - abel + module have hvww : x + (v + w) + w ∈ interior s := by convert s_conv.interior.add_smul_sub_mem h2w h2v2w B using 1 - rw [one_div, add_sub_add_right_eq_sub, add_sub_cancel_left, inv_smul_smul₀ two_ne_zero, - two_smul] - abel + module have TA1 := s_conv.taylor_approx_two_segment hf xs hx h2vw h2vww have TA2 := s_conv.taylor_approx_two_segment hf xs hx hvw hvww convert TA1.sub TA2 using 1 @@ -245,11 +232,9 @@ theorem Convex.second_derivative_within_at_symmetric_of_mem_interior {v w : E} apply C.congr' _ _ · filter_upwards [self_mem_nhdsWithin] intro h (hpos : 0 < h) - rw [← one_smul ℝ (f'' w v - f'' v w), smul_smul, smul_smul] - congr 1 - field_simp [LT.lt.ne' hpos] + match_scalars <;> field_simp · filter_upwards [self_mem_nhdsWithin] with h (hpos : 0 < h) - field_simp [LT.lt.ne' hpos, SMul.smul] + field_simp simpa only [sub_eq_zero] using isLittleO_const_const_iff.1 B end @@ -298,8 +283,8 @@ theorem Convex.second_derivative_within_at_symmetric {s : Set E} (s_conv : Conve s_conv.second_derivative_within_at_symmetric_of_mem_interior hf xs hx (ts w) (ts v) simp only [ContinuousLinearMap.map_add, ContinuousLinearMap.map_smul, smul_add, smul_smul, ContinuousLinearMap.add_apply, Pi.smul_apply, ContinuousLinearMap.coe_smul', C] at this - rw [add_assoc, add_assoc, add_right_inj, add_left_comm, add_right_inj, add_right_inj, mul_comm] - at this + have : (t v * t w) • (f'' v) w = (t v * t w) • (f'' w) v := by + linear_combination (norm := module) this apply smul_right_injective F _ this simp [(tpos v).ne', (tpos w).ne'] diff --git a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean index 5474585d6e11e..06d42a093e031 100644 --- a/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean +++ b/Mathlib/Analysis/Calculus/FormalMultilinearSeries.lean @@ -302,7 +302,7 @@ noncomputable def fslope (p : FormalMultilinearSeries 𝕜 𝕜 E) : FormalMulti theorem coeff_fslope : p.fslope.coeff n = p.coeff (n + 1) := by simp only [fslope, coeff, ContinuousMultilinearMap.curryLeft_apply] congr 1 - exact Fin.cons_self_tail 1 + exact Fin.cons_self_tail (fun _ => (1 : 𝕜)) @[simp] theorem coeff_iterate_fslope (k n : ℕ) : (fslope^[k] p).coeff n = p.coeff (n + k) := by diff --git a/Mathlib/Analysis/Calculus/Implicit.lean b/Mathlib/Analysis/Calculus/Implicit.lean index 72620c2d28d46..2e323d8872a82 100644 --- a/Mathlib/Analysis/Calculus/Implicit.lean +++ b/Mathlib/Analysis/Calculus/Implicit.lean @@ -326,12 +326,12 @@ theorem to_implicitFunctionOfComplemented (hf : HasStrictFDerivAt f f' a) (hf' : · ext -- Porting note: added parentheses to help `simp` simp only [Classical.choose_spec hker, implicitFunctionDataOfComplemented, - ContinuousLinearMap.comp_apply, Submodule.coe_subtypeL', Submodule.coeSubtype, + ContinuousLinearMap.comp_apply, Submodule.coe_subtypeL', Submodule.coe_subtype, ContinuousLinearMap.id_apply] swap · ext -- Porting note: added parentheses to help `simp` - simp only [(ContinuousLinearMap.comp_apply), Submodule.coe_subtypeL', Submodule.coeSubtype, + simp only [(ContinuousLinearMap.comp_apply), Submodule.coe_subtypeL', Submodule.coe_subtype, LinearMap.map_coe_ker, (ContinuousLinearMap.zero_apply)] simp only [implicitFunctionDataOfComplemented, map_sub, sub_self] diff --git a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean index ea6f8405c48bf..67b3db1e4cd80 100644 --- a/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean +++ b/Mathlib/Analysis/Calculus/InverseFunctionTheorem/ApproximatesLinearOn.lean @@ -144,7 +144,7 @@ theorem surjOn_closedBall_of_nonlinearRightInverse simp only [dist_le_zero] at this rw [this] have If' : (0 : ℝ) < f'symm.nnnorm := by rw [← inv_pos]; exact (NNReal.coe_nonneg _).trans_lt hc - have Icf' : (c : ℝ) * f'symm.nnnorm < 1 := by rwa [inv_eq_one_div, lt_div_iff If'] at hc + have Icf' : (c : ℝ) * f'symm.nnnorm < 1 := by rwa [inv_eq_one_div, lt_div_iff₀ If'] at hc have Jf' : (f'symm.nnnorm : ℝ) ≠ 0 := ne_of_gt If' have Jcf' : (1 : ℝ) - c * f'symm.nnnorm ≠ 0 := by apply ne_of_gt; linarith /- We have to show that `y` can be written as `f x` for some `x ∈ closedBall b ε`. diff --git a/Mathlib/Analysis/Calculus/LHopital.lean b/Mathlib/Analysis/Calculus/LHopital.lean index 653749f47e528..f1e691d8342cf 100644 --- a/Mathlib/Analysis/Calculus/LHopital.lean +++ b/Mathlib/Analysis/Calculus/LHopital.lean @@ -143,7 +143,7 @@ theorem lhopital_zero_atTop_on_Ioi (hff' : ∀ x ∈ Ioi a, HasDerivAt f (f' x) ⟨lt_of_le_of_lt (le_max_left a 0) (lt_one_add _), lt_of_le_of_lt (le_max_right a 0) (lt_one_add _)⟩⟩ have fact1 : ∀ x : ℝ, x ∈ Ioo 0 a'⁻¹ → x ≠ 0 := fun _ hx => (ne_of_lt hx.1).symm - have fact2 : ∀ x ∈ Ioo 0 a'⁻¹, a < x⁻¹ := fun _ hx => lt_trans haa' ((lt_inv ha' hx.1).mpr hx.2) + have fact2 (x) (hx : x ∈ Ioo 0 a'⁻¹) : a < x⁻¹ := lt_trans haa' ((lt_inv_comm₀ ha' hx.1).mpr hx.2) have hdnf : ∀ x ∈ Ioo 0 a'⁻¹, HasDerivAt (f ∘ Inv.inv) (f' x⁻¹ * -(x ^ 2)⁻¹) x := fun x hx => comp x (hff' x⁻¹ <| fact2 x hx) (hasDerivAt_inv <| fact1 x hx) have hdng : ∀ x ∈ Ioo 0 a'⁻¹, HasDerivAt (g ∘ Inv.inv) (g' x⁻¹ * -(x ^ 2)⁻¹) x := fun x hx => @@ -161,7 +161,7 @@ theorem lhopital_zero_atTop_on_Ioi (hff' : ∀ x ∈ Ioi a, HasDerivAt f (f' x) intro x hx unfold Function.comp simp only - erw [mul_div_mul_right] + rw [mul_div_mul_right] exact neg_ne_zero.mpr (inv_ne_zero <| pow_ne_zero _ <| ne_of_gt hx)) have := this.comp tendsto_inv_atTop_zero' unfold Function.comp at this diff --git a/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean b/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean index 6d2876fdc8402..81863eb235bbc 100644 --- a/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean +++ b/Mathlib/Analysis/Calculus/LineDeriv/IntegrationByParts.lean @@ -44,7 +44,7 @@ TODO: prove similar theorems assuming that the functions tend to zero at infinit integrable derivatives. -/ -open MeasureTheory Measure FiniteDimensional +open MeasureTheory Measure Module variable {E F G W : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [NormedAddCommGroup F] [NormedSpace ℝ F] [NormedAddCommGroup G] [NormedSpace ℝ G] [NormedAddCommGroup W] diff --git a/Mathlib/Analysis/Calculus/MeanValue.lean b/Mathlib/Analysis/Calculus/MeanValue.lean index 7459bc396a5f2..703da3c9d5c78 100644 --- a/Mathlib/Analysis/Calculus/MeanValue.lean +++ b/Mathlib/Analysis/Calculus/MeanValue.lean @@ -901,7 +901,7 @@ theorem Convex.mul_sub_lt_image_sub_of_lt_deriv {D : Set ℝ} (hD : Convex ℝ D obtain ⟨a, a_mem, ha⟩ : ∃ a ∈ Ioo x y, deriv f a = (f y - f x) / (y - x) := exists_deriv_eq_slope f hxy (hf.mono hxyD) (hf'.mono hxyD') have : C < (f y - f x) / (y - x) := ha ▸ hf'_gt _ (hxyD' a_mem) - exact (lt_div_iff (sub_pos.2 hxy)).1 this + exact (lt_div_iff₀ (sub_pos.2 hxy)).1 this /-- Let `f : ℝ → ℝ` be a differentiable function. If `C < f'`, then `f` grows faster than `C * x`, i.e., `C * (y - x) < f y - f x` whenever `x < y`. -/ diff --git a/Mathlib/Analysis/Calculus/ParametricIntegral.lean b/Mathlib/Analysis/Calculus/ParametricIntegral.lean index e6088a80f8437..6bafbed0ec063 100644 --- a/Mathlib/Analysis/Calculus/ParametricIntegral.lean +++ b/Mathlib/Analysis/Calculus/ParametricIntegral.lean @@ -140,7 +140,7 @@ theorem hasFDerivAt_integral_of_dominated_loc_of_lip' {F' : α → H →L[𝕜] gcongr; exact (F' a).le_opNorm _ _ ≤ b a + ‖F' a‖ := ?_ simp only [← div_eq_inv_mul] - apply_rules [add_le_add, div_le_of_nonneg_of_le_mul] <;> first | rfl | positivity + apply_rules [add_le_add, div_le_of_le_mul₀] <;> first | rfl | positivity · exact b_int.add hF'_int.norm · apply h_diff.mono intro a ha diff --git a/Mathlib/Analysis/Calculus/Rademacher.lean b/Mathlib/Analysis/Calculus/Rademacher.lean index b1924f51dde25..67771abec0dce 100644 --- a/Mathlib/Analysis/Calculus/Rademacher.lean +++ b/Mathlib/Analysis/Calculus/Rademacher.lean @@ -42,7 +42,7 @@ See `LipschitzWith.hasFderivAt_of_hasLineDerivAt_of_closure`. * [Pertti Mattila, Geometry of sets and measures in Euclidean spaces, Theorem 7.3][Federer1996] -/ -open Filter MeasureTheory Measure FiniteDimensional Metric Set Asymptotics +open Filter MeasureTheory Measure Module Metric Set Asymptotics open scoped NNReal ENNReal Topology @@ -386,3 +386,18 @@ theorem LipschitzWith.ae_differentiableAt {f : E → F} (h : LipschitzWith C f) ∀ᵐ x ∂μ, DifferentiableAt ℝ f x := by rw [← lipschitzOnWith_univ] at h simpa [differentiableWithinAt_univ] using h.ae_differentiableWithinAt_of_mem + +/-- In a real finite-dimensional normed vector space, + the norm is almost everywhere differentiable. -/ +theorem ae_differentiableAt_norm : + ∀ᵐ x ∂μ, DifferentiableAt ℝ (‖·‖) x := lipschitzWith_one_norm.ae_differentiableAt + +omit [MeasurableSpace E] in +/-- In a real finite-dimensional normed vector space, + the set of points where the norm is differentiable at is dense. -/ +theorem dense_differentiableAt_norm : + Dense {x : E | DifferentiableAt ℝ (‖·‖) x} := + let _ : MeasurableSpace E := borel E + have _ : BorelSpace E := ⟨rfl⟩ + let w := Basis.ofVectorSpace ℝ E + MeasureTheory.Measure.dense_of_ae (ae_differentiableAt_norm (μ := w.addHaar)) diff --git a/Mathlib/Analysis/Calculus/TangentCone.lean b/Mathlib/Analysis/Calculus/TangentCone.lean index 280e5356cb943..f3ac765b70a30 100644 --- a/Mathlib/Analysis/Calculus/TangentCone.lean +++ b/Mathlib/Analysis/Calculus/TangentCone.lean @@ -81,7 +81,7 @@ theorem mem_tangentConeAt_of_pow_smul {r : 𝕜} (hr₀ : r ≠ 0) (hr : ‖r‖ (hs : ∀ᶠ n : ℕ in atTop, x + r ^ n • y ∈ s) : y ∈ tangentConeAt 𝕜 s x := by refine ⟨fun n ↦ (r ^ n)⁻¹, fun n ↦ r ^ n • y, hs, ?_, ?_⟩ · simp only [norm_inv, norm_pow, ← inv_pow] - exact tendsto_pow_atTop_atTop_of_one_lt <| one_lt_inv (norm_pos_iff.2 hr₀) hr + exact tendsto_pow_atTop_atTop_of_one_lt <| (one_lt_inv₀ (norm_pos_iff.2 hr₀)).2 hr · simp only [inv_smul_smul₀ (pow_ne_zero _ hr₀), tendsto_const_nhds] theorem tangentCone_univ : tangentConeAt 𝕜 univ x = univ := @@ -196,7 +196,7 @@ theorem mem_tangentCone_of_openSegment_subset {s : Set G} {x y : G} (h : openSeg rw [openSegment_eq_image] refine ⟨(1 / 2) ^ n, ⟨?_, ?_⟩, ?_⟩ · exact pow_pos one_half_pos _ - · exact pow_lt_one one_half_pos.le one_half_lt_one hn + · exact pow_lt_one₀ one_half_pos.le one_half_lt_one hn · simp only [sub_smul, one_smul, smul_sub]; abel /-- If a subset of a real vector space contains a segment, then the direction of this diff --git a/Mathlib/Analysis/Calculus/UniformLimitsDeriv.lean b/Mathlib/Analysis/Calculus/UniformLimitsDeriv.lean index da30835b1f395..434945a20c58c 100644 --- a/Mathlib/Analysis/Calculus/UniformLimitsDeriv.lean +++ b/Mathlib/Analysis/Calculus/UniformLimitsDeriv.lean @@ -286,7 +286,7 @@ theorem difference_quotients_converge_uniformly refine lt_of_le_of_lt ?_ hqε by_cases hyz' : x = y; · simp [hyz', hqpos.le] have hyz : 0 < ‖y - x‖ := by rw [norm_pos_iff]; intro hy'; exact hyz' (eq_of_sub_eq_zero hy').symm - rw [inv_mul_le_iff hyz, mul_comm, sub_sub_sub_comm] + rw [inv_mul_le_iff₀ hyz, mul_comm, sub_sub_sub_comm] simp only [Pi.zero_apply, dist_zero_left] at e refine Convex.norm_image_sub_le_of_norm_hasFDerivWithin_le @@ -356,8 +356,8 @@ theorem hasFDerivAt_of_tendstoUniformlyOnFilter [NeBot l] apply ((this ε hε).filter_mono curry_le_prod).mono intro n hn rw [dist_eq_norm] at hn ⊢ - rw [← smul_sub] at hn - rwa [sub_zero] + convert hn using 2 + module · -- (Almost) the definition of the derivatives rw [Metric.tendsto_nhds] intro ε hε @@ -385,7 +385,7 @@ theorem hasFDerivAt_of_tendstoUniformlyOnFilter [NeBot l] by_cases hx : x = n.2; · simp [hx] have hnx : 0 < ‖n.2 - x‖ := by rw [norm_pos_iff]; intro hx'; exact hx (eq_of_sub_eq_zero hx').symm - rw [inv_mul_le_iff hnx, mul_comm] + rw [inv_mul_le_iff₀ hnx, mul_comm] simp only [Function.comp_apply, Prod.map_apply'] rw [norm_sub_rev] exact (f' n.1 x - g' x).le_opNorm (n.2 - x) diff --git a/Mathlib/Analysis/Complex/AbelLimit.lean b/Mathlib/Analysis/Complex/AbelLimit.lean index d00d00856facc..167aa0434d806 100644 --- a/Mathlib/Analysis/Complex/AbelLimit.lean +++ b/Mathlib/Analysis/Complex/AbelLimit.lean @@ -206,9 +206,9 @@ theorem tendsto_tsum_powerSeries_nhdsWithin_stolzSet calc _ ≤ ‖1 - z‖ * ∑ i ∈ range B₁, ‖l - s (i + 1)‖ := by gcongr; nth_rw 3 [← mul_one ‖_‖] - gcongr; exact pow_le_one _ (norm_nonneg _) zn.le + gcongr; exact pow_le_one₀ (norm_nonneg _) zn.le _ ≤ ‖1 - z‖ * (F + 1) := by gcongr; linarith only - _ < _ := by rwa [norm_sub_rev, lt_div_iff (by positivity)] at zd + _ < _ := by rwa [norm_sub_rev, lt_div_iff₀ (by positivity)] at zd have S₂ : ‖1 - z‖ * ∑ i ∈ Ico B₁ (max B₁ B₂), ‖l - s (i + 1)‖ * ‖z‖ ^ i < ε / 4 := calc _ ≤ ‖1 - z‖ * ∑ i ∈ Ico B₁ (max B₁ B₂), ε / 4 / M * ‖z‖ ^ i := by diff --git a/Mathlib/Analysis/Complex/Basic.lean b/Mathlib/Analysis/Complex/Basic.lean index 28550b2fd6baa..b2b77580329f5 100644 --- a/Mathlib/Analysis/Complex/Basic.lean +++ b/Mathlib/Analysis/Complex/Basic.lean @@ -208,11 +208,14 @@ theorem antilipschitz_equivRealProd : AntilipschitzWith (NNReal.sqrt 2) equivRea AddMonoidHomClass.antilipschitz_of_bound equivRealProdLm fun z ↦ by simpa only [Real.coe_sqrt, NNReal.coe_ofNat] using abs_le_sqrt_two_mul_max z -theorem uniformEmbedding_equivRealProd : UniformEmbedding equivRealProd := - antilipschitz_equivRealProd.uniformEmbedding lipschitz_equivRealProd.uniformContinuous +theorem isUniformEmbedding_equivRealProd : IsUniformEmbedding equivRealProd := + antilipschitz_equivRealProd.isUniformEmbedding lipschitz_equivRealProd.uniformContinuous + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_equivRealProd := isUniformEmbedding_equivRealProd instance : CompleteSpace ℂ := - (completeSpace_congr uniformEmbedding_equivRealProd).mpr inferInstance + (completeSpace_congr isUniformEmbedding_equivRealProd).mpr inferInstance instance instT2Space : T2Space ℂ := TopologicalSpace.t2Space_of_metrizableSpace diff --git a/Mathlib/Analysis/Complex/CauchyIntegral.lean b/Mathlib/Analysis/Complex/CauchyIntegral.lean index acb07715c395f..ebc991f8801e8 100644 --- a/Mathlib/Analysis/Complex/CauchyIntegral.lean +++ b/Mathlib/Analysis/Complex/CauchyIntegral.lean @@ -568,14 +568,18 @@ protected theorem _root_.DifferentiableOn.analyticAt {s : Set ℂ} {f : ℂ → lift R to ℝ≥0 using hR0.le exact ((hd.mono hRs).hasFPowerSeriesOnBall hR0).analyticAt +theorem _root_.DifferentiableOn.analyticOnNhd {s : Set ℂ} {f : ℂ → E} (hd : DifferentiableOn ℂ f s) + (hs : IsOpen s) : AnalyticOnNhd ℂ f s := fun _z hz => hd.analyticAt (hs.mem_nhds hz) + theorem _root_.DifferentiableOn.analyticOn {s : Set ℂ} {f : ℂ → E} (hd : DifferentiableOn ℂ f s) - (hs : IsOpen s) : AnalyticOn ℂ f s := fun _z hz => hd.analyticAt (hs.mem_nhds hz) + (hs : IsOpen s) : AnalyticOn ℂ f s := + (hd.analyticOnNhd hs).analyticOn /-- 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} {n : ℕ} (hd : DifferentiableOn ℂ f s) (hs : IsOpen s) : ContDiffOn ℂ n f s := - (hd.analyticOn hs).contDiffOn + (hd.analyticOnNhd hs).contDiffOn /-- A complex differentiable function `f : ℂ → E` is analytic at every point. -/ protected theorem _root_.Differentiable.analyticAt {f : ℂ → E} (hf : Differentiable ℂ f) (z : ℂ) : @@ -594,16 +598,27 @@ protected theorem _root_.Differentiable.hasFPowerSeriesOnBall {f : ℂ → E} (h (h.differentiableOn.hasFPowerSeriesOnBall hR).r_eq_top_of_exists fun _r hr => ⟨_, h.differentiableOn.hasFPowerSeriesOnBall hr⟩ +/-- On an open set, `f : ℂ → E` is analytic iff it is differentiable -/ +theorem analyticOnNhd_iff_differentiableOn {f : ℂ → E} {s : Set ℂ} (o : IsOpen s) : + AnalyticOnNhd ℂ f s ↔ DifferentiableOn ℂ f s := + ⟨AnalyticOnNhd.differentiableOn, fun d _ zs ↦ d.analyticAt (o.mem_nhds zs)⟩ + /-- On an open set, `f : ℂ → E` is analytic iff it is differentiable -/ theorem analyticOn_iff_differentiableOn {f : ℂ → E} {s : Set ℂ} (o : IsOpen s) : - AnalyticOn ℂ f s ↔ DifferentiableOn ℂ f s := - ⟨AnalyticOn.differentiableOn, fun d _ zs ↦ d.analyticAt (o.mem_nhds zs)⟩ + AnalyticOn ℂ f s ↔ DifferentiableOn ℂ f s := by + rw [o.analyticOn_iff_analyticOnNhd] + exact analyticOnNhd_iff_differentiableOn o /-- `f : ℂ → E` is entire iff it's differentiable -/ +theorem analyticOnNhd_univ_iff_differentiable {f : ℂ → E} : + AnalyticOnNhd ℂ f univ ↔ Differentiable ℂ f := by + simp only [← differentiableOn_univ] + exact analyticOnNhd_iff_differentiableOn isOpen_univ + theorem analyticOn_univ_iff_differentiable {f : ℂ → E} : AnalyticOn ℂ f univ ↔ Differentiable ℂ f := by - simp only [← differentiableOn_univ] - exact analyticOn_iff_differentiableOn isOpen_univ + rw [analyticOn_univ] + exact analyticOnNhd_univ_iff_differentiable /-- `f : ℂ → E` is analytic at `z` iff it's differentiable near `z` -/ theorem analyticAt_iff_eventually_differentiableAt {f : ℂ → E} {c : ℂ} : @@ -614,8 +629,8 @@ theorem analyticAt_iff_eventually_differentiableAt {f : ℂ → E} {c : ℂ} : apply AnalyticAt.differentiableAt · intro d rcases _root_.eventually_nhds_iff.mp d with ⟨s, d, o, m⟩ - have h : AnalyticOn ℂ f s := by - refine DifferentiableOn.analyticOn ?_ o + have h : AnalyticOnNhd ℂ f s := by + refine DifferentiableOn.analyticOnNhd ?_ o intro z m exact (d z m).differentiableWithinAt exact h _ m diff --git a/Mathlib/Analysis/Complex/Circle.lean b/Mathlib/Analysis/Complex/Circle.lean index bda86fd651ad1..72e66ae46c1b7 100644 --- a/Mathlib/Analysis/Complex/Circle.lean +++ b/Mathlib/Analysis/Complex/Circle.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Heather Macbeth -/ import Mathlib.Analysis.SpecialFunctions.Exp -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Analysis.Normed.Field.UnitBall /-! diff --git a/Mathlib/Analysis/Complex/Hadamard.lean b/Mathlib/Analysis/Complex/Hadamard.lean index 88d6c801d518c..37d20a8d07540 100644 --- a/Mathlib/Analysis/Complex/Hadamard.lean +++ b/Mathlib/Analysis/Complex/Hadamard.lean @@ -189,14 +189,14 @@ lemma F_edge_le_one (f : ℂ → E) (ε : ℝ) (hε : ε > 0) (z : ℂ) rcases hz with hz0 | hz1 -- `z.re = 0` · simp only [hz0, zero_sub, Real.rpow_neg_one, neg_zero, Real.rpow_zero, mul_one, - inv_mul_le_iff (sSupNormIm_eps_pos f hε 0)] + inv_mul_le_iff₀ (sSupNormIm_eps_pos f hε 0)] rw [← hz0] apply le_of_lt (norm_lt_sSupNormIm_eps f ε hε _ _ hB) simp only [verticalClosedStrip, mem_preimage, zero_le_one, left_mem_Icc, hz0] -- `z.re = 1` · rw [mem_singleton_iff] at hz1 simp only [hz1, one_mul, Real.rpow_zero, sub_self, Real.rpow_neg_one, - inv_mul_le_iff (sSupNormIm_eps_pos f hε 1), mul_one] + inv_mul_le_iff₀ (sSupNormIm_eps_pos f hε 1), mul_one] rw [← hz1] apply le_of_lt (norm_lt_sSupNormIm_eps f ε hε _ _ hB) simp only [verticalClosedStrip, mem_preimage, zero_le_one, hz1, right_mem_Icc] @@ -304,7 +304,7 @@ lemma norm_le_interpStrip_of_mem_verticalClosedStrip_eps (ε : ℝ) (hε : ε > ‖f z‖ ≤ ‖((ε + sSupNormIm f 0) ^ (1-z) * (ε + sSupNormIm f 1) ^ z : ℂ)‖ := by simp only [F, abs_invInterpStrip _ _ hε, norm_smul, norm_mul, norm_eq_abs, ← ofReal_add, abs_cpow_eq_rpow_re_of_pos (sSupNormIm_eps_pos f hε _) _, sub_re, one_re] - rw [← mul_inv_le_iff, ← one_mul (((ε + sSupNormIm f 1) ^ z.re)), ← mul_inv_le_iff', + rw [← mul_inv_le_iff₀', ← one_mul (((ε + sSupNormIm f 1) ^ z.re)), ← mul_inv_le_iff₀, ← Real.rpow_neg_one, ← Real.rpow_neg_one] · simp only [← Real.rpow_mul (le_of_lt (sSupNormIm_eps_pos f hε _)), mul_neg, mul_one, neg_sub, mul_assoc] diff --git a/Mathlib/Analysis/Complex/OpenMapping.lean b/Mathlib/Analysis/Complex/OpenMapping.lean index 9ce4d01945319..c37d82d1058c9 100644 --- a/Mathlib/Analysis/Complex/OpenMapping.lean +++ b/Mathlib/Analysis/Complex/OpenMapping.lean @@ -27,7 +27,7 @@ That second step is implemented in `DiffContOnCl.ball_subset_image_closedBall`. * `AnalyticAt.eventually_constant_or_nhds_le_map_nhds` is the local version of the open mapping theorem around a point; -* `AnalyticOn.is_constant_or_isOpen` is the open mapping theorem on a connected open set. +* `AnalyticOnNhd.is_constant_or_isOpen` is the open mapping theorem on a connected open set. -/ @@ -51,7 +51,7 @@ theorem DiffContOnCl.ball_subset_image_closedBall (h : DiffContOnCl ℂ f (ball have h1 : DiffContOnCl ℂ (fun z => f z - v) (ball z₀ r) := h.sub_const v have h2 : ContinuousOn (fun z => ‖f z - v‖) (closedBall z₀ r) := continuous_norm.comp_continuousOn (closure_ball z₀ hr.ne.symm ▸ h1.continuousOn) - have h3 : AnalyticOn ℂ f (ball z₀ r) := h.differentiableOn.analyticOn isOpen_ball + have h3 : AnalyticOnNhd ℂ f (ball z₀ r) := h.differentiableOn.analyticOnNhd isOpen_ball have h4 : ∀ z ∈ sphere z₀ r, ε / 2 ≤ ‖f z - v‖ := fun z hz => by linarith [hf z hz, show ‖v - f z₀‖ < ε / 2 from mem_ball.mp hv, norm_sub_sub_norm_sub_le_norm_sub (f z) v (f z₀)] @@ -64,7 +64,7 @@ theorem DiffContOnCl.ball_subset_image_closedBall (h : DiffContOnCl ℂ f (ball have h7 : ∀ᶠ w in 𝓝 z, f w = f z := by filter_upwards [key] with h; field_simp replace h7 : ∃ᶠ w in 𝓝[≠] z, f w = f z := (h7.filter_mono nhdsWithin_le_nhds).frequently have h8 : IsPreconnected (ball z₀ r) := (convex_ball z₀ r).isPreconnected - have h9 := h3.eqOn_of_preconnected_of_frequently_eq analyticOn_const h8 hz1 h7 + have h9 := h3.eqOn_of_preconnected_of_frequently_eq analyticOnNhd_const h8 hz1 h7 have h10 : f z = f z₀ := (h9 (mem_ball_self hr)).symm exact not_eventually.mpr hz₀ (mem_of_superset (ball_mem_nhds z₀ hr) (h10 ▸ h9)) @@ -83,7 +83,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds_aux (hf : AnalyticAt have h1 := (hf.eventually_eq_or_eventually_ne analyticAt_const).resolve_left h have h2 : ∀ᶠ z in 𝓝 z₀, AnalyticAt ℂ f z := (isOpen_analyticAt ℂ f).eventually_mem hf obtain ⟨ρ, hρ, h3, h4⟩ : - ∃ ρ > 0, AnalyticOn ℂ f (closedBall z₀ ρ) ∧ ∀ z ∈ closedBall z₀ ρ, z ≠ z₀ → f z ≠ f z₀ := by + ∃ ρ > 0, AnalyticOnNhd ℂ f (closedBall z₀ ρ) ∧ ∀ z ∈ closedBall z₀ ρ, z ≠ z₀ → f z ≠ f z₀ := by simpa only [setOf_and, subset_inter_iff] using nhds_basis_closedBall.mem_iff.mp (h2.and (eventually_nhdsWithin_iff.mp h1)) replace h3 : DiffContOnCl ℂ f (ball z₀ ρ) := @@ -118,7 +118,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal let ray : E → ℂ → E := fun z t => z₀ + t • z let gray : E → ℂ → ℂ := fun z => g ∘ ray z obtain ⟨r, hr, hgr⟩ := isOpen_iff.mp (isOpen_analyticAt ℂ g) z₀ hg - have h1 : ∀ z ∈ sphere (0 : E) 1, AnalyticOn ℂ (gray z) (ball 0 r) := by + have h1 : ∀ z ∈ sphere (0 : E) 1, AnalyticOnNhd ℂ (gray z) (ball 0 r) := by refine fun z hz t ht => AnalyticAt.comp ?_ ?_ · exact hgr (by simpa [ray, norm_smul, mem_sphere_zero_iff_norm.mp hz] using ht) · exact analyticAt_const.add @@ -134,7 +134,7 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal have e1 : IsPreconnected (ball (0 : ℂ) r) := (convex_ball 0 r).isPreconnected have e2 : w ∈ sphere (0 : E) 1 := by simp [w, norm_smul, inv_mul_cancel₀ h'] specialize h1 w e2 - apply h1.eqOn_of_preconnected_of_eventuallyEq analyticOn_const e1 (mem_ball_self hr) + apply h1.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const e1 (mem_ball_self hr) simpa [ray, gray] using h w e2 have h4 : ‖z - z₀‖ < r := by simpa [dist_eq_norm] using mem_ball.mp hz replace h4 : ↑‖z - z₀‖ ∈ ball (0 : ℂ) r := by @@ -156,13 +156,16 @@ theorem AnalyticAt.eventually_constant_or_nhds_le_map_nhds {z₀ : E} (hg : Anal /-- The *open mapping theorem* for holomorphic functions, global version: if a function `g : E → ℂ` is analytic on a connected set `U`, then either it is constant on `U`, or it is open on `U` (in the sense that it maps any open set contained in `U` to an open set in `ℂ`). -/ -theorem AnalyticOn.is_constant_or_isOpen (hg : AnalyticOn ℂ g U) (hU : IsPreconnected U) : +theorem AnalyticOnNhd.is_constant_or_isOpen (hg : AnalyticOnNhd ℂ g U) (hU : IsPreconnected U) : (∃ w, ∀ z ∈ U, g z = w) ∨ ∀ s ⊆ U, IsOpen s → IsOpen (g '' s) := by by_cases h : ∃ z₀ ∈ U, ∀ᶠ z in 𝓝 z₀, g z = g z₀ · obtain ⟨z₀, hz₀, h⟩ := h - exact Or.inl ⟨g z₀, hg.eqOn_of_preconnected_of_eventuallyEq analyticOn_const hU hz₀ h⟩ + exact Or.inl ⟨g z₀, hg.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const hU hz₀ h⟩ · push_neg at h refine Or.inr fun s hs1 hs2 => isOpen_iff_mem_nhds.mpr ?_ rintro z ⟨w, hw1, rfl⟩ exact (hg w (hs1 hw1)).eventually_constant_or_nhds_le_map_nhds.resolve_left (h w (hs1 hw1)) (image_mem_map (hs2.mem_nhds hw1)) + +@[deprecated (since := "2024-09-26")] +alias AnalyticOn.is_constant_or_isOpen := AnalyticOnNhd.is_constant_or_isOpen diff --git a/Mathlib/Analysis/Complex/PhragmenLindelof.lean b/Mathlib/Analysis/Complex/PhragmenLindelof.lean index e172dd9cfe031..a457d182cf842 100644 --- a/Mathlib/Analysis/Complex/PhragmenLindelof.lean +++ b/Mathlib/Analysis/Complex/PhragmenLindelof.lean @@ -133,7 +133,7 @@ theorem horizontal_strip (hfd : DiffContOnCl ℂ f (im ⁻¹' Ioo a b)) rcases hB with ⟨c, hc, B, hO⟩ obtain ⟨d, ⟨hcd, hd₀⟩, hd⟩ : ∃ d, (c < d ∧ 0 < d) ∧ d < π / 2 / b := by simpa only [max_lt_iff] using exists_between (max_lt hc hπb) - have hb' : d * b < π / 2 := (lt_div_iff hb).1 hd + have hb' : d * b < π / 2 := (lt_div_iff₀ hb).1 hd set aff := (fun w => d * (w - a * I) : ℂ → ℂ) set g := fun (ε : ℝ) (w : ℂ) => exp (ε * (exp (aff w) + exp (-aff w))) /- Since `g ε z → 1` as `ε → 0⁻`, it suffices to prove that `‖g ε z • f z‖ ≤ C` diff --git a/Mathlib/Analysis/Complex/RemovableSingularity.lean b/Mathlib/Analysis/Complex/RemovableSingularity.lean index 9702422a17c49..b6d73c9132378 100644 --- a/Mathlib/Analysis/Complex/RemovableSingularity.lean +++ b/Mathlib/Analysis/Complex/RemovableSingularity.lean @@ -48,7 +48,7 @@ theorem differentiableOn_compl_singleton_and_continuousAt_iff {f : ℂ → E} {s rcases eq_or_ne x c with (rfl | hne) · refine (analyticAt_of_differentiable_on_punctured_nhds_of_continuousAt ?_ hc).differentiableAt.differentiableWithinAt - refine eventually_nhdsWithin_iff.2 ((eventually_mem_nhds.2 hs).mono fun z hz hzx => ?_) + refine eventually_nhdsWithin_iff.2 ((eventually_mem_nhds_iff.2 hs).mono fun z hz hzx => ?_) exact hd.differentiableAt (inter_mem hz (isOpen_ne.mem_nhds hzx)) · simpa only [DifferentiableWithinAt, HasFDerivWithinAt, hne.nhdsWithin_diff_singleton] using hd x ⟨hx, hne⟩ diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean index f3d8eacb2243d..2bc3767cffe15 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Manifold.lean @@ -4,6 +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.ContMDiff.Atlas import Mathlib.Geometry.Manifold.MFDeriv.Basic /-! diff --git a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean index f4c7f5c6d05f3..256120e306349 100644 --- a/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean +++ b/Mathlib/Analysis/Complex/UpperHalfPlane/Metric.lean @@ -261,7 +261,7 @@ instance : MetricSpace ℍ := have h₀ : 0 < R / im z + 1 := one_pos.trans h₁ refine ⟨log (R / im z + 1), Real.log_pos h₁, ?_⟩ refine fun w hw => (dist_coe_le w z).trans_lt ?_ - rwa [← lt_div_iff' z.im_pos, sub_lt_iff_lt_add, ← Real.lt_log_iff_exp_lt h₀] + rwa [← lt_div_iff₀' z.im_pos, sub_lt_iff_lt_add, ← Real.lt_log_iff_exp_lt h₀] theorem im_pos_of_dist_center_le {z : ℍ} {r : ℝ} {w : ℂ} (h : dist w (center z r) ≤ z.im * Real.sinh r) : 0 < w.im := diff --git a/Mathlib/Analysis/Convex/Basic.lean b/Mathlib/Analysis/Convex/Basic.lean index f07e88d57f245..3c3fc373308f3 100644 --- a/Mathlib/Analysis/Convex/Basic.lean +++ b/Mathlib/Analysis/Convex/Basic.lean @@ -8,6 +8,8 @@ import Mathlib.Algebra.Order.Module.OrderedSMul import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Analysis.Convex.Star import Mathlib.LinearAlgebra.AffineSpace.AffineSubspace +import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.NoncommRing /-! # Convex sets and functions in vector spaces @@ -158,8 +160,7 @@ theorem convex_segment (x y : E) : Convex 𝕜 [x -[𝕜] y] := by ⟨a * ap + b * aq, a * bp + b * bq, add_nonneg (mul_nonneg ha hap) (mul_nonneg hb haq), add_nonneg (mul_nonneg ha hbp) (mul_nonneg hb hbq), ?_, ?_⟩ · rw [add_add_add_comm, ← mul_add, ← mul_add, habp, habq, mul_one, mul_one, hab] - · simp_rw [add_smul, mul_smul, smul_add] - exact add_add_add_comm _ _ _ _ + · match_scalars <;> noncomm_ring theorem Convex.linear_image (hs : Convex 𝕜 s) (f : E →ₗ[𝕜] F) : Convex 𝕜 (f '' s) := by rintro _ ⟨x, hx, rfl⟩ _ ⟨y, hy, rfl⟩ a b ha hb hab @@ -406,8 +407,8 @@ theorem convex_openSegment (a b : E) : Convex 𝕜 (openSegment 𝕜 a b) := by rw [convex_iff_openSegment_subset] rintro p ⟨ap, bp, hap, hbp, habp, rfl⟩ q ⟨aq, bq, haq, hbq, habq, rfl⟩ z ⟨a, b, ha, hb, hab, rfl⟩ refine ⟨a * ap + b * aq, a * bp + b * bq, by positivity, by positivity, ?_, ?_⟩ - · rw [add_add_add_comm, ← mul_add, ← mul_add, habp, habq, mul_one, mul_one, hab] - · simp_rw [add_smul, mul_smul, smul_add, add_add_add_comm] + · linear_combination (norm := noncomm_ring) a * habp + b * habq + hab + · module end StrictOrderedCommSemiring @@ -425,8 +426,7 @@ theorem convex_vadd (a : E) : Convex 𝕜 (a +ᵥ s) ↔ Convex 𝕜 s := theorem Convex.add_smul_mem (hs : Convex 𝕜 s) {x y : E} (hx : x ∈ s) (hy : x + y ∈ s) {t : 𝕜} (ht : t ∈ Icc (0 : 𝕜) 1) : x + t • y ∈ s := by - have h : x + t • y = (1 - t) • x + t • (x + y) := by - rw [smul_add, ← add_assoc, ← add_smul, sub_add_cancel, one_smul] + have h : x + t • y = (1 - t) • x + t • (x + y) := by match_scalars <;> noncomm_ring rw [h] exact hs hx hy (sub_nonneg_of_le ht.2) ht.1 (sub_add_cancel _ _) @@ -505,7 +505,8 @@ theorem convex_iff_div : theorem Convex.mem_smul_of_zero_mem (h : Convex 𝕜 s) {x : E} (zero_mem : (0 : E) ∈ s) (hx : x ∈ s) {t : 𝕜} (ht : 1 ≤ t) : x ∈ t • s := by rw [mem_smul_set_iff_inv_smul_mem₀ (zero_lt_one.trans_le ht).ne'] - exact h.smul_mem_of_zero_mem zero_mem hx ⟨inv_nonneg.2 (zero_le_one.trans ht), inv_le_one ht⟩ + exact h.smul_mem_of_zero_mem zero_mem hx + ⟨inv_nonneg.2 (zero_le_one.trans ht), inv_le_one_of_one_le₀ ht⟩ theorem Convex.exists_mem_add_smul_eq (h : Convex 𝕜 s) {x y : E} {p q : 𝕜} (hx : x ∈ s) (hy : y ∈ s) (hp : 0 ≤ p) (hq : 0 ≤ q) : ∃ z ∈ s, (p + q) • z = p • x + q • y := by @@ -515,7 +516,7 @@ theorem Convex.exists_mem_add_smul_eq (h : Convex 𝕜 s) {x y : E} {p q : 𝕜} · replace hpq : 0 < p + q := (add_nonneg hp hq).lt_of_ne' (mt (add_eq_zero_iff_of_nonneg hp hq).1 hpq) refine ⟨_, convex_iff_div.1 h hx hy hp hq hpq, ?_⟩ - simp only [smul_add, smul_smul, mul_div_cancel₀ _ hpq.ne'] + match_scalars <;> field_simp theorem Convex.add_smul (h_conv : Convex 𝕜 s) {p q : 𝕜} (hp : 0 ≤ p) (hq : 0 ≤ q) : (p + q) • s = p • s + q • s := (add_smul_subset _ _ _).antisymm <| by @@ -604,7 +605,8 @@ theorem convex_stdSimplex : Convex 𝕜 (stdSimplex 𝕜 ι) := by lemma stdSimplex_of_isEmpty_index [IsEmpty ι] [Nontrivial 𝕜] : stdSimplex 𝕜 ι = ∅ := eq_empty_of_forall_not_mem <| by rintro f ⟨-, hf⟩; simp at hf -lemma stdSimplex_unique [Unique ι] : stdSimplex 𝕜 ι = {fun _ ↦ 1} := by +lemma stdSimplex_unique [Nonempty ι] [Subsingleton ι] : stdSimplex 𝕜 ι = {fun _ ↦ 1} := by + cases nonempty_unique ι refine eq_singleton_iff_unique_mem.2 ⟨⟨fun _ ↦ zero_le_one, Fintype.sum_unique _⟩, ?_⟩ rintro f ⟨-, hf⟩ rw [Fintype.sum_unique] at hf diff --git a/Mathlib/Analysis/Convex/Between.lean b/Mathlib/Analysis/Convex/Between.lean index ccbae3b13d6c8..d1be44a83c178 100644 --- a/Mathlib/Analysis/Convex/Between.lean +++ b/Mathlib/Analysis/Convex/Between.lean @@ -5,6 +5,7 @@ Authors: Joseph Myers -/ import Mathlib.Algebra.CharP.Invertible import Mathlib.Algebra.Order.Interval.Set.Group +import Mathlib.Analysis.Convex.Basic import Mathlib.Analysis.Convex.Segment import Mathlib.LinearAlgebra.AffineSpace.FiniteDimensional import Mathlib.Tactic.FieldSimp @@ -128,6 +129,14 @@ variable {R} lemma mem_segment_iff_wbtw {x y z : V} : y ∈ segment R x z ↔ Wbtw R x y z := by rw [Wbtw, affineSegment_eq_segment] +alias ⟨_, Wbtw.mem_segment⟩ := mem_segment_iff_wbtw + +lemma Convex.mem_of_wbtw {p₀ p₁ p₂ : V} {s : Set V} (hs : Convex R s) (h₀₁₂ : Wbtw R p₀ p₁ p₂) + (h₀ : p₀ ∈ s) (h₂ : p₂ ∈ s) : p₁ ∈ s := hs.segment_subset h₀ h₂ h₀₁₂.mem_segment + +lemma AffineSubspace.mem_of_wbtw {s : AffineSubspace R P} {x y z : P} (hxyz : Wbtw R x y z) + (hx : x ∈ s) (hz : z ∈ s) : y ∈ s := by obtain ⟨ε, -, rfl⟩ := hxyz; exact lineMap_mem _ hx hz + theorem Wbtw.map {x y z : P} (h : Wbtw R x y z) (f : P →ᵃ[R] P') : Wbtw R (f x) (f y) (f z) := by rw [Wbtw, ← affineSegment_image] exact Set.mem_image_of_mem _ h @@ -392,7 +401,7 @@ theorem sbtw_one_zero_iff {x : R} : Sbtw R 1 x 0 ↔ x ∈ Set.Ioo (0 : R) 1 := theorem Wbtw.trans_left {w x y z : P} (h₁ : Wbtw R w y z) (h₂ : Wbtw R w x y) : Wbtw R w x z := by rcases h₁ with ⟨t₁, ht₁, rfl⟩ rcases h₂ with ⟨t₂, ht₂, rfl⟩ - refine ⟨t₂ * t₁, ⟨mul_nonneg ht₂.1 ht₁.1, mul_le_one ht₂.2 ht₁.1 ht₁.2⟩, ?_⟩ + refine ⟨t₂ * t₁, ⟨mul_nonneg ht₂.1 ht₁.1, mul_le_one₀ ht₂.2 ht₁.1 ht₁.2⟩, ?_⟩ rw [lineMap_apply, lineMap_apply, lineMap_vsub_left, smul_smul] theorem Wbtw.trans_right {w x y z : P} (h₁ : Wbtw R w x z) (h₂ : Wbtw R x y z) : Wbtw R w y z := by @@ -574,7 +583,7 @@ end LinearOrderedRing section LinearOrderedField -variable [LinearOrderedField R] [AddCommGroup V] [Module R V] [AddTorsor V P] +variable [LinearOrderedField R] [AddCommGroup V] [Module R V] [AddTorsor V P] {x y z : P} variable {R} theorem wbtw_iff_left_eq_or_right_mem_image_Ici {x y z : P} : @@ -583,14 +592,14 @@ theorem wbtw_iff_left_eq_or_right_mem_image_Ici {x y z : P} : · rcases h with ⟨r, ⟨hr0, hr1⟩, rfl⟩ rcases hr0.lt_or_eq with (hr0' | rfl) · rw [Set.mem_image] - refine Or.inr ⟨r⁻¹, one_le_inv hr0' hr1, ?_⟩ + refine .inr ⟨r⁻¹, (one_le_inv₀ hr0').2 hr1, ?_⟩ simp only [lineMap_apply, smul_smul, vadd_vsub] rw [inv_mul_cancel₀ hr0'.ne', one_smul, vsub_vadd] · simp · rcases h with (rfl | ⟨r, ⟨hr, rfl⟩⟩) · exact wbtw_self_left _ _ _ · rw [Set.mem_Ici] at hr - refine ⟨r⁻¹, ⟨inv_nonneg.2 (zero_le_one.trans hr), inv_le_one hr⟩, ?_⟩ + refine ⟨r⁻¹, ⟨inv_nonneg.2 (zero_le_one.trans hr), inv_le_one_of_one_le₀ hr⟩, ?_⟩ simp only [lineMap_apply, smul_smul, vadd_vsub] rw [inv_mul_cancel₀ (one_pos.trans_le hr).ne', one_smul, vsub_vadd] @@ -653,9 +662,15 @@ theorem Sbtw.left_mem_image_Ioi {x y z : P} (h : Sbtw R x y z) : theorem Sbtw.left_mem_affineSpan {x y z : P} (h : Sbtw R x y z) : x ∈ line[R, z, y] := h.symm.right_mem_affineSpan +lemma AffineSubspace.right_mem_of_wbtw {s : AffineSubspace R P} (hxyz : Wbtw R x y z) (hx : x ∈ s) + (hy : y ∈ s) (hxy : x ≠ y) : z ∈ s := by + obtain ⟨ε, -, rfl⟩ := hxyz + have hε : ε ≠ 0 := by rintro rfl; simp at hxy + simpa [hε] using lineMap_mem ε⁻¹ hx hy + theorem wbtw_smul_vadd_smul_vadd_of_nonneg_of_le (x : P) (v : V) {r₁ r₂ : R} (hr₁ : 0 ≤ r₁) (hr₂ : r₁ ≤ r₂) : Wbtw R x (r₁ • v +ᵥ x) (r₂ • v +ᵥ x) := by - refine ⟨r₁ / r₂, ⟨div_nonneg hr₁ (hr₁.trans hr₂), div_le_one_of_le hr₂ (hr₁.trans hr₂)⟩, ?_⟩ + refine ⟨r₁ / r₂, ⟨div_nonneg hr₁ (hr₁.trans hr₂), div_le_one_of_le₀ hr₂ (hr₁.trans hr₂)⟩, ?_⟩ by_cases h : r₁ = 0; · simp [h] simp [lineMap_apply, smul_smul, ((hr₁.lt_of_ne' h).trans_le hr₂).ne.symm] @@ -695,8 +710,8 @@ theorem Wbtw.trans_left_right {w x y z : P} (h₁ : Wbtw R w y z) (h₂ : Wbtw R refine ⟨(t₁ - t₂ * t₁) / (1 - t₂ * t₁), ⟨div_nonneg (sub_nonneg.2 (mul_le_of_le_one_left ht₁.1 ht₂.2)) - (sub_nonneg.2 (mul_le_one ht₂.2 ht₁.1 ht₁.2)), - div_le_one_of_le (sub_le_sub_right ht₁.2 _) (sub_nonneg.2 (mul_le_one ht₂.2 ht₁.1 ht₁.2))⟩, + (sub_nonneg.2 (mul_le_one₀ ht₂.2 ht₁.1 ht₁.2)), div_le_one_of_le₀ + (sub_le_sub_right ht₁.2 _) (sub_nonneg.2 (mul_le_one₀ ht₂.2 ht₁.1 ht₁.2))⟩, ?_⟩ simp only [lineMap_apply, smul_smul, ← add_vadd, vsub_vadd_eq_vsub_sub, smul_sub, ← sub_smul, ← add_smul, vadd_vsub, vadd_right_cancel_iff, div_mul_eq_mul_div, div_sub_div_same] @@ -772,7 +787,7 @@ theorem wbtw_iff_sameRay_vsub {x y z : P} : Wbtw R x y z ↔ SameRay R (y -ᵥ x · refine ⟨r₂ / (r₁ + r₂), ⟨div_nonneg hr₂.le (add_nonneg hr₁.le hr₂.le), - div_le_one_of_le (le_add_of_nonneg_left hr₁.le) (add_nonneg hr₁.le hr₂.le)⟩, + div_le_one_of_le₀ (le_add_of_nonneg_left hr₁.le) (add_nonneg hr₁.le hr₂.le)⟩, ?_⟩ have h' : z = r₂⁻¹ • r₁ • (y -ᵥ x) +ᵥ y := by simp [h, hr₂.ne'] rw [eq_comm] diff --git a/Mathlib/Analysis/Convex/Birkhoff.lean b/Mathlib/Analysis/Convex/Birkhoff.lean new file mode 100644 index 0000000000000..a754f5db135c9 --- /dev/null +++ b/Mathlib/Analysis/Convex/Birkhoff.lean @@ -0,0 +1,172 @@ +/- +Copyright (c) 2024 Bhavik Mehta. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bhavik Mehta +-/ + +import Mathlib.Analysis.Convex.Combination +import Mathlib.Combinatorics.Hall.Basic +import Mathlib.Data.Matrix.DoublyStochastic +import Mathlib.Tactic.Linarith + +/-! +# Birkhoff's theorem + +## Main statements + +* `doublyStochastic_eq_sum_perm`: If `M` is a doubly stochastic matrix, then it is a convex + combination of permutation matrices. +* `doublyStochastic_eq_convexHull_perm`: The set of doubly stochastic matrices is the convex hull + of the permutation matrices. + +## TODO + +* Show that the extreme points of doubly stochastic matrices are the permutation matrices. +* Show that for `x y : n → R`, `x` is majorized by `y` if and only if there is a doubly stochastic + matrix `M` such that `M *ᵥ y = x`. + +## Tags + +Doubly stochastic, Birkhoff's theorem, Birkhoff-von Neumann theorem +-/ + +open Finset Function Matrix + +variable {R n : Type*} [Fintype n] [DecidableEq n] + +section LinearOrderedSemifield + +variable [LinearOrderedSemifield R] {M : Matrix n n R} + +/-- +If M is a positive scalar multiple of a doubly stochastic matrix, then there is a permutation matrix +whose support is contained in the support of M. +-/ +private lemma exists_perm_eq_zero_implies_eq_zero [Nonempty n] {s : R} (hs : 0 < s) + (hM : ∃ M' ∈ doublyStochastic R n, M = s • M') : + ∃ σ : Equiv.Perm n, ∀ i j, M i j = 0 → σ.permMatrix R i j = 0 := by + rw [exists_mem_doublyStochastic_eq_smul_iff hs.le] at hM + let f (i : n) : Finset n := univ.filter (M i · ≠ 0) + have hf (A : Finset n) : A.card ≤ (A.biUnion f).card := by + have (i) : ∑ j ∈ f i, M i j = s := by simp [sum_subset (filter_subset _ _), hM.2.1] + have h₁ : ∑ i ∈ A, ∑ j ∈ f i, M i j = A.card * s := by simp [this] + have h₂ : ∑ i, ∑ j ∈ A.biUnion f, M i j = (A.biUnion f).card * s := by + simp [sum_comm (t := A.biUnion f), hM.2.2, mul_comm s] + suffices A.card * s ≤ (A.biUnion f).card * s by exact_mod_cast le_of_mul_le_mul_right this hs + rw [← h₁, ← h₂] + trans ∑ i ∈ A, ∑ j ∈ A.biUnion f, M i j + · refine sum_le_sum fun i hi => ?_ + exact sum_le_sum_of_subset_of_nonneg (subset_biUnion_of_mem f hi) (by simp [*]) + · exact sum_le_sum_of_subset_of_nonneg (by simp) fun _ _ _ => sum_nonneg fun j _ => hM.1 _ _ + obtain ⟨g, hg, hg'⟩ := (all_card_le_biUnion_card_iff_exists_injective f).1 hf + rw [Finite.injective_iff_bijective] at hg + refine ⟨Equiv.ofBijective g hg, fun i j hij => ?_⟩ + simp only [PEquiv.toMatrix_apply, Option.mem_def, ite_eq_right_iff, one_ne_zero, imp_false, + Equiv.toPEquiv_apply, Equiv.ofBijective_apply, Option.some.injEq] + rintro rfl + simpa [f, hij] using hg' i + +end LinearOrderedSemifield + +section LinearOrderedField + +variable [LinearOrderedField R] {M : Matrix n n R} + +/-- +If M is a scalar multiple of a doubly stochastic matrix, then it is a conical combination of +permutation matrices. This is most useful when M is a doubly stochastic matrix, in which case +the combination is convex. + +This particular formulation is chosen to make the inductive step easier: we no longer need to +rescale each time a permutation matrix is subtracted. +-/ +private lemma doublyStochastic_sum_perm_aux (M : Matrix n n R) + (s : R) (hs : 0 ≤ s) + (hM : ∃ M' ∈ doublyStochastic R n, M = s • M') : + ∃ w : Equiv.Perm n → R, (∀ σ, 0 ≤ w σ) ∧ ∑ σ, w σ • σ.permMatrix R = M := by + rcases isEmpty_or_nonempty n + case inl => exact ⟨1, by simp, Subsingleton.elim _ _⟩ + set d : ℕ := (Finset.univ.filter fun i : n × n => M i.1 i.2 ≠ 0).card with ← hd + clear_value d + induction d using Nat.strongRecOn generalizing M s + case ind d ih => + rcases eq_or_lt_of_le hs with rfl | hs' + case inl => + use 0 + simp only [zero_smul, exists_and_right] at hM + simp [hM] + obtain ⟨σ, hσ⟩ := exists_perm_eq_zero_implies_eq_zero hs' hM + obtain ⟨i, hi, hi'⟩ := exists_min_image _ (fun i => M i (σ i)) univ_nonempty + rw [exists_mem_doublyStochastic_eq_smul_iff hs] at hM + let N : Matrix n n R := M - M i (σ i) • σ.permMatrix R + have hMi' : 0 < M i (σ i) := (hM.1 _ _).lt_of_ne' fun h => by + simpa [Equiv.toPEquiv_apply] using hσ _ _ h + let s' : R := s - M i (σ i) + have hs' : 0 ≤ s' := by + simp only [s', sub_nonneg, ← hM.2.1 i] + exact single_le_sum (fun j _ => hM.1 i j) (by simp) + have : ∃ M' ∈ doublyStochastic R n, N = s' • M' := by + rw [exists_mem_doublyStochastic_eq_smul_iff hs'] + simp only [sub_apply, smul_apply, PEquiv.toMatrix_apply, Equiv.toPEquiv_apply, Option.mem_def, + Option.some.injEq, smul_eq_mul, mul_ite, mul_one, mul_zero, sub_nonneg, + sum_sub_distrib, sum_ite_eq, mem_univ, ↓reduceIte, N] + refine ⟨fun i' j => ?_, by simp [hM.2.1], by simp [← σ.eq_symm_apply, hM]⟩ + split + case isTrue h => exact (hi' i' (by simp)).trans_eq (by rw [h]) + case isFalse h => exact hM.1 _ _ + have hd' : (univ.filter fun i : n × n => N i.1 i.2 ≠ 0).card < d := by + rw [← hd] + refine card_lt_card ?_ + rw [ssubset_iff_of_subset (monotone_filter_right _ _)] + · simp only [ne_eq, mem_filter, mem_univ, true_and, Decidable.not_not, Prod.exists] + refine ⟨i, σ i, hMi'.ne', ?_⟩ + simp [N, Equiv.toPEquiv_apply] + · rintro ⟨i', j'⟩ hN' hM' + dsimp at hN' hM' + simp only [sub_apply, hM', smul_apply, PEquiv.toMatrix_apply, Equiv.toPEquiv_apply, + Option.mem_def, Option.some.injEq, smul_eq_mul, mul_ite, mul_one, mul_zero, zero_sub, + neg_eq_zero, ite_eq_right_iff, Classical.not_imp, N] at hN' + obtain ⟨rfl, _⟩ := hN' + linarith [hi' i' (by simp)] + obtain ⟨w, hw, hw'⟩ := ih _ hd' _ s' hs' this rfl + refine ⟨w + fun σ' => if σ' = σ then M i (σ i) else 0, ?_⟩ + simp only [Pi.add_apply, add_smul, sum_add_distrib, hw', ite_smul, zero_smul, + sum_ite_eq', mem_univ, ↓reduceIte, N, sub_add_cancel, and_true] + intro σ' + split <;> simp [add_nonneg, hw, hM.1] + +/-- +If M is a doubly stochastic matrix, then it is an convex combination of permutation matrices. Note +`doublyStochastic_eq_convexHull_permMatrix` shows `doublyStochastic n` is exactly the convex hull of +the permutation matrices, and this lemma is instead most useful for accessing the coefficients of +each permutation matrices directly. +-/ +lemma exists_eq_sum_perm_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) : + ∃ w : Equiv.Perm n → R, (∀ σ, 0 ≤ w σ) ∧ ∑ σ, w σ = 1 ∧ ∑ σ, w σ • σ.permMatrix R = M := by + rcases isEmpty_or_nonempty n + case inl => exact ⟨fun _ => 1, by simp, by simp, Subsingleton.elim _ _⟩ + obtain ⟨w, hw1, hw3⟩ := doublyStochastic_sum_perm_aux M 1 (by simp) ⟨M, hM, by simp⟩ + refine ⟨w, hw1, ?_, hw3⟩ + inhabit n + have : ∑ j, ∑ σ : Equiv.Perm n, w σ • σ.permMatrix R default j = 1 := by + simp only [← smul_apply (m := n), ← Finset.sum_apply, hw3] + rw [sum_row_of_mem_doublyStochastic hM] + simpa [sum_comm (γ := n), Equiv.toPEquiv_apply] using this + +/-- +**Birkhoff's theorem** +The set of doubly stochastic matrices is the convex hull of the permutation matrices. Note +`exists_eq_sum_perm_of_mem_doublyStochastic` gives a convex weighting of each permutation matrix +directly. To show `doublyStochastic n` is convex, use `convex_doublyStochastic`. +-/ +theorem doublyStochastic_eq_convexHull_permMatrix : + doublyStochastic R n = convexHull R {σ.permMatrix R | σ : Equiv.Perm n} := by + refine (convexHull_min ?g1 convex_doublyStochastic).antisymm' fun M hM => ?g2 + case g1 => + rintro x ⟨h, rfl⟩ + exact permMatrix_mem_doublyStochastic + case g2 => + obtain ⟨w, hw1, hw2, hw3⟩ := exists_eq_sum_perm_of_mem_doublyStochastic hM + exact mem_convexHull_of_exists_fintype w (·.permMatrix R) hw1 hw2 (by simp) hw3 + +end LinearOrderedField diff --git a/Mathlib/Analysis/Convex/Body.lean b/Mathlib/Analysis/Convex/Body.lean index ab8c493ff10c3..219c7807cb05d 100644 --- a/Mathlib/Analysis/Convex/Body.lean +++ b/Mathlib/Analysis/Convex/Body.lean @@ -212,7 +212,7 @@ theorem iInter_smul_eq_self [T2Space V] {u : ℕ → ℝ≥0} (K : ConvexBody V) rw [show (1 + u n : ℝ) • y - y = (u n : ℝ) • y by rw [add_smul, one_smul, add_sub_cancel_left], norm_smul, Real.norm_eq_abs] specialize hn n le_rfl - rw [_root_.lt_div_iff' hC_pos, mul_comm, NNReal.coe_zero, sub_zero, Real.norm_eq_abs] at hn + rw [lt_div_iff₀' hC_pos, mul_comm, NNReal.coe_zero, sub_zero, Real.norm_eq_abs] at hn refine lt_of_le_of_lt ?_ hn exact mul_le_mul_of_nonneg_left (hC_bdd _ hyK) (abs_nonneg _) · refine Set.mem_iInter.mpr (fun n => Convex.mem_smul_of_zero_mem K.convex h_zero h ?_) diff --git a/Mathlib/Analysis/Convex/Caratheodory.lean b/Mathlib/Analysis/Convex/Caratheodory.lean index 5d81223dc517b..6bae295f47f1a 100644 --- a/Mathlib/Analysis/Convex/Caratheodory.lean +++ b/Mathlib/Analysis/Convex/Caratheodory.lean @@ -133,7 +133,7 @@ theorem affineIndependent_minCardFinsetOfMemConvexHull : (minCardFinsetOfMemConvexHull_subseteq hx)) hp rw [← not_lt] at contra apply contra - erw [card_erase_of_mem p.2, hk] + rw [card_erase_of_mem p.2, hk] exact lt_add_one _ end Caratheodory @@ -172,7 +172,7 @@ theorem eq_pos_convex_span_of_mem_convexHull {x : E} (hx : x ∈ convexHull 𝕜 (hw₁ _ (Finset.mem_filter.mp i.2).1).lt_of_ne (Finset.mem_filter.mp i.property).2.symm · erw [Finset.sum_attach, Finset.sum_filter_ne_zero, hw₂] · change (∑ i ∈ t'.attach, (fun e => w e • e) ↑i) = x - erw [Finset.sum_attach (f := fun e => w e • e), Finset.sum_filter_of_ne] + rw [Finset.sum_attach (f := fun e => w e • e), Finset.sum_filter_of_ne] · rw [t.centerMass_eq_of_sum_1 id hw₂] at hw₃ exact hw₃ · intro e _ hwe contra diff --git a/Mathlib/Analysis/Convex/Combination.lean b/Mathlib/Analysis/Convex/Combination.lean index 1fc98bcd1e819..399464ada7406 100644 --- a/Mathlib/Analysis/Convex/Combination.lean +++ b/Mathlib/Analysis/Convex/Combination.lean @@ -50,7 +50,8 @@ theorem Finset.centerMass_empty : (∅ : Finset ι).centerMass w z = 0 := by theorem Finset.centerMass_pair (hne : i ≠ j) : ({i, j} : Finset ι).centerMass w z = (w i / (w i + w j)) • z i + (w j / (w i + w j)) • z j := by - simp only [centerMass, sum_pair hne, smul_add, (mul_smul _ _ _).symm, div_eq_inv_mul] + simp only [centerMass, sum_pair hne] + module variable {w} @@ -63,7 +64,9 @@ theorem Finset.centerMass_insert (ha : i ∉ t) (hw : ∑ j ∈ t, w j ≠ 0) : rw [div_mul_eq_mul_div, mul_inv_cancel₀ hw, one_div] theorem Finset.centerMass_singleton (hw : w i ≠ 0) : ({i} : Finset ι).centerMass w z = z i := by - rw [centerMass, sum_singleton, sum_singleton, ← mul_smul, inv_mul_cancel₀ hw, one_smul] + rw [centerMass, sum_singleton, sum_singleton] + match_scalars + field_simp @[simp] lemma Finset.centerMass_neg_left : t.centerMass (-w) z = t.centerMass w z := by simp [centerMass, inv_neg] diff --git a/Mathlib/Analysis/Convex/Cone/Extension.lean b/Mathlib/Analysis/Convex/Cone/Extension.lean index 0e1685f92d6f4..31d7448ecb98e 100644 --- a/Mathlib/Analysis/Convex/Cone/Extension.lean +++ b/Mathlib/Analysis/Convex/Cone/Extension.lean @@ -88,7 +88,7 @@ theorem step (nonneg : ∀ x : f.domain, (x : E) ∈ s → 0 ≤ f x) rcases mem_sup.1 hz with ⟨x, hx, y', hy', rfl⟩ rcases mem_span_singleton.1 hy' with ⟨r, rfl⟩ simp only [Subtype.coe_mk] at hzs - erw [LinearPMap.supSpanSingleton_apply_mk _ _ _ _ _ hx, smul_neg, ← sub_eq_add_neg, sub_nonneg] + rw [LinearPMap.supSpanSingleton_apply_mk _ _ _ _ _ hx, smul_neg, ← sub_eq_add_neg, sub_nonneg] rcases lt_trichotomy r 0 with (hr | hr | hr) · have : -(r⁻¹ • x) - y ∈ s := by rwa [← s.smul_mem_iff (neg_pos.2 hr), smul_sub, smul_neg, neg_smul, neg_neg, smul_smul, diff --git a/Mathlib/Analysis/Convex/Continuous.lean b/Mathlib/Analysis/Convex/Continuous.lean new file mode 100644 index 0000000000000..4b2ebd632b395 --- /dev/null +++ b/Mathlib/Analysis/Convex/Continuous.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2023 Yaël Dillies, Zichen Wang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dillies, Zichen Wang +-/ +import Mathlib.Analysis.Convex.Normed + +/-! +# Convex functions are continuous + +This file proves that a convex function from a finite dimensional real normed space to `ℝ` is +continuous. +-/ + +open FiniteDimensional Metric Set List Bornology +open scoped Topology + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + {C : Set E} {f : E → ℝ} {x₀ : E} {ε r r' M : ℝ} + +lemma ConvexOn.lipschitzOnWith_of_abs_le (hf : ConvexOn ℝ (ball x₀ r) f) (hε : 0 < ε) + (hM : ∀ a, dist a x₀ < r → |f a| ≤ M) : + LipschitzOnWith (2 * M / ε).toNNReal f (ball x₀ (r - ε)) := by + set K := 2 * M / ε with hK + have oneside {x y : E} (hx : x ∈ ball x₀ (r - ε)) (hy : y ∈ ball x₀ (r - ε)) : + f x - f y ≤ K * ‖x - y‖ := by + obtain rfl | hxy := eq_or_ne x y + · simp + have hx₀r : ball x₀ (r - ε) ⊆ ball x₀ r := ball_subset_ball <| by linarith + have hx' : x ∈ ball x₀ r := hx₀r hx + have hy' : y ∈ ball x₀ r := hx₀r hy + let z := x + (ε / ‖x - y‖) • (x - y) + replace hxy : 0 < ‖x - y‖ := by rwa [norm_sub_pos_iff] + have hz : z ∈ ball x₀ r := mem_ball_iff_norm.2 <| by + calc + _ = ‖(x - x₀) + (ε / ‖x - y‖) • (x - y)‖ := by simp only [z, add_sub_right_comm] + _ ≤ ‖x - x₀‖ + ‖(ε / ‖x - y‖) • (x - y)‖ := norm_add_le .. + _ < r - ε + ε := + add_lt_add_of_lt_of_le (mem_ball_iff_norm.1 hx) <| by + simp [norm_smul, abs_of_nonneg, hε.le, hxy.ne'] + _ = r := by simp + let a := ε / (ε + ‖x - y‖) + let b := ‖x - y‖ / (ε + ‖x - y‖) + have hab : a + b = 1 := by field_simp [a, b] + have hxyz : x = a • y + b • z := by + calc + x = a • x + b • x := by rw [Convex.combo_self hab] + _ = a • y + b • z := by simp [z, a, b, smul_smul, hxy.ne', smul_sub]; abel + rw [hK, mul_comm, ← mul_div_assoc, le_div_iff₀' hε] + calc + ε * (f x - f y) ≤ ‖x - y‖ * (f z - f x) := by + rw [mul_sub, mul_sub, sub_le_sub_iff, ← add_mul] + have h := hf.2 hy' hz (by positivity) (by positivity) hab + field_simp [← hxyz, a, b, ← mul_div_right_comm] at h + rwa [← le_div_iff₀' (by positivity), add_comm (_ * _)] + _ ≤ _ := by + rw [sub_eq_add_neg (f _), two_mul] + gcongr + · exact (le_abs_self _).trans <| hM _ hz + · exact (neg_le_abs _).trans <| hM _ hx' + refine .of_dist_le' fun x hx y hy ↦ ?_ + simp_rw [dist_eq_norm_sub, Real.norm_eq_abs, abs_sub_le_iff] + exact ⟨oneside hx hy, norm_sub_rev x _ ▸ oneside hy hx⟩ + +lemma ConcaveOn.lipschitzOnWith_of_abs_le (hf : ConcaveOn ℝ (ball x₀ r) f) (hε : 0 < ε) + (hM : ∀ a, dist a x₀ < r → |f a| ≤ M) : + LipschitzOnWith (2 * M / ε).toNNReal f (ball x₀ (r - ε)) := by + simpa using hf.neg.lipschitzOnWith_of_abs_le hε <| by simpa using hM + +lemma ConvexOn.exists_lipschitzOnWith_of_isBounded (hf : ConvexOn ℝ (ball x₀ r) f) (hr : r' < r) + (hf' : IsBounded (f '' ball x₀ r)) : ∃ K, LipschitzOnWith K f (ball x₀ r') := by + rw [isBounded_iff_subset_ball 0] at hf' + simp only [Set.subset_def, mem_image, mem_ball, dist_zero_right, Real.norm_eq_abs, + forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] at hf' + obtain ⟨M, hM⟩ := hf' + rw [← sub_sub_cancel r r'] + exact ⟨_, hf.lipschitzOnWith_of_abs_le (sub_pos.2 hr) fun a ha ↦ (hM a ha).le⟩ + +lemma ConcaveOn.exists_lipschitzOnWith_of_isBounded (hf : ConcaveOn ℝ (ball x₀ r) f) (hr : r' < r) + (hf' : IsBounded (f '' ball x₀ r)) : ∃ K, LipschitzOnWith K f (ball x₀ r') := by + replace hf' : IsBounded ((-f) '' ball x₀ r) := by convert hf'.neg; ext; simp [neg_eq_iff_eq_neg] + simpa using hf.neg.exists_lipschitzOnWith_of_isBounded hr hf' + +lemma ConvexOn.isBoundedUnder_abs (hf : ConvexOn ℝ C f) {x₀ : E} (hC : C ∈ 𝓝 x₀) : + (𝓝 x₀).IsBoundedUnder (· ≤ ·) |f| ↔ (𝓝 x₀).IsBoundedUnder (· ≤ ·) f := by + refine ⟨fun h ↦ h.mono_le <| .of_forall fun x ↦ le_abs_self _, ?_⟩ + rintro ⟨r, hr⟩ + refine ⟨|r| + 2 * |f x₀|, ?_⟩ + have : (𝓝 x₀).Tendsto (fun y => 2 • x₀ - y) (𝓝 x₀) := + tendsto_nhds_nhds.2 (⟨·, ·, by simp [two_nsmul, dist_comm]⟩) + simp only [Filter.eventually_map, Pi.abs_apply, abs_le'] at hr ⊢ + filter_upwards [this.eventually_mem hC, hC, hr, this.eventually hr] with y hx hx' hfr hfr' + refine ⟨hfr.trans <| (le_abs_self _).trans <| by simp, ?_⟩ + rw [← sub_le_iff_le_add, neg_sub_comm, sub_le_iff_le_add', ← abs_two, ← abs_mul] + calc + -|2 * f x₀| ≤ 2 * f x₀ := neg_abs_le _ + _ ≤ f y + f (2 • x₀ - y) := by + have := hf.2 hx' hx (by positivity) (by positivity) (add_halves _) + simp only [one_div, ← Nat.cast_smul_eq_nsmul ℝ, Nat.cast_ofNat, smul_sub, ne_eq, + OfNat.ofNat_ne_zero, not_false_eq_true, inv_smul_smul₀, add_sub_cancel, smul_eq_mul] at this + cancel_denoms at this + rwa [← Nat.cast_two, Nat.cast_smul_eq_nsmul] at this + _ ≤ f y + |r| := by gcongr; exact hfr'.trans (le_abs_self _) + +lemma ConcaveOn.isBoundedUnder_abs (hf : ConcaveOn ℝ C f) {x₀ : E} (hC : C ∈ 𝓝 x₀) : + (𝓝 x₀).IsBoundedUnder (· ≤ ·) |f| ↔ (𝓝 x₀).IsBoundedUnder (· ≥ ·) f := by + simpa [Pi.neg_def, Pi.abs_def] using hf.neg.isBoundedUnder_abs hC + +lemma ConvexOn.continuousOn_tfae (hC : IsOpen C) (hC' : C.Nonempty) (hf : ConvexOn ℝ C f) : TFAE [ + LocallyLipschitzOn C f, + ContinuousOn f C, + ∃ x₀ ∈ C, ContinuousAt f x₀, + ∃ x₀ ∈ C, (𝓝 x₀).IsBoundedUnder (· ≤ ·) f, + ∀ ⦃x₀⦄, x₀ ∈ C → (𝓝 x₀).IsBoundedUnder (· ≤ ·) f, + ∀ ⦃x₀⦄, x₀ ∈ C → (𝓝 x₀).IsBoundedUnder (· ≤ ·) |f|] := by + tfae_have 1 → 2 + · exact LocallyLipschitzOn.continuousOn + tfae_have 2 → 3 + · obtain ⟨x₀, hx₀⟩ := hC' + exact fun h ↦ ⟨x₀, hx₀, h.continuousAt <| hC.mem_nhds hx₀⟩ + tfae_have 3 → 4 + · rintro ⟨x₀, hx₀, h⟩ + exact ⟨x₀, hx₀, f x₀ + 1, by simpa using h.eventually (eventually_le_nhds (by simp))⟩ + tfae_have 4 → 5 + · rintro ⟨x₀, hx₀, r, hr⟩ x hx + have : ∀ᶠ δ in 𝓝 (0 : ℝ), (1 - δ)⁻¹ • x - (δ / (1 - δ)) • x₀ ∈ C := by + have h : ContinuousAt (fun δ : ℝ ↦ (1 - δ)⁻¹ • x - (δ / (1 - δ)) • x₀) 0 := by + fun_prop (disch := norm_num) + exact h (by simpa using hC.mem_nhds hx) + obtain ⟨δ, hδ₀, hy, hδ₁⟩ := (this.and <| eventually_lt_nhds zero_lt_one).exists_gt + set y := (1 - δ)⁻¹ • x - (δ / (1 - δ)) • x₀ + refine ⟨max r (f y), ?_⟩ + simp only [Filter.eventually_map, Pi.abs_apply] at hr ⊢ + obtain ⟨ε, hε, hr⟩ := Metric.eventually_nhds_iff.1 <| hr.and (hC.eventually_mem hx₀) + refine Metric.eventually_nhds_iff.2 ⟨ε * δ, by positivity, fun z hz ↦ ?_⟩ + have hx₀' : δ⁻¹ • (x - y) + y = x₀ := MulAction.injective₀ (sub_ne_zero.2 hδ₁.ne') <| by + simp [y, smul_sub, smul_smul, hδ₀.ne', div_eq_mul_inv, sub_ne_zero.2 hδ₁.ne', mul_left_comm, + sub_mul, sub_smul] + let w := δ⁻¹ • (z - y) + y + have hwyz : δ • w + (1 - δ) • y = z := by simp [w, hδ₀.ne', sub_smul] + have hw : dist w x₀ < ε := by + simpa [w, ← hx₀', dist_smul₀, abs_of_nonneg, hδ₀.le, inv_mul_lt_iff₀', hδ₀] + calc + f z ≤ max (f w) (f y) := + hf.le_max_of_mem_segment (hr hw).2 hy ⟨_, _, hδ₀.le, sub_nonneg.2 hδ₁.le, by simp, hwyz⟩ + _ ≤ max r (f y) := by gcongr; exact (hr hw).1 + tfae_have 6 ↔ 5 + · exact forall₂_congr fun x₀ hx₀ ↦ hf.isBoundedUnder_abs (hC.mem_nhds hx₀) + tfae_have 6 → 1 + · rintro h x hx + obtain ⟨r, hr⟩ := h hx + obtain ⟨ε, hε, hεD⟩ := Metric.mem_nhds_iff.1 <| Filter.inter_mem (hC.mem_nhds hx) hr + simp only [preimage_setOf_eq, Pi.abs_apply, subset_inter_iff, hC.nhdsWithin_eq hx] at hεD ⊢ + obtain ⟨K, hK⟩ := exists_lipschitzOnWith_of_isBounded (hf.subset hεD.1 (convex_ball ..)) + (half_lt_self hε) <| isBounded_iff_forall_norm_le.2 ⟨r, by simpa using hεD.2⟩ + exact ⟨K, _, ball_mem_nhds _ (by simpa), hK⟩ + tfae_finish + +lemma ConcaveOn.continuousOn_tfae (hC : IsOpen C) (hC' : C.Nonempty) (hf : ConcaveOn ℝ C f) : TFAE [ + LocallyLipschitzOn C f, + ContinuousOn f C, + ∃ x₀ ∈ C, ContinuousAt f x₀, + ∃ x₀ ∈ C, (𝓝 x₀).IsBoundedUnder (· ≥ ·) f, + ∀ ⦃x₀⦄, x₀ ∈ C → (𝓝 x₀).IsBoundedUnder (· ≥ ·) f, + ∀ ⦃x₀⦄, x₀ ∈ C → (𝓝 x₀).IsBoundedUnder (· ≤ ·) |f|] := by + have := hf.neg.continuousOn_tfae hC hC' + simp at this + convert this using 8 <;> exact (Equiv.neg ℝ).exists_congr (by simp) + +lemma ConvexOn.locallyLipschitzOn_iff_continuousOn (hC : IsOpen C) (hf : ConvexOn ℝ C f) : + LocallyLipschitzOn C f ↔ ContinuousOn f C := by + obtain rfl | hC' := C.eq_empty_or_nonempty + · simp + · exact (hf.continuousOn_tfae hC hC').out 0 1 + +lemma ConcaveOn.locallyLipschitzOn_iff_continuousOn (hC : IsOpen C) (hf : ConcaveOn ℝ C f) : + LocallyLipschitzOn C f ↔ ContinuousOn f C := by + simpa using hf.neg.locallyLipschitzOn_iff_continuousOn hC + +variable [FiniteDimensional ℝ E] + +protected lemma ConvexOn.locallyLipschitzOn (hC : IsOpen C) (hf : ConvexOn ℝ C f) : + LocallyLipschitzOn C f := by + obtain rfl | ⟨x₀, hx₀⟩ := C.eq_empty_or_nonempty + · simp + · obtain ⟨b, hx₀b, hbC⟩ := exists_mem_interior_convexHull_affineBasis (hC.mem_nhds hx₀) + refine ((hf.continuousOn_tfae hC ⟨x₀, hx₀⟩).out 3 0).mp ?_ + refine ⟨x₀, hx₀, BddAbove.isBoundedUnder (IsOpen.mem_nhds isOpen_interior hx₀b) ?_⟩ + exact (hf.bddAbove_convexHull ((subset_convexHull ..).trans hbC) + ((finite_range _).image _).bddAbove).mono (by gcongr; exact interior_subset) + +protected lemma ConcaveOn.locallyLipschitzOn (hC : IsOpen C) (hf : ConcaveOn ℝ C f) : + LocallyLipschitzOn C f := by simpa using hf.neg.locallyLipschitzOn hC + +protected lemma ConvexOn.continuousOn (hC : IsOpen C) (hf : ConvexOn ℝ C f) : + ContinuousOn f C := (hf.locallyLipschitzOn hC).continuousOn + +protected lemma ConcaveOn.continuousOn (hC : IsOpen C) (hf : ConcaveOn ℝ C f) : + ContinuousOn f C := (hf.locallyLipschitzOn hC).continuousOn + +lemma ConvexOn.locallyLipschitzOn_interior (hf : ConvexOn ℝ C f) : + LocallyLipschitzOn (interior C) f := + (hf.subset interior_subset hf.1.interior).locallyLipschitzOn isOpen_interior + +lemma ConcaveOn.locallyLipschitzOn_interior (hf : ConcaveOn ℝ C f) : + LocallyLipschitzOn (interior C) f := + (hf.subset interior_subset hf.1.interior).locallyLipschitzOn isOpen_interior + +lemma ConvexOn.continuousOn_interior (hf : ConvexOn ℝ C f) : ContinuousOn f (interior C) := + hf.locallyLipschitzOn_interior.continuousOn + +lemma ConcaveOn.continuousOn_interior (hf : ConcaveOn ℝ C f) : ContinuousOn f (interior C) := + hf.locallyLipschitzOn_interior.continuousOn + +protected lemma ConvexOn.locallyLipschitz (hf : ConvexOn ℝ univ f) : LocallyLipschitz f := by + simpa using hf.locallyLipschitzOn_interior + +protected lemma ConcaveOn.locallyLipschitz (hf : ConcaveOn ℝ univ f) : LocallyLipschitz f := by + simpa using hf.locallyLipschitzOn_interior + +-- Commented out since `intrinsicInterior` is not imported (but should be once these are proved) +-- proof_wanted ConvexOn.locallyLipschitzOn_intrinsicInterior (hf : ConvexOn ℝ C f) : +-- ContinuousOn f (intrinsicInterior ℝ C) + +-- proof_wanted ConcaveOn.locallyLipschitzOn_intrinsicInterior (hf : ConcaveOn ℝ C f) : +-- ContinuousOn f (intrinsicInterior ℝ C) + +-- proof_wanted ConvexOn.continuousOn_intrinsicInterior (hf : ConvexOn ℝ C f) : +-- ContinuousOn f (intrinsicInterior ℝ C) + +-- proof_wanted ConcaveOn.continuousOn_intrinsicInterior (hf : ConcaveOn ℝ C f) : +-- ContinuousOn f (intrinsicInterior ℝ C) diff --git a/Mathlib/Analysis/Convex/Deriv.lean b/Mathlib/Analysis/Convex/Deriv.lean index 6954ba6c48f2b..4d71b529373a4 100644 --- a/Mathlib/Analysis/Convex/Deriv.lean +++ b/Mathlib/Analysis/Convex/Deriv.lean @@ -95,7 +95,7 @@ theorem StrictMonoOn.exists_slope_lt_deriv {x y : ℝ} {f : ℝ → ℝ} (hf : C apply ne_of_gt exact hf'_mono ⟨hxw, hwy⟩ ⟨hxw.trans hz.1, hz.2⟩ hz.1 refine ⟨b, ⟨hxw.trans hwb, hby⟩, ?_⟩ - simp only [div_lt_iff, hxy, hxw, hwy, sub_pos] at ha hb ⊢ + simp only [div_lt_iff₀, hxy, hxw, hwy, sub_pos] at ha hb ⊢ have : deriv f a * (w - x) < deriv f b * (w - x) := by apply mul_lt_mul _ le_rfl (sub_pos.2 hxw) _ · exact hf'_mono ⟨hxa, haw.trans hwy⟩ ⟨hxw.trans hwb, hby⟩ (haw.trans hwb) @@ -139,7 +139,7 @@ theorem StrictMonoOn.exists_deriv_lt_slope {x y : ℝ} {f : ℝ → ℝ} (hf : C apply ne_of_gt exact hf'_mono ⟨hxw, hwy⟩ ⟨hxw.trans hz.1, hz.2⟩ hz.1 refine ⟨a, ⟨hxa, haw.trans hwy⟩, ?_⟩ - simp only [lt_div_iff, hxy, hxw, hwy, sub_pos] at ha hb ⊢ + simp only [lt_div_iff₀, hxy, hxw, hwy, sub_pos] at ha hb ⊢ have : deriv f a * (y - w) < deriv f b * (y - w) := by apply mul_lt_mul _ le_rfl (sub_pos.2 hwy) _ · exact hf'_mono ⟨hxa, haw.trans hwy⟩ ⟨hxw.trans hwb, hby⟩ (haw.trans hwb) diff --git a/Mathlib/Analysis/Convex/Gauge.lean b/Mathlib/Analysis/Convex/Gauge.lean index b73b52f91006a..df43239a123de 100644 --- a/Mathlib/Analysis/Convex/Gauge.lean +++ b/Mathlib/Analysis/Convex/Gauge.lean @@ -111,7 +111,7 @@ theorem gauge_of_subset_zero (h : s ⊆ 0) : gauge s = 0 := by /-- The gauge is always nonnegative. -/ theorem gauge_nonneg (x : E) : 0 ≤ gauge s x := - Real.sInf_nonneg _ fun _ hx => hx.1.le + Real.sInf_nonneg fun _ hx => hx.1.le theorem gauge_neg (symmetric : ∀ x ∈ s, -x ∈ s) (x : E) : gauge s (-x) = gauge s x := by have : ∀ x, -x ∈ s ↔ x ∈ s := fun x => ⟨fun h => by simpa using symmetric _ h, symmetric x⟩ @@ -139,7 +139,7 @@ theorem gauge_le_eq (hs₁ : Convex ℝ s) (hs₀ : (0 : E) ∈ s) (hs₂ : Abso suffices (r⁻¹ * δ) • δ⁻¹ • x ∈ s by rwa [smul_smul, mul_inv_cancel_right₀ δ_pos.ne'] at this rw [mem_smul_set_iff_inv_smul_mem₀ δ_pos.ne'] at hδ refine hs₁.smul_mem_of_zero_mem hs₀ hδ ⟨by positivity, ?_⟩ - rw [inv_mul_le_iff hr', mul_one] + rw [inv_mul_le_iff₀ hr', mul_one] exact hδr.le · have hε' := (lt_add_iff_pos_right a).2 (half_pos hε) exact @@ -214,7 +214,7 @@ theorem le_gauge_of_not_mem (hs₀ : StarConvex ℝ 0 s) (hs₂ : Absorbs ℝ s have ha := hb.trans hba refine ⟨(a⁻¹ * b) • x, hs₀ hx' (by positivity) ?_, ?_⟩ · rw [← div_eq_inv_mul] - exact div_le_one_of_le hba.le ha.le + exact div_le_one_of_le₀ hba.le ha.le · dsimp only rw [← mul_smul, mul_inv_cancel_left₀ ha.ne'] @@ -316,7 +316,7 @@ theorem comap_gauge_nhds_zero_le (ha : Absorbent ℝ s) (hb : Bornology.IsVonNBo rcases (hb hu).exists_pos with ⟨r, hr₀, hr⟩ filter_upwards [preimage_mem_comap (gt_mem_nhds (inv_pos.2 hr₀))] with x (hx : gauge s x < r⁻¹) rcases exists_lt_of_gauge_lt ha hx with ⟨c, hc₀, hcr, y, hy, rfl⟩ - have hrc := (lt_inv hr₀ hc₀).2 hcr + have hrc := (lt_inv_comm₀ hr₀ hc₀).2 hcr rcases hr c⁻¹ (hrc.le.trans (le_abs_self _)) hy with ⟨z, hz, rfl⟩ simpa only [smul_inv_smul₀ hc₀.ne'] @@ -369,7 +369,7 @@ theorem gauge_lt_of_mem_smul (x : E) (ε : ℝ) (hε : 0 < ε) (hs₂ : IsOpen s gauge s x < ε := by have : ε⁻¹ • x ∈ s := by rwa [← mem_smul_set_iff_inv_smul_mem₀ hε.ne'] have h_gauge_lt := gauge_lt_one_of_mem_of_isOpen hs₂ this - rwa [gauge_smul_of_nonneg (inv_nonneg.2 hε.le), smul_eq_mul, inv_mul_lt_iff hε, mul_one] + rwa [gauge_smul_of_nonneg (inv_nonneg.2 hε.le), smul_eq_mul, inv_mul_lt_iff₀ hε, mul_one] at h_gauge_lt theorem mem_closure_of_gauge_le_one (hc : Convex ℝ s) (hs₀ : 0 ∈ s) (ha : Absorbent ℝ s) @@ -500,7 +500,7 @@ protected theorem Seminorm.gauge_ball (p : Seminorm ℝ E) : gauge (p.ball 0 1) have hpx₂ : 0 < 2 * p x := mul_pos zero_lt_two hpx refine hp.subset ⟨hpx₂, (2 * p x)⁻¹ • x, ?_, smul_inv_smul₀ hpx₂.ne' _⟩ rw [p.mem_ball_zero, map_smul_eq_mul, Real.norm_eq_abs, abs_of_pos (inv_pos.2 hpx₂), - inv_mul_lt_iff hpx₂, mul_one] + inv_mul_lt_iff₀ hpx₂, mul_one] exact lt_mul_of_one_lt_left hpx one_lt_two refine IsGLB.csInf_eq ⟨fun r => ?_, fun r hr => le_of_forall_pos_le_add fun ε hε => ?_⟩ hp · rintro ⟨hr, y, hy, rfl⟩ @@ -512,7 +512,7 @@ protected theorem Seminorm.gauge_ball (p : Seminorm ℝ E) : gauge (p.ball 0 1) add_pos_of_nonneg_of_pos (apply_nonneg _ _) hε refine hr ⟨hpε, (p x + ε)⁻¹ • x, ?_, smul_inv_smul₀ hpε.ne' _⟩ rw [p.mem_ball_zero, map_smul_eq_mul, Real.norm_eq_abs, abs_of_pos (inv_pos.2 hpε), - inv_mul_lt_iff hpε, mul_one] + inv_mul_lt_iff₀ hpε, mul_one] exact lt_add_of_pos_right _ hε theorem Seminorm.gaugeSeminorm_ball (p : Seminorm ℝ E) : diff --git a/Mathlib/Analysis/Convex/Integral.lean b/Mathlib/Analysis/Convex/Integral.lean index 12b11b68057db..dd75c412a4ffc 100644 --- a/Mathlib/Analysis/Convex/Integral.lean +++ b/Mathlib/Analysis/Convex/Integral.lean @@ -328,7 +328,7 @@ theorem ae_eq_const_or_norm_integral_lt_of_norm_le_const [StrictConvexSpace ℝ simp [ENNReal.toReal_pos_iff, pos_iff_ne_zero, h₀, measure_lt_top] refine (ae_eq_const_or_norm_average_lt_of_norm_le_const h_le).imp_right fun H => ?_ rwa [average_eq, norm_smul, norm_inv, Real.norm_eq_abs, abs_of_pos hμ, ← div_eq_inv_mul, - div_lt_iff' hμ] at H + div_lt_iff₀' hμ] at H /-- If `E` is a strictly convex normed space and `f : α → E` is a function such that `‖f x‖ ≤ C` a.e. on a set `t` of finite measure, then either this function is a.e. equal to its average value on diff --git a/Mathlib/Analysis/Convex/Intrinsic.lean b/Mathlib/Analysis/Convex/Intrinsic.lean index b244bd60d24fb..82cc1b1b0da2d 100644 --- a/Mathlib/Analysis/Convex/Intrinsic.lean +++ b/Mathlib/Analysis/Convex/Intrinsic.lean @@ -96,24 +96,6 @@ theorem intrinsicFrontier_subset_intrinsicClosure : intrinsicFrontier 𝕜 s ⊆ theorem subset_intrinsicClosure : s ⊆ intrinsicClosure 𝕜 s := fun x hx => ⟨⟨x, subset_affineSpan _ _ hx⟩, subset_closure hx, rfl⟩ -lemma intrinsicInterior_eq_interior_of_span (hs : affineSpan 𝕜 s = ⊤) : - intrinsicInterior 𝕜 s = interior s := by - set f : affineSpan 𝕜 s ≃ₜ P := .trans (.setCongr (congr_arg SetLike.coe hs)) (.Set.univ _) - change f '' interior (f ⁻¹' s) = interior s - rw [f.image_interior, f.image_preimage] - -lemma intrinsicFrontier_eq_frontier_of_span (hs : affineSpan 𝕜 s = ⊤) : - intrinsicFrontier 𝕜 s = frontier s := by - set f : affineSpan 𝕜 s ≃ₜ P := .trans (.setCongr (congr_arg SetLike.coe hs)) (.Set.univ _) - change f '' frontier (f ⁻¹' s) = frontier s - rw [f.image_frontier, f.image_preimage] - -lemma intrinsicClosure_eq_closure_of_span (hs : affineSpan 𝕜 s = ⊤) : - intrinsicClosure 𝕜 s = closure s := by - set f : affineSpan 𝕜 s ≃ₜ P := .trans (.setCongr (congr_arg SetLike.coe hs)) (.Set.univ _) - change f '' closure (f ⁻¹' s) = closure s - rw [f.image_closure, f.image_preimage] - @[simp] theorem intrinsicInterior_empty : intrinsicInterior 𝕜 (∅ : Set P) = ∅ := by simp [intrinsicInterior] @@ -123,15 +105,6 @@ theorem intrinsicFrontier_empty : intrinsicFrontier 𝕜 (∅ : Set P) = ∅ := @[simp] theorem intrinsicClosure_empty : intrinsicClosure 𝕜 (∅ : Set P) = ∅ := by simp [intrinsicClosure] -@[simp] lemma intrinsicInterior_univ : intrinsicInterior 𝕜 (univ : Set P) = univ := by - simp [intrinsicInterior] - -@[simp] lemma intrinsicFrontier_univ : intrinsicFrontier 𝕜 (univ : Set P) = ∅ := by - simp [intrinsicFrontier] - -@[simp] lemma intrinsicClosure_univ : intrinsicClosure 𝕜 (univ : Set P) = univ := by - simp [intrinsicClosure] - @[simp] theorem intrinsicClosure_nonempty : (intrinsicClosure 𝕜 s).Nonempty ↔ s.Nonempty := ⟨by simp_rw [nonempty_iff_ne_empty]; rintro h rfl; exact h intrinsicClosure_empty, diff --git a/Mathlib/Analysis/Convex/Jensen.lean b/Mathlib/Analysis/Convex/Jensen.lean index 20e5b017a492d..93f195e014393 100644 --- a/Mathlib/Analysis/Convex/Jensen.lean +++ b/Mathlib/Analysis/Convex/Jensen.lean @@ -118,11 +118,10 @@ lemma StrictConvexOn.map_sum_lt (hf : StrictConvexOn 𝕜 s f) (h₀ : ∀ i ∈ 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 - have hck : c * (w k / c) = w k := by field_simp calc f (w j • p j + (w k • p k + ∑ x ∈ u, w x • p x)) _ = f (c • ((w j / c) • p j + (w k / c) • p k) + ∑ x ∈ u, w x • p x) := by - rw [smul_add, ← mul_smul, ← mul_smul, hcj, hck, add_assoc] + congrm f ?_ + match_scalars <;> field_simp _ ≤ c • f ((w j / c) • p j + (w k / c) • p k) + ∑ x ∈ 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 @@ -134,7 +133,7 @@ lemma StrictConvexOn.map_sum_lt (hf : StrictConvexOn 𝕜 s f) (h₀ : ∀ i ∈ -- 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 _ = (w j • f (p j) + w k • f (p k)) + ∑ x ∈ u, w x • f (p x) := by - rw [smul_add, ← mul_smul, ← mul_smul, hcj, hck] + match_scalars <;> field_simp _ = w j • f (p j) + (w k • f (p k) + ∑ x ∈ u, w x • f (p x)) := by abel_nf /-- Concave **strict Jensen inequality**. diff --git a/Mathlib/Analysis/Convex/Join.lean b/Mathlib/Analysis/Convex/Join.lean index a8641487cfccd..590ebaa4aa614 100644 --- a/Mathlib/Analysis/Convex/Join.lean +++ b/Mathlib/Analysis/Convex/Join.lean @@ -113,19 +113,13 @@ theorem convexJoin_assoc_aux (s t u : Set E) : rintro _ ⟨z, ⟨x, hx, y, hy, a₁, b₁, ha₁, hb₁, hab₁, rfl⟩, z, hz, a₂, b₂, ha₂, hb₂, hab₂, rfl⟩ obtain rfl | hb₂ := hb₂.eq_or_lt · refine ⟨x, hx, y, ⟨y, hy, z, hz, left_mem_segment 𝕜 _ _⟩, a₁, b₁, ha₁, hb₁, hab₁, ?_⟩ - rw [add_zero] at hab₂ - rw [hab₂, one_smul, zero_smul, add_zero] - have ha₂b₁ : 0 ≤ a₂ * b₁ := mul_nonneg ha₂ hb₁ - have hab : 0 < a₂ * b₁ + b₂ := add_pos_of_nonneg_of_pos ha₂b₁ hb₂ + linear_combination (norm := module) congr(-$hab₂ • (a₁ • x + b₁ • y)) refine ⟨x, hx, (a₂ * b₁ / (a₂ * b₁ + b₂)) • y + (b₂ / (a₂ * b₁ + b₂)) • z, - ⟨y, hy, z, hz, _, _, ?_, ?_, ?_, rfl⟩, - a₂ * a₁, a₂ * b₁ + b₂, mul_nonneg ha₂ ha₁, hab.le, ?_, ?_⟩ - · exact div_nonneg ha₂b₁ hab.le - · exact div_nonneg hb₂.le hab.le - · rw [← add_div, div_self hab.ne'] - · rw [← add_assoc, ← mul_add, hab₁, mul_one, hab₂] - · simp_rw [smul_add, ← mul_smul, mul_div_cancel₀ _ hab.ne', add_assoc] + ⟨y, hy, z, hz, _, _, by positivity, by positivity, by field_simp, rfl⟩, + a₂ * a₁, a₂ * b₁ + b₂, by positivity, by positivity, ?_, ?_⟩ + · linear_combination a₂ * hab₁ + hab₂ + · match_scalars <;> field_simp theorem convexJoin_assoc (s t u : Set E) : convexJoin 𝕜 (convexJoin 𝕜 s t) u = convexJoin 𝕜 s (convexJoin 𝕜 t u) := by @@ -155,9 +149,9 @@ protected theorem Convex.convexJoin (hs : Convex 𝕜 s) (ht : Convex 𝕜 t) : rcases hs.exists_mem_add_smul_eq hx₁ hx₂ (mul_nonneg hp ha₁) (mul_nonneg hq ha₂) with ⟨x, hxs, hx⟩ rcases ht.exists_mem_add_smul_eq hy₁ hy₂ (mul_nonneg hp hb₁) (mul_nonneg hq hb₂) with ⟨y, hyt, hy⟩ refine ⟨_, hxs, _, hyt, p * a₁ + q * a₂, p * b₁ + q * b₂, ?_, ?_, ?_, ?_⟩ <;> try positivity - · rwa [add_add_add_comm, ← mul_add, ← mul_add, hab₁, hab₂, mul_one, mul_one] - · rw [hx, hy, add_add_add_comm] - simp only [smul_add, smul_smul] + · linear_combination p * hab₁ + q * hab₂ + hpq + · rw [hx, hy] + module protected theorem Convex.convexHull_union (hs : Convex 𝕜 s) (ht : Convex 𝕜 t) (hs₀ : s.Nonempty) (ht₀ : t.Nonempty) : convexHull 𝕜 (s ∪ t) = convexJoin 𝕜 s t := diff --git a/Mathlib/Analysis/Convex/Measure.lean b/Mathlib/Analysis/Convex/Measure.lean index d8b9b78be2d4b..cf276ed3f8958 100644 --- a/Mathlib/Analysis/Convex/Measure.lean +++ b/Mathlib/Analysis/Convex/Measure.lean @@ -18,7 +18,7 @@ convex set in `E`. Then the frontier of `s` has measure zero (see `Convex.addHaa open MeasureTheory MeasureTheory.Measure Set Metric Filter Bornology -open FiniteDimensional (finrank) +open Module (finrank) open scoped Topology NNReal ENNReal @@ -64,7 +64,7 @@ theorem addHaar_frontier (hs : Convex ℝ s) : μ (frontier s) = 0 := by /- Due to `Convex.closure_subset_image_homothety_interior_of_one_lt`, for any `r > 1` we have `closure s ⊆ homothety x r '' interior s`, hence `μ (closure s) ≤ r ^ d * μ (interior s)`, where `d = finrank ℝ E`. -/ - set d : ℕ := FiniteDimensional.finrank ℝ E + set d : ℕ := Module.finrank ℝ E have : ∀ r : ℝ≥0, 1 < r → μ (closure s) ≤ ↑(r ^ d) * μ (interior s) := fun r hr ↦ by refine (measure_mono <| hs.closure_subset_image_homothety_interior_of_one_lt hx r hr).trans_eq ?_ diff --git a/Mathlib/Analysis/Convex/Normed.lean b/Mathlib/Analysis/Convex/Normed.lean index 2cb4a8b2db0d7..bfb9ac2e29cd3 100644 --- a/Mathlib/Analysis/Convex/Normed.lean +++ b/Mathlib/Analysis/Convex/Normed.lean @@ -27,7 +27,7 @@ We prove the following facts: variable {ι : Type*} {E P : Type*} -open AffineBasis FiniteDimensional Metric Set +open AffineBasis Module Metric Set open scoped Convex Pointwise Topology section SeminormedAddCommGroup diff --git a/Mathlib/Analysis/Convex/Radon.lean b/Mathlib/Analysis/Convex/Radon.lean index ee505ba41b251..f297649b6f470 100644 --- a/Mathlib/Analysis/Convex/Radon.lean +++ b/Mathlib/Analysis/Convex/Radon.lean @@ -62,7 +62,7 @@ theorem radon_partition {f : ι → E} (h : ¬ AffineIndependent 𝕜 f) : · linarith only [hI, hJI] · exact (mem_filter.mp hi').2.not_lt (mem_filter.mp hi).2 -open FiniteDimensional +open Module /-- Corner case for `helly_theorem'`. -/ private lemma helly_theorem_corner {F : ι → Set E} {s : Finset ι} diff --git a/Mathlib/Analysis/Convex/Side.lean b/Mathlib/Analysis/Convex/Side.lean index 4bedc05dc363e..45bc7d0036eb8 100644 --- a/Mathlib/Analysis/Convex/Side.lean +++ b/Mathlib/Analysis/Convex/Side.lean @@ -333,12 +333,8 @@ theorem _root_.Wbtw.wOppSide₁₃ {s : AffineSubspace R P} {x y z : P} (h : Wbt rcases ht0.lt_or_eq with (ht0' | rfl); swap · rw [lineMap_apply_zero]; simp refine Or.inr (Or.inr ⟨1 - t, t, sub_pos.2 ht1', ht0', ?_⟩) - -- TODO: after lean4#2336 "simp made no progress feature" - -- had to add `_` to several lemmas here. Not sure why! - simp_rw [lineMap_apply _, vadd_vsub_assoc _, vsub_vadd_eq_vsub_sub _, - ← neg_vsub_eq_vsub_rev z x, vsub_self _, zero_sub, ← neg_one_smul R (z -ᵥ x), - ← add_smul, smul_neg, ← neg_smul, smul_smul] - ring_nf + rw [lineMap_apply, vadd_vsub_assoc, vsub_vadd_eq_vsub_sub, ← neg_vsub_eq_vsub_rev z, vsub_self] + module theorem _root_.Wbtw.wOppSide₃₁ {s : AffineSubspace R P} {x y z : P} (h : Wbtw R x y z) (hy : y ∈ s) : s.WOppSide z x := @@ -411,9 +407,9 @@ theorem wOppSide_iff_exists_left {s : AffineSubspace R P} {x y p₁ : P} (h : p exact SameRay.zero_right _ · refine Or.inr ⟨(-r₁ / r₂) • (p₁ -ᵥ p₁') +ᵥ p₂', s.smul_vsub_vadd_mem _ h hp₁' hp₂', Or.inr (Or.inr ⟨r₁, r₂, hr₁, hr₂, ?_⟩)⟩ - rw [vadd_vsub_assoc, smul_add, ← hr, smul_smul, neg_div, mul_neg, - mul_div_cancel₀ _ hr₂.ne.symm, neg_smul, neg_add_eq_sub, ← smul_sub, - vsub_sub_vsub_cancel_right] + rw [vadd_vsub_assoc, ← vsub_sub_vsub_cancel_right x p₁ p₁'] + linear_combination (norm := match_scalars <;> field_simp) hr + ring · rintro (h' | ⟨h₁, h₂, h₃⟩) · exact wOppSide_of_left_mem y h' · exact ⟨p₁, h, h₁, h₂, h₃⟩ @@ -584,16 +580,15 @@ theorem wOppSide_iff_exists_wbtw {s : AffineSubspace R P} {x y : P} : · refine ⟨lineMap x y (r₂ / (r₁ + r₂)), ?_, ?_⟩ · have : (r₂ / (r₁ + r₂)) • (y -ᵥ p₂ + (p₂ -ᵥ p₁) - (x -ᵥ p₁)) + (x -ᵥ p₁) = (r₂ / (r₁ + r₂)) • (p₂ -ᵥ p₁) := by - rw [add_comm (y -ᵥ p₂), smul_sub, smul_add, add_sub_assoc, add_assoc, add_right_eq_self, - div_eq_inv_mul, ← neg_vsub_eq_vsub_rev, smul_neg, ← smul_smul, ← h, smul_smul, ← neg_smul, - ← sub_smul, ← div_eq_inv_mul, ← div_eq_inv_mul, ← neg_div, ← sub_div, sub_eq_add_neg, - ← neg_add, neg_div, div_self (Left.add_pos hr₁ hr₂).ne.symm, neg_one_smul, neg_add_cancel] + rw [← neg_vsub_eq_vsub_rev p₂ y] + linear_combination (norm := match_scalars <;> field_simp) congr((r₁ + r₂)⁻¹ • $h) + ring rw [lineMap_apply, ← vsub_vadd x p₁, ← vsub_vadd y p₂, vsub_vadd_eq_vsub_sub, vadd_vsub_assoc, ← vadd_assoc, vadd_eq_add, this] exact s.smul_vsub_vadd_mem (r₂ / (r₁ + r₂)) hp₂ hp₁ hp₁ · exact Set.mem_image_of_mem _ - ⟨div_nonneg hr₂.le (Left.add_pos hr₁ hr₂).le, - div_le_one_of_le (le_add_of_nonneg_left hr₁.le) (Left.add_pos hr₁ hr₂).le⟩ + ⟨by positivity, + div_le_one_of_le₀ (le_add_of_nonneg_left hr₁.le) (Left.add_pos hr₁ hr₂).le⟩ theorem SOppSide.exists_sbtw {s : AffineSubspace R P} {x y : P} (h : s.SOppSide x y) : ∃ p ∈ s, Sbtw R x p y := by diff --git a/Mathlib/Analysis/Convex/Slope.lean b/Mathlib/Analysis/Convex/Slope.lean index ea7ca88a2e853..38072902d3e91 100644 --- a/Mathlib/Analysis/Convex/Slope.lean +++ b/Mathlib/Analysis/Convex/Slope.lean @@ -158,7 +158,7 @@ theorem strictConvexOn_of_slope_strict_mono_adjacent (hs : Convex 𝕜 s) simp_rw [div_eq_iff hxz.ne', ← hab] ring rwa [sub_mul, sub_mul, sub_lt_iff_lt_add', ← add_sub_assoc, lt_sub_iff_add_lt, ← mul_add, - sub_add_sub_cancel, ← lt_div_iff hxz, add_div, mul_div_assoc, mul_div_assoc, mul_comm (f x), + sub_add_sub_cancel, ← lt_div_iff₀ hxz, add_div, mul_div_assoc, mul_div_assoc, mul_comm (f x), mul_comm (f z), ha, hb] at this /-- If for any three points `x < y < z`, the slope of the secant line of `f : 𝕜 → 𝕜` on `[x, y]` is @@ -267,7 +267,7 @@ theorem StrictConvexOn.secant_strict_mono_aux1 (hf : StrictConvexOn 𝕜 s f) {x have hxy' : 0 < y - x := by linarith have hyz' : 0 < z - y := by linarith have hxz' : 0 < z - x := by linarith - rw [← lt_div_iff' hxz'] + rw [← lt_div_iff₀' hxz'] have ha : 0 < (z - y) / (z - x) := by positivity have hb : 0 < (y - x) / (z - x) := by positivity calc diff --git a/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean b/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean index 922b18543ffe0..b293f4c6a7eb3 100644 --- a/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean +++ b/Mathlib/Analysis/Convex/SpecificFunctions/Basic.lean @@ -40,14 +40,14 @@ theorem strictConvexOn_exp : StrictConvexOn ℝ univ exp := by trans exp y · have h1 : 0 < y - x := by linarith have h2 : x - y < 0 := by linarith - rw [div_lt_iff h1] + rw [div_lt_iff₀ h1] calc exp y - exp x = exp y - exp y * exp (x - y) := by rw [← exp_add]; ring_nf _ = exp y * (1 - exp (x - y)) := by ring _ < exp y * -(x - y) := by gcongr; linarith [add_one_lt_exp h2.ne] _ = exp y * (y - x) := by ring · have h1 : 0 < z - y := by linarith - rw [lt_div_iff h1] + rw [lt_div_iff₀ h1] calc exp y * (z - y) < exp y * (exp (z - y) - 1) := by gcongr _ * ?_ @@ -66,7 +66,7 @@ theorem strictConcaveOn_log_Ioi : StrictConcaveOn ℝ (Ioi 0) log := by have hy : 0 < y := hx.trans hxy trans y⁻¹ · have h : 0 < z - y := by linarith - rw [div_lt_iff h] + rw [div_lt_iff₀ h] have hyz' : 0 < z / y := by positivity have hyz'' : z / y ≠ 1 := by contrapose! h @@ -77,7 +77,7 @@ theorem strictConcaveOn_log_Ioi : StrictConcaveOn ℝ (Ioi 0) log := by _ < z / y - 1 := log_lt_sub_one_of_pos hyz' hyz'' _ = y⁻¹ * (z - y) := by field_simp · have h : 0 < y - x := by linarith - rw [lt_div_iff h] + rw [lt_div_iff₀ h] have hxy' : 0 < x / y := by positivity have hxy'' : x / y ≠ 1 := by contrapose! h @@ -105,12 +105,12 @@ theorem one_add_mul_self_lt_rpow_one_add {s : ℝ} (hs : -1 ≤ s) (hs' : s ≠ rw [rpow_def_of_pos hs1, ← exp_log hs2] apply exp_strictMono cases' lt_or_gt_of_ne hs' with hs' hs' - · rw [← div_lt_iff hp', ← div_lt_div_right_of_neg hs'] + · rw [← div_lt_iff₀ hp', ← div_lt_div_right_of_neg hs'] convert strictConcaveOn_log_Ioi.secant_strict_mono (zero_lt_one' ℝ) hs2 hs1 hs4 hs3 _ using 1 · rw [add_sub_cancel_left, log_one, sub_zero] · rw [add_sub_cancel_left, div_div, log_one, sub_zero] · apply add_lt_add_left (mul_lt_of_one_lt_left hs' hp) - · rw [← div_lt_iff hp', ← div_lt_div_right hs'] + · rw [← div_lt_iff₀ hp', ← div_lt_div_right hs'] convert strictConcaveOn_log_Ioi.secant_strict_mono (zero_lt_one' ℝ) hs1 hs2 hs3 hs4 _ using 1 · rw [add_sub_cancel_left, div_div, log_one, sub_zero] · rw [add_sub_cancel_left, log_one, sub_zero] @@ -144,12 +144,12 @@ theorem rpow_one_add_lt_one_add_mul_self {s : ℝ} (hs : -1 ≤ s) (hs' : s ≠ rw [rpow_def_of_pos hs1, ← exp_log hs2] apply exp_strictMono cases' lt_or_gt_of_ne hs' with hs' hs' - · rw [← lt_div_iff hp1, ← div_lt_div_right_of_neg hs'] + · rw [← lt_div_iff₀ hp1, ← div_lt_div_right_of_neg hs'] convert strictConcaveOn_log_Ioi.secant_strict_mono (zero_lt_one' ℝ) hs1 hs2 hs3 hs4 _ using 1 · rw [add_sub_cancel_left, div_div, log_one, sub_zero] · rw [add_sub_cancel_left, log_one, sub_zero] · apply add_lt_add_left (lt_mul_of_lt_one_left hs' hp2) - · rw [← lt_div_iff hp1, ← div_lt_div_right hs'] + · rw [← lt_div_iff₀ hp1, ← div_lt_div_right hs'] convert strictConcaveOn_log_Ioi.secant_strict_mono (zero_lt_one' ℝ) hs2 hs1 hs4 hs3 _ using 1 · rw [add_sub_cancel_left, log_one, sub_zero] · rw [add_sub_cancel_left, div_div, log_one, sub_zero] @@ -175,20 +175,21 @@ theorem strictConvexOn_rpow {p : ℝ} (hp : 1 < p) : StrictConvexOn ℝ (Ici 0) have hy' : 0 < y ^ p := rpow_pos_of_pos hy _ trans p * y ^ (p - 1) · have q : 0 < y - x := by rwa [sub_pos] - rw [div_lt_iff q, ← div_lt_div_right hy', _root_.sub_div, div_self hy'.ne', ← div_rpow hx hy.le, - sub_lt_comm, ← add_sub_cancel_right (x / y) 1, add_comm, add_sub_assoc, ← div_mul_eq_mul_div, - mul_div_assoc, ← rpow_sub hy, sub_sub_cancel_left, rpow_neg_one, mul_assoc, ← div_eq_inv_mul, - sub_eq_add_neg, ← mul_neg, ← neg_div, neg_sub, _root_.sub_div, div_self hy.ne'] + rw [div_lt_iff₀ q, ← div_lt_div_right hy', _root_.sub_div, div_self hy'.ne', + ← div_rpow hx hy.le, sub_lt_comm, ← add_sub_cancel_right (x / y) 1, add_comm, add_sub_assoc, + ← div_mul_eq_mul_div, mul_div_assoc, ← rpow_sub hy, sub_sub_cancel_left, rpow_neg_one, + mul_assoc, ← div_eq_inv_mul, sub_eq_add_neg, ← mul_neg, ← neg_div, neg_sub, _root_.sub_div, + div_self hy.ne'] apply one_add_mul_self_lt_rpow_one_add _ _ hp · rw [le_sub_iff_add_le, neg_add_cancel, div_nonneg_iff] exact Or.inl ⟨hx, hy.le⟩ · rw [sub_ne_zero] exact ((div_lt_one hy).mpr hxy).ne · have q : 0 < z - y := by rwa [sub_pos] - rw [lt_div_iff q, ← div_lt_div_right hy', _root_.sub_div, div_self hy'.ne', ← div_rpow hz hy.le, - lt_sub_iff_add_lt', ← add_sub_cancel_right (z / y) 1, add_comm _ 1, add_sub_assoc, - ← div_mul_eq_mul_div, mul_div_assoc, ← rpow_sub hy, sub_sub_cancel_left, rpow_neg_one, - mul_assoc, ← div_eq_inv_mul, _root_.sub_div, div_self hy.ne'] + rw [lt_div_iff₀ q, ← div_lt_div_right hy', _root_.sub_div, div_self hy'.ne', + ← div_rpow hz hy.le, lt_sub_iff_add_lt', ← add_sub_cancel_right (z / y) 1, add_comm _ 1, + add_sub_assoc, ← div_mul_eq_mul_div, mul_div_assoc, ← rpow_sub hy, sub_sub_cancel_left, + rpow_neg_one, mul_assoc, ← div_eq_inv_mul, _root_.sub_div, div_self hy.ne'] apply one_add_mul_self_lt_rpow_one_add _ _ hp · rw [le_sub_iff_add_le, neg_add_cancel, div_nonneg_iff] exact Or.inl ⟨hz, hy.le⟩ diff --git a/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean b/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean index 9d5442089d921..981b12a32e26c 100644 --- a/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean +++ b/Mathlib/Analysis/Convex/SpecificFunctions/Deriv.lean @@ -96,7 +96,7 @@ theorem strictConvexOn_zpow {m : ℤ} (hm₀ : m ≠ 0) (hm₁ : m ≠ 1) : intro x hx rw [mem_Ioi] at hx rw [iter_deriv_zpow] - refine mul_pos ?_ (zpow_pos_of_pos hx _) + refine mul_pos ?_ (zpow_pos hx _) norm_cast refine int_prod_range_pos (by decide) fun hm => ?_ rw [← Finset.coe_Ico] at hm diff --git a/Mathlib/Analysis/Convex/Star.lean b/Mathlib/Analysis/Convex/Star.lean index 44f1a60ccabfb..ad0ee8acf1ca5 100644 --- a/Mathlib/Analysis/Convex/Star.lean +++ b/Mathlib/Analysis/Convex/Star.lean @@ -8,6 +8,7 @@ import Mathlib.Algebra.Order.Module.Synonym import Mathlib.Algebra.Order.Group.Instances import Mathlib.Analysis.Convex.Segment import Mathlib.Tactic.GCongr +import Mathlib.Tactic.Module /-! # Star-convex sets @@ -210,14 +211,14 @@ theorem StarConvex.add_left (hs : StarConvex 𝕜 x s) (z : E) : intro y hy a b ha hb hab obtain ⟨y', hy', rfl⟩ := hy refine ⟨a • x + b • y', hs hy' ha hb hab, ?_⟩ - rw [smul_add, smul_add, add_add_add_comm, ← add_smul, hab, one_smul] + match_scalars <;> simp [hab] theorem StarConvex.add_right (hs : StarConvex 𝕜 x s) (z : E) : StarConvex 𝕜 (x + z) ((fun x => x + z) '' s) := by intro y hy a b ha hb hab obtain ⟨y', hy', rfl⟩ := hy refine ⟨a • x + b • y', hs hy' ha hb hab, ?_⟩ - rw [smul_add, smul_add, add_add_add_comm, ← add_smul, hab, one_smul] + match_scalars <;> simp [hab] /-- The translation of a star-convex set is also star-convex. -/ theorem StarConvex.preimage_add_right (hs : StarConvex 𝕜 (z + x) s) : @@ -385,7 +386,7 @@ theorem starConvex_iff_div : StarConvex 𝕜 x s ↔ ∀ ⦃y⦄, y ∈ s → theorem StarConvex.mem_smul (hs : StarConvex 𝕜 0 s) (hx : x ∈ s) {t : 𝕜} (ht : 1 ≤ t) : x ∈ t • s := by rw [mem_smul_set_iff_inv_smul_mem₀ (zero_lt_one.trans_le ht).ne'] - exact hs.smul_mem hx (by positivity) (inv_le_one ht) + exact hs.smul_mem hx (by positivity) (inv_le_one_of_one_le₀ ht) end AddCommGroup diff --git a/Mathlib/Analysis/Convex/StoneSeparation.lean b/Mathlib/Analysis/Convex/StoneSeparation.lean index 4f746cd1909fd..1027690d2b881 100644 --- a/Mathlib/Analysis/Convex/StoneSeparation.lean +++ b/Mathlib/Analysis/Convex/StoneSeparation.lean @@ -46,9 +46,6 @@ theorem not_disjoint_segment_convexHull_triple {p q u v x y z : E} (hz : z ∈ s · positivity · positivity · rw [← add_div, div_self]; positivity - rw [smul_add, smul_add, add_add_add_comm] - nth_rw 2 [add_comm] - rw [← mul_smul, ← mul_smul] classical let w : Fin 3 → 𝕜 := ![az * av * bu, bz * au * bv, au * av] let z : Fin 3 → E := ![p, q, az • x + bz • y] @@ -61,18 +58,15 @@ theorem not_disjoint_segment_convexHull_triple {p q u v x y z : E} (hz : z ∈ s have hw : ∑ i, w i = az * av + bz * au := by trans az * av * bu + (bz * au * bv + au * av) · simp [w, Fin.sum_univ_succ, Fin.sum_univ_zero] - rw [← one_mul (au * av), ← habz, add_mul, ← add_assoc, add_add_add_comm, mul_assoc, ← mul_add, - mul_assoc, ← mul_add, mul_comm av, ← add_mul, ← mul_add, add_comm bu, add_comm bv, habu, - habv, one_mul, mul_one] + linear_combination (au * bv - 1 * au) * habz + (-(1 * az * au) + au) * habv + az * av * habu have hz : ∀ i, z i ∈ ({p, q, az • x + bz • y} : Set E) := fun i => by fin_cases i <;> simp [z] convert (Finset.centerMass_mem_convexHull (Finset.univ : Finset (Fin 3)) (fun i _ => hw₀ i) (by rwa [hw]) fun i _ => hz i : Finset.univ.centerMass w z ∈ _) - rw [Finset.centerMass] - simp_rw [div_eq_inv_mul, hw, mul_assoc, mul_smul (az * av + bz * au)⁻¹, ← smul_add, add_assoc, ← - mul_assoc] + rw [Finset.centerMass, hw] + trans (az * av + bz * au)⁻¹ • + ((az * av * bu) • p + ((bz * au * bv) • q + (au * av) • (az • x + bz • y))) + · module congr 3 - rw [← mul_smul, ← mul_rotate, mul_right_comm, mul_smul, ← mul_smul _ av, mul_rotate, - mul_smul _ bz, ← smul_add] simp only [w, z, smul_add, List.foldr, Matrix.cons_val_succ', Fin.mk_one, Matrix.cons_val_one, Matrix.head_cons, add_zero] diff --git a/Mathlib/Analysis/Convex/Strict.lean b/Mathlib/Analysis/Convex/Strict.lean index da771a82ffc55..1eabcd86ec380 100644 --- a/Mathlib/Analysis/Convex/Strict.lean +++ b/Mathlib/Analysis/Convex/Strict.lean @@ -302,8 +302,7 @@ theorem StrictConvex.eq_of_openSegment_subset_frontier [Nontrivial 𝕜] [Densel theorem StrictConvex.add_smul_mem (hs : StrictConvex 𝕜 s) (hx : x ∈ s) (hxy : x + y ∈ s) (hy : y ≠ 0) {t : 𝕜} (ht₀ : 0 < t) (ht₁ : t < 1) : x + t • y ∈ interior s := by - have h : x + t • y = (1 - t) • x + t • (x + y) := by - rw [smul_add, ← add_assoc, ← _root_.add_smul, sub_add_cancel, one_smul] + have h : x + t • y = (1 - t) • x + t • (x + y) := by match_scalars <;> field_simp rw [h] exact hs hx hxy (fun h => hy <| add_left_cancel (a := x) (by rw [← h, add_zero])) (sub_pos_of_lt ht₁) ht₀ (sub_add_cancel 1 t) @@ -359,16 +358,14 @@ theorem strictConvex_iff_div : StrictConvex 𝕜 s ↔ s.Pairwise fun x y => ∀ ⦃a b : 𝕜⦄, 0 < a → 0 < b → (a / (a + b)) • x + (b / (a + b)) • y ∈ interior s := - ⟨fun h x hx y hy hxy a b ha hb => by - apply h hx hy hxy (div_pos ha <| add_pos ha hb) (div_pos hb <| add_pos ha hb) - rw [← add_div] - exact div_self (add_pos ha hb).ne', fun h x hx y hy hxy a b ha hb hab => by + ⟨fun h x hx y hy hxy a b ha hb ↦ h hx hy hxy (by positivity) (by positivity) (by field_simp), + fun h x hx y hy hxy a b ha hb hab ↦ by convert h hx hy hxy ha hb <;> rw [hab, div_one]⟩ theorem StrictConvex.mem_smul_of_zero_mem (hs : StrictConvex 𝕜 s) (zero_mem : (0 : E) ∈ s) (hx : x ∈ s) (hx₀ : x ≠ 0) {t : 𝕜} (ht : 1 < t) : x ∈ t • interior s := by - rw [mem_smul_set_iff_inv_smul_mem₀ (zero_lt_one.trans ht).ne'] - exact hs.smul_mem_of_zero_mem zero_mem hx hx₀ (inv_pos.2 <| zero_lt_one.trans ht) (inv_lt_one ht) + rw [mem_smul_set_iff_inv_smul_mem₀ (by positivity)] + exact hs.smul_mem_of_zero_mem zero_mem hx hx₀ (by positivity) (inv_lt_one_of_one_lt₀ ht) end AddCommGroup diff --git a/Mathlib/Analysis/Convex/StrictConvexSpace.lean b/Mathlib/Analysis/Convex/StrictConvexSpace.lean index 29a52bd553f83..32a1cef9cd3a9 100644 --- a/Mathlib/Analysis/Convex/StrictConvexSpace.lean +++ b/Mathlib/Analysis/Convex/StrictConvexSpace.lean @@ -204,5 +204,5 @@ theorem not_sameRay_iff_abs_lt_norm_sub : ¬SameRay ℝ x y ↔ |‖x‖ - ‖y theorem norm_midpoint_lt_iff (h : ‖x‖ = ‖y‖) : ‖(1 / 2 : ℝ) • (x + y)‖ < ‖x‖ ↔ x ≠ y := by rw [norm_smul, Real.norm_of_nonneg (one_div_nonneg.2 zero_le_two), ← inv_eq_one_div, ← - div_eq_inv_mul, div_lt_iff (zero_lt_two' ℝ), mul_two, ← not_sameRay_iff_of_norm_eq h, + div_eq_inv_mul, div_lt_iff₀ (zero_lt_two' ℝ), mul_two, ← not_sameRay_iff_of_norm_eq h, not_sameRay_iff_norm_add_lt, h] diff --git a/Mathlib/Analysis/Convex/Topology.lean b/Mathlib/Analysis/Convex/Topology.lean index 312786bb4c364..c6d92df1bdcf2 100644 --- a/Mathlib/Analysis/Convex/Topology.lean +++ b/Mathlib/Analysis/Convex/Topology.lean @@ -26,9 +26,20 @@ open Metric Bornology Set Pointwise Convex variable {ι 𝕜 E : Type*} -theorem Real.convex_iff_isPreconnected {s : Set ℝ} : Convex ℝ s ↔ IsPreconnected s := +namespace Real +variable {s : Set ℝ} {r ε : ℝ} + +lemma closedBall_eq_segment (hε : 0 ≤ ε) : closedBall r ε = segment ℝ (r - ε) (r + ε) := by + rw [closedBall_eq_Icc, segment_eq_Icc ((sub_le_self _ hε).trans <| le_add_of_nonneg_right hε)] + +lemma ball_eq_openSegment (hε : 0 < ε) : ball r ε = openSegment ℝ (r - ε) (r + ε) := by + rw [ball_eq_Ioo, openSegment_eq_Ioo ((sub_lt_self _ hε).trans <| lt_add_of_pos_right _ hε)] + +theorem convex_iff_isPreconnected : Convex ℝ s ↔ IsPreconnected s := convex_iff_ordConnected.trans isPreconnected_iff_ordConnected.symm +end Real + alias ⟨_, IsPreconnected.convex⟩ := Real.convex_iff_isPreconnected /-! ### Standard simplex -/ diff --git a/Mathlib/Analysis/Convex/Uniform.lean b/Mathlib/Analysis/Convex/Uniform.lean index c57da9a0c876f..9e22c41ca4d16 100644 --- a/Mathlib/Analysis/Convex/Uniform.lean +++ b/Mathlib/Analysis/Convex/Uniform.lean @@ -72,7 +72,8 @@ theorem exists_forall_closed_ball_dist_add_le_two_sub (hε : 0 < ε) : have h₂ : ∀ z : E, ‖z‖ ≤ 1 → 1 - δ' ≤ ‖z‖ → ‖‖z‖⁻¹ • z - z‖ ≤ δ' := by rintro z hz hδz nth_rw 3 [← one_smul ℝ z] - rwa [← sub_smul, norm_smul_of_nonneg (sub_nonneg_of_le <| one_le_inv (hδ'.trans_le hδz) hz), + rwa [← sub_smul, + norm_smul_of_nonneg (sub_nonneg_of_le <| (one_le_inv₀ (hδ'.trans_le hδz)).2 hz), sub_mul, inv_mul_cancel₀ (hδ'.trans_le hδz).ne', one_mul, sub_le_comm] set x' := ‖x‖⁻¹ • x set y' := ‖y‖⁻¹ • y diff --git a/Mathlib/Analysis/Distribution/SchwartzSpace.lean b/Mathlib/Analysis/Distribution/SchwartzSpace.lean index 310970a55e4ef..ba8aae073aff9 100644 --- a/Mathlib/Analysis/Distribution/SchwartzSpace.lean +++ b/Mathlib/Analysis/Distribution/SchwartzSpace.lean @@ -139,7 +139,7 @@ theorem isBigO_cocompact_zpow_neg_nat (k : ℕ) : refine ⟨d, Filter.Eventually.filter_mono Filter.cocompact_le_cofinite ?_⟩ refine (Filter.eventually_cofinite_ne 0).mono fun x hx => ?_ rw [Real.norm_of_nonneg (zpow_nonneg (norm_nonneg _) _), zpow_neg, ← div_eq_mul_inv, le_div_iff₀'] - exacts [hd' x, zpow_pos_of_pos (norm_pos_iff.mpr hx) _] + exacts [hd' x, zpow_pos (norm_pos_iff.mpr hx) _] theorem isBigO_cocompact_rpow [ProperSpace E] (s : ℝ) : f =O[cocompact E] fun x => ‖x‖ ^ s := by @@ -575,11 +575,11 @@ lemma _root_.ContinuousLinearMap.hasTemperateGrowth (f : E →L[ℝ] F) : variable [NormedAddCommGroup D] [MeasurableSpace D] -open MeasureTheory FiniteDimensional +open MeasureTheory Module /-- A measure `μ` has temperate growth if there is an `n : ℕ` such that `(1 + ‖x‖) ^ (- n)` is `μ`-integrable. -/ -class _root_.MeasureTheory.Measure.HasTemperateGrowth (μ : Measure D) : Prop := +class _root_.MeasureTheory.Measure.HasTemperateGrowth (μ : Measure D) : Prop where exists_integrable : ∃ (n : ℕ), Integrable (fun x ↦ (1 + ‖x‖) ^ (- (n : ℝ))) μ open Classical in @@ -616,7 +616,7 @@ lemma pow_mul_le_of_le_of_pow_mul_le {C₁ C₂ : ℝ} {k l : ℕ} {x f : ℝ} ( rw [this] rcases le_total x 1 with h'x|h'x · gcongr - · apply (pow_le_one k hx h'x).trans + · apply (pow_le_one₀ hx h'x).trans apply Real.one_le_rpow_of_pos_of_le_one_of_nonpos · linarith · linarith @@ -854,7 +854,7 @@ def compCLM {g : D → E} (hg : g.HasTemperateGrowth) refine add_le_add ?_ (hg_upper' x) nth_rw 1 [← one_mul (1 : ℝ)] gcongr - apply one_le_pow_of_one_le + apply one_le_pow₀ simp only [le_add_iff_nonneg_right, norm_nonneg] have hbound : ∀ i, i ≤ n → ‖iteratedFDeriv ℝ i f (g x)‖ ≤ 2 ^ k' * seminorm_f / (1 + ‖g x‖) ^ k' := by @@ -870,8 +870,8 @@ def compCLM {g : D → E} (hg : g.HasTemperateGrowth) rw [mul_pow] have hN₁' := (lt_of_lt_of_le zero_lt_one hN₁).ne' gcongr - · exact le_trans (by simp [hC]) (le_self_pow (by simp [hC]) hN₁') - · refine le_self_pow (one_le_pow_of_one_le ?_ l) hN₁' + · exact le_trans (by simp [hC]) (le_self_pow₀ (by simp [hC]) hN₁') + · refine le_self_pow₀ (one_le_pow₀ ?_) hN₁' simp only [le_add_iff_nonneg_right, norm_nonneg] have := norm_iteratedFDeriv_comp_le f.smooth' hg.1 le_top x hbound hgrowth' have hxk : ‖x‖ ^ k ≤ (1 + ‖x‖) ^ k := @@ -956,7 +956,7 @@ theorem fderivCLM_apply (f : 𝓢(E, F)) (x : E) : fderivCLM 𝕜 f x = fderiv /-- The 1-dimensional derivative on Schwartz space as a continuous `𝕜`-linear map. -/ def derivCLM : 𝓢(ℝ, F) →L[𝕜] 𝓢(ℝ, F) := - mkCLM (fun f => deriv f) (fun f g _ => deriv_add f.differentiableAt g.differentiableAt) + mkCLM deriv (fun f g _ => deriv_add f.differentiableAt g.differentiableAt) (fun a f _ => deriv_const_smul a f.differentiableAt) (fun f => (contDiff_top_iff_deriv.mp f.smooth').2) fun ⟨k, n⟩ => ⟨{⟨k, n + 1⟩}, 1, zero_le_one, fun f x => by @@ -1036,7 +1036,7 @@ section Integration /-! ### Integration -/ -open Real Complex Filter MeasureTheory MeasureTheory.Measure FiniteDimensional +open Real Complex Filter MeasureTheory MeasureTheory.Measure Module variable [RCLike 𝕜] variable [NormedAddCommGroup D] [NormedSpace ℝ D] @@ -1182,7 +1182,7 @@ instance instZeroAtInftyContinuousMapClass : ZeroAtInftyContinuousMapClass 𝓢( intro ε hε use (SchwartzMap.seminorm ℝ 1 0) f / ε intro x hx - rw [div_lt_iff hε] at hx + rw [div_lt_iff₀ hε] at hx have hxpos : 0 < ‖x‖ := by rw [norm_pos_iff'] intro hxzero @@ -1191,7 +1191,7 @@ instance instZeroAtInftyContinuousMapClass : ZeroAtInftyContinuousMapClass 𝓢( have := norm_pow_mul_le_seminorm ℝ f 1 x rw [pow_one, ← le_div_iff₀' hxpos] at this apply lt_of_le_of_lt this - rwa [div_lt_iff' hxpos] + rwa [div_lt_iff₀' hxpos] /-- Schwartz functions as continuous functions vanishing at infinity. -/ def toZeroAtInfty (f : 𝓢(E, F)) : C₀(E, F) where diff --git a/Mathlib/Analysis/Fourier/AddCircle.lean b/Mathlib/Analysis/Fourier/AddCircle.lean index 86ac394b06e8d..d162af7712aca 100644 --- a/Mathlib/Analysis/Fourier/AddCircle.lean +++ b/Mathlib/Analysis/Fourier/AddCircle.lean @@ -10,7 +10,7 @@ import Mathlib.MeasureTheory.Function.ContinuousMapDense import Mathlib.MeasureTheory.Function.L2Space import Mathlib.MeasureTheory.Group.Integral import Mathlib.MeasureTheory.Integral.Periodic -import Mathlib.Topology.ContinuousFunction.StoneWeierstrass +import Mathlib.Topology.ContinuousMap.StoneWeierstrass import Mathlib.MeasureTheory.Integral.FundThmCalculus /-! @@ -315,7 +315,7 @@ theorem fourierCoeffOn_eq_integral {a b : ℝ} (f : ℝ → E) (n : ℤ) (hab : rw [fourierCoeffOn, fourierCoeff_eq_intervalIntegral _ _ a, add_sub, add_sub_cancel_left] congr 1 simp_rw [intervalIntegral.integral_of_le hab.le] - refine setIntegral_congr measurableSet_Ioc fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioc fun x hx => ?_ rw [liftIoc_coe_apply] rwa [add_sub, add_sub_cancel_left] @@ -344,7 +344,7 @@ theorem fourierCoeff_liftIco_eq {a : ℝ} (f : ℝ → ℂ) (n : ℤ) : congr 1 simp_rw [intervalIntegral.integral_of_le (lt_add_of_pos_right a hT.out).le] iterate 2 rw [integral_Ioc_eq_integral_Ioo] - refine setIntegral_congr measurableSet_Ioo fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioo fun x hx => ?_ rw [liftIco_coe_apply (Ioo_subset_Ico_self hx)] end fourierCoeff diff --git a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean index e48a2caf91986..0fbe303edbe46 100644 --- a/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean +++ b/Mathlib/Analysis/Fourier/FourierTransformDeriv.lean @@ -413,7 +413,7 @@ lemma norm_iteratedFDeriv_fourierPowSMulRight · rw [← Nat.cast_pow, Nat.cast_le] calc n.descFactorial i ≤ n ^ i := Nat.descFactorial_le_pow _ _ _ ≤ (n + 1) ^ i := pow_le_pow_left (by omega) (by omega) i - _ ≤ (n + 1) ^ k := pow_le_pow_right (by omega) (Finset.mem_range_succ_iff.mp hi) + _ ≤ (n + 1) ^ k := pow_right_mono₀ (by omega) (Finset.mem_range_succ_iff.mp hi) · exact hv _ (by omega) _ (by omega) _ = (2 * n + 2) ^ k * (‖L‖^n * C) := by simp only [← Finset.sum_mul, ← Nat.cast_sum, Nat.sum_range_choose, mul_one, ← mul_assoc, @@ -627,7 +627,7 @@ lemma pow_mul_norm_iteratedFDeriv_fourierIntegral_le [FiniteDimensional ℝ V] _ ≤ (2 * π) ^ n * (|L v w| ^ n * ‖iteratedFDeriv ℝ k (fourierIntegral 𝐞 μ L.toLinearMap₂ f) w‖) := by apply le_mul_of_one_le_left (by positivity) - apply one_le_pow_of_one_le + apply one_le_pow₀ linarith [one_le_pi_div_two] _ = ‖fourierPowSMulRight (-L.flip) (iteratedFDeriv ℝ k (fourierIntegral 𝐞 μ L.toLinearMap₂ f)) w n (fun _ ↦ v)‖ := by diff --git a/Mathlib/Analysis/Fourier/Inversion.lean b/Mathlib/Analysis/Fourier/Inversion.lean index cea8c2f5ade12..158aae8391b20 100644 --- a/Mathlib/Analysis/Fourier/Inversion.lean +++ b/Mathlib/Analysis/Fourier/Inversion.lean @@ -37,7 +37,7 @@ To check the concentration property of the middle factor and the fact that it ha rely on the explicit computation of the Fourier transform of Gaussians. -/ -open Filter MeasureTheory Complex FiniteDimensional Metric Real Bornology +open Filter MeasureTheory Complex Module Metric Real Bornology open scoped Topology FourierTransform RealInnerProductSpace Complex diff --git a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean index 024a1e6a9ca37..1531edb4f4be0 100644 --- a/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean +++ b/Mathlib/Analysis/Fourier/RiemannLebesgueLemma.lean @@ -45,7 +45,7 @@ equivalence to an inner-product space. noncomputable section -open MeasureTheory Filter Complex Set FiniteDimensional +open MeasureTheory Filter Complex Set Module open scoped Filter Topology Real ENNReal FourierTransform RealInnerProductSpace NNReal @@ -140,7 +140,7 @@ theorem tendsto_integral_exp_inner_smul_cocompact_of_continuous_compact_support have : ‖(1 / 2 : ℂ)‖ = 2⁻¹ := by norm_num rw [fourierIntegral_eq_half_sub_half_period_translate hw_ne (hf1.integrable_of_hasCompactSupport hf2), - norm_smul, this, inv_mul_eq_div, div_lt_iff' two_pos] + norm_smul, this, inv_mul_eq_div, div_lt_iff₀' two_pos] refine lt_of_le_of_lt (norm_integral_le_integral_norm _) ?_ simp_rw [Circle.norm_smul] --* Show integral can be taken over A only. @@ -164,8 +164,8 @@ theorem tendsto_integral_exp_inner_smul_cocompact_of_continuous_compact_support simp_rw [norm_norm] simp_rw [dist_eq_norm] at hδ2 refine fun x _ => (hδ2 ?_).le - rw [sub_add_cancel_left, norm_neg, hw'_nm, ← div_div, div_lt_iff (norm_pos_iff.mpr hw_ne), ← - div_lt_iff' hδ1, div_div] + rw [sub_add_cancel_left, norm_neg, hw'_nm, ← div_div, div_lt_iff₀ (norm_pos_iff.mpr hw_ne), ← + div_lt_iff₀' hδ1, div_div] exact (lt_add_of_pos_left _ one_half_pos).trans_le hw_bd have bdA2 := norm_setIntegral_le_of_norm_le_const (hB_vol.trans_lt ENNReal.coe_lt_top) bdA ?_ swap @@ -177,7 +177,7 @@ theorem tendsto_integral_exp_inner_smul_cocompact_of_continuous_compact_support Real.norm_of_nonneg (setIntegral_nonneg mA fun x _ => norm_nonneg _) rw [this] at bdA2 refine bdA2.trans_lt ?_ - rw [div_mul_eq_mul_div, div_lt_iff (NNReal.coe_pos.mpr hB_pos), mul_comm (2 : ℝ), mul_assoc, + rw [div_mul_eq_mul_div, div_lt_iff₀ (NNReal.coe_pos.mpr hB_pos), mul_comm (2 : ℝ), mul_assoc, mul_lt_mul_left hε] rw [← ENNReal.toReal_le_toReal] at hB_vol · refine hB_vol.trans_lt ?_ diff --git a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean index 6b402f751dabd..8164bbd406fee 100644 --- a/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean +++ b/Mathlib/Analysis/FunctionalSpaces/SobolevInequality.lean @@ -349,7 +349,7 @@ theorem lintegral_pow_le_pow_lintegral_fderiv_aux [Fintype ι] variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [MeasurableSpace E] [BorelSpace E] [FiniteDimensional ℝ E] (μ : Measure E) [IsAddHaarMeasure μ] -open FiniteDimensional +open Module /-- The constant factor occurring in the conclusion of `lintegral_pow_le_pow_lintegral_fderiv`. It only depends on `E`, `μ` and `p`. @@ -489,7 +489,7 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq_inner {u : E → F'} have : 0 < p⁻¹ - (n : ℝ)⁻¹ := NNReal.coe_lt_coe.mpr (pos_iff_ne_zero.mpr (inv_ne_zero hp'0)) |>.trans_eq hp' rwa [NNReal.coe_inv, sub_pos, - inv_lt_inv _ (zero_lt_one.trans_le (NNReal.coe_le_coe.mpr hp))] at this + inv_lt_inv₀ _ (zero_lt_one.trans_le (NNReal.coe_le_coe.mpr hp))] at this exact_mod_cast hn have h0n : 2 ≤ n := Nat.succ_le_of_lt <| Nat.one_lt_cast.mp <| hp.trans_lt h2p have hn : NNReal.IsConjExponent n n' := .conjExponent (by norm_cast) @@ -514,7 +514,7 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_eq_inner {u : E → F'} have h0p' : p' ≠ 0 := by suffices 0 < (p' : ℝ) from (show 0 < p' from this) |>.ne' rw [← inv_pos, hp', sub_pos] - exact inv_lt_inv_of_lt hq.pos h2p + exact inv_strictAnti₀ hq.pos h2p have h2q : 1 / n' - 1 / q = 1 / p' := by simp_rw (config := {zeta := false}) [one_div, hp'] rw [← hq.one_sub_inv, ← hn.coe.one_sub_inv, sub_sub_sub_cancel_left] @@ -684,7 +684,7 @@ theorem eLpNorm_le_eLpNorm_fderiv_of_le [FiniteDimensional ℝ F] have : (q : ℝ≥0∞) ≤ p' := by have H : (p' : ℝ)⁻¹ ≤ (↑q)⁻¹ := trans hp' hpq norm_cast at H ⊢ - rwa [inv_le_inv] at H + rwa [inv_le_inv₀] at H · dsimp have : 0 < p⁻¹ - (finrank ℝ E : ℝ≥0)⁻¹ := by simp only [tsub_pos_iff_lt] diff --git a/Mathlib/Analysis/Hofer.lean b/Mathlib/Analysis/Hofer.lean index 3224c5efddfd7..8d5fda97eb89e 100644 --- a/Mathlib/Analysis/Hofer.lean +++ b/Mathlib/Analysis/Hofer.lean @@ -35,7 +35,7 @@ theorem hofer {X : Type*} [MetricSpace X] [CompleteSpace X] (x : X) (ε : ℝ) ( ∃ y, d x' y ≤ ε / 2 ^ k ∧ 2 * ϕ x' < ϕ y := by intro k x' push_neg at H - have := H (ε / 2 ^ k) (by positivity) x' (by simp [ε_pos.le, one_le_two]) + have := H (ε / 2 ^ k) (by positivity) x' (div_le_self ε_pos.le <| one_le_pow₀ one_le_two) simpa [reformulation] using this haveI : Nonempty X := ⟨x⟩ choose! F hF using H diff --git a/Mathlib/Analysis/InnerProductSpace/Basic.lean b/Mathlib/Analysis/InnerProductSpace/Basic.lean index aff60c1cd6250..1e37689bab1f9 100644 --- a/Mathlib/Analysis/InnerProductSpace/Basic.lean +++ b/Mathlib/Analysis/InnerProductSpace/Basic.lean @@ -548,8 +548,30 @@ theorem inner_re_symm (x y : E) : re ⟪x, y⟫ = re ⟪y, x⟫ := by rw [← in theorem inner_im_symm (x y : E) : im ⟪x, y⟫ = -im ⟪y, x⟫ := by rw [← inner_conj_symm, conj_im] +section Algebra +variable {𝕝 : Type*} [CommSemiring 𝕝] [StarRing 𝕝] [Algebra 𝕝 𝕜] [Module 𝕝 E] + [IsScalarTower 𝕝 𝕜 E] [StarModule 𝕝 𝕜] + +/-- See `inner_smul_left` for the common special when `𝕜 = 𝕝`. -/ +lemma inner_smul_left_eq_star_smul (x y : E) (r : 𝕝) : ⟪r • x, y⟫ = r† • ⟪x, y⟫ := by + rw [← algebraMap_smul 𝕜 r, InnerProductSpace.smul_left, starRingEnd_apply, starRingEnd_apply, + ← algebraMap_star_comm, ← smul_eq_mul, algebraMap_smul] + +/-- Special case of `inner_smul_left_eq_star_smul` when the acting ring has a trivial star +(eg `ℕ`, `ℤ`, `ℚ≥0`, `ℚ`, `ℝ`). -/ +lemma inner_smul_left_eq_smul [TrivialStar 𝕝] (x y : E) (r : 𝕝) : ⟪r • x, y⟫ = r • ⟪x, y⟫ := by + rw [inner_smul_left_eq_star_smul, starRingEnd_apply, star_trivial] + +/-- See `inner_smul_right` for the common special when `𝕜 = 𝕝`. -/ +lemma inner_smul_right_eq_smul (x y : E) (r : 𝕝) : ⟪x, r • y⟫ = r • ⟪x, y⟫ := by + rw [← inner_conj_symm, inner_smul_left_eq_star_smul, starRingEnd_apply, starRingEnd_apply, + star_smul, star_star, ← starRingEnd_apply, inner_conj_symm] + +end Algebra + +/-- See `inner_smul_left_eq_star_smul` for the case of a general algebra action. -/ theorem inner_smul_left (x y : E) (r : 𝕜) : ⟪r • x, y⟫ = r† * ⟪x, y⟫ := - InnerProductSpace.smul_left _ _ _ + inner_smul_left_eq_star_smul .. theorem real_inner_smul_left (x y : F) (r : ℝ) : ⟪r • x, y⟫_ℝ = r * ⟪x, y⟫_ℝ := inner_smul_left _ _ _ @@ -557,8 +579,9 @@ theorem real_inner_smul_left (x y : F) (r : ℝ) : ⟪r • x, y⟫_ℝ = r * theorem inner_smul_real_left (x y : E) (r : ℝ) : ⟪(r : 𝕜) • x, y⟫ = r • ⟪x, y⟫ := by rw [inner_smul_left, conj_ofReal, Algebra.smul_def] -theorem inner_smul_right (x y : E) (r : 𝕜) : ⟪x, r • y⟫ = r * ⟪x, y⟫ := by - rw [← inner_conj_symm, inner_smul_left, RingHom.map_mul, conj_conj, inner_conj_symm] +/-- See `inner_smul_right_eq_smul` for the case of a general algebra action. -/ +theorem inner_smul_right (x y : E) (r : 𝕜) : ⟪x, r • y⟫ = r * ⟪x, y⟫ := + inner_smul_right_eq_smul .. theorem real_inner_smul_right (x y : F) (r : ℝ) : ⟪x, r • y⟫_ℝ = r * ⟪x, y⟫_ℝ := inner_smul_right _ _ _ @@ -990,7 +1013,7 @@ theorem exists_maximal_orthonormal {s : Set E} (hs : Orthonormal 𝕜 (Subtype.v · exact orthonormal_sUnion_of_directed cc.directedOn fun x xc => hc xc · exact fun _ => Set.subset_sUnion_of_mem -open FiniteDimensional +open Module /-- A family of orthonormal vectors with the correct cardinality forms a basis. -/ def basisOfOrthonormalOfCardEqFinrank [Fintype ι] [Nonempty ι] {v : ι → E} (hv : Orthonormal 𝕜 v) @@ -1003,27 +1026,12 @@ theorem coe_basisOfOrthonormalOfCardEqFinrank [Fintype ι] [Nonempty ι] {v : ι (basisOfOrthonormalOfCardEqFinrank hv card_eq : ι → E) = v := coe_basisOfLinearIndependentOfCardEqFinrank _ _ -end OrthonormalSets_Seminormed - -section OrthonormalSets - -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] -variable [NormedAddCommGroup F] [InnerProductSpace ℝ F] -variable {ι : Type*} - -local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y - -local notation "IK" => @RCLike.I 𝕜 _ - -local postfix:90 "†" => starRingEnd _ - theorem Orthonormal.ne_zero {v : ι → E} (hv : Orthonormal 𝕜 v) (i : ι) : v i ≠ 0 := by - have : ‖v i‖ ≠ 0 := by - rw [hv.1 i] - norm_num - simpa using this + refine ne_of_apply_ne norm ?_ + rw [hv.1 i, norm_zero] + norm_num -end OrthonormalSets +end OrthonormalSets_Seminormed section Norm_Seminormed @@ -1198,9 +1206,9 @@ instance (priority := 100) InnerProductSpace.toUniformConvexSpace : UniformConve ring_nf exact sub_le_sub_left (pow_le_pow_left hε.le hxy _) 4⟩ -section Complex +section Complex_Seminormed -variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] +variable {V : Type*} [SeminormedAddCommGroup V] [InnerProductSpace ℂ V] /-- A complex polarization identity, with a linear map -/ @@ -1226,6 +1234,12 @@ theorem inner_map_polarization' (T : V →ₗ[ℂ] V) (x y : V) : mul_add, ← mul_assoc, mul_neg, neg_neg, sub_neg_eq_add, one_mul, neg_one_mul, mul_sub, sub_sub] ring +end Complex_Seminormed + +section Complex + +variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] + /-- A linear map `T` is zero, if and only if the identity `⟪T x, x⟫_ℂ = 0` holds for all `x`. -/ theorem inner_map_self_eq_zero (T : V →ₗ[ℂ] V) : (∀ x : V, ⟪T x, x⟫_ℂ = 0) ↔ T = 0 := by @@ -1481,7 +1495,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) (by positivity) + exact div_le_one_of_le₀ (abs_real_inner_le_norm x y) (by positivity) /-- The inner product of a vector with a multiple of itself. -/ theorem real_inner_smul_self_left (x : F) (r : ℝ) : ⟪r • x, x⟫_ℝ = r * (‖x‖ * ‖x‖) := by @@ -1551,7 +1565,7 @@ variable {𝕜} namespace ContinuousLinearMap -variable {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] +variable {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] -- Note: odd and expensive build behavior is explicitly turned off using `noncomputable` /-- Given `f : E →L[𝕜] E'`, construct the continuous sesquilinear form `fun x y ↦ ⟪x, A y⟫`, given @@ -1576,6 +1590,83 @@ theorem toSesqForm_apply_norm_le {f : E →L[𝕜] E'} {v : E'} : ‖toSesqForm end ContinuousLinearMap +section + +variable {ι : Type*} {ι' : Type*} {ι'' : Type*} +variable {E' : Type*} [SeminormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] +variable {E'' : Type*} [SeminormedAddCommGroup E''] [InnerProductSpace 𝕜 E''] + +@[simp] +theorem Orthonormal.equiv_refl {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) : + hv.equiv hv (Equiv.refl ι) = LinearIsometryEquiv.refl 𝕜 E := + v.ext_linearIsometryEquiv fun i => by + simp only [Orthonormal.equiv_apply, Equiv.coe_refl, id, LinearIsometryEquiv.coe_refl] + +@[simp] +theorem Orthonormal.equiv_symm {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) {v' : Basis ι' 𝕜 E'} + (hv' : Orthonormal 𝕜 v') (e : ι ≃ ι') : (hv.equiv hv' e).symm = hv'.equiv hv e.symm := + v'.ext_linearIsometryEquiv fun i => + (hv.equiv hv' e).injective <| by + simp only [LinearIsometryEquiv.apply_symm_apply, Orthonormal.equiv_apply, e.apply_symm_apply] + +end + +variable (𝕜) + +/-- `innerSL` is an isometry. Note that the associated `LinearIsometry` is defined in +`InnerProductSpace.Dual` as `toDualMap`. -/ +@[simp] +theorem innerSL_apply_norm (x : E) : ‖innerSL 𝕜 x‖ = ‖x‖ := by + refine + le_antisymm ((innerSL 𝕜 x).opNorm_le_bound (norm_nonneg _) fun y => norm_inner_le_norm _ _) ?_ + rcases (norm_nonneg x).eq_or_gt with (h | h) + · simp [h] + · refine (mul_le_mul_right h).mp ?_ + calc + ‖x‖ * ‖x‖ = ‖(⟪x, x⟫ : 𝕜)‖ := by + rw [← sq, inner_self_eq_norm_sq_to_K, norm_pow, norm_ofReal, abs_norm] + _ ≤ ‖innerSL 𝕜 x‖ * ‖x‖ := (innerSL 𝕜 x).le_opNorm _ + +lemma norm_innerSL_le : ‖innerSL 𝕜 (E := E)‖ ≤ 1 := + ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp) + +variable {𝕜} + +/-- When an inner product space `E` over `𝕜` is considered as a real normed space, its inner +product satisfies `IsBoundedBilinearMap`. + +In order to state these results, we need a `NormedSpace ℝ E` instance. We will later establish +such an instance by restriction-of-scalars, `InnerProductSpace.rclikeToReal 𝕜 E`, but this +instance may be not definitionally equal to some other “natural” instance. So, we assume +`[NormedSpace ℝ E]`. +-/ +theorem _root_.isBoundedBilinearMap_inner [NormedSpace ℝ E] [IsScalarTower ℝ 𝕜 E] : + IsBoundedBilinearMap ℝ fun p : E × E => ⟪p.1, p.2⟫ := + { add_left := inner_add_left + smul_left := fun r x y => by + simp only [← algebraMap_smul 𝕜 r x, algebraMap_eq_ofReal, inner_smul_real_left] + add_right := inner_add_right + smul_right := fun r x y => by + simp only [← algebraMap_smul 𝕜 r y, algebraMap_eq_ofReal, inner_smul_real_right] + bound := + ⟨1, zero_lt_one, fun x y => by + rw [one_mul] + exact norm_inner_le_norm x y⟩ } + +/-- The inner product of two weighted sums, where the weights in each +sum add to 0, in terms of the norms of pairwise differences. -/ +theorem inner_sum_smul_sum_smul_of_sum_eq_zero {ι₁ : Type*} {s₁ : Finset ι₁} {w₁ : ι₁ → ℝ} + (v₁ : ι₁ → F) (h₁ : ∑ i ∈ s₁, w₁ i = 0) {ι₂ : Type*} {s₂ : Finset ι₂} {w₂ : ι₂ → ℝ} + (v₂ : ι₂ → F) (h₂ : ∑ i ∈ s₂, w₂ i = 0) : + ⟪∑ i₁ ∈ s₁, w₁ i₁ • v₁ i₁, ∑ i₂ ∈ s₂, w₂ i₂ • v₂ i₂⟫_ℝ = + (-∑ i₁ ∈ s₁, ∑ i₂ ∈ s₂, w₁ i₁ * w₂ i₂ * (‖v₁ i₁ - v₂ i₂‖ * ‖v₁ i₁ - v₂ i₂‖)) / 2 := by + simp_rw [sum_inner, inner_sum, real_inner_smul_left, real_inner_smul_right, + real_inner_eq_norm_mul_self_add_norm_mul_self_sub_norm_sub_mul_self_div_two, ← div_sub_div_same, + ← div_add_div_same, mul_sub_left_distrib, left_distrib, Finset.sum_sub_distrib, + Finset.sum_add_distrib, ← Finset.mul_sum, ← Finset.sum_mul, h₁, h₂, zero_mul, + mul_zero, Finset.sum_const_zero, zero_add, zero_sub, Finset.mul_sum, neg_div, + Finset.sum_div, mul_div_assoc, mul_assoc] + end Norm_Seminormed section Norm @@ -1611,27 +1702,6 @@ theorem dist_div_norm_sq_smul {x y : F} (hx : x ≠ 0) (hy : y ≠ 0) (R : ℝ) _ = R ^ 2 / (‖x‖ * ‖y‖) * dist x y := by rw [sqrt_mul, sqrt_sq, sqrt_sq, dist_eq_norm] <;> positivity -section - -variable {ι : Type*} {ι' : Type*} {ι'' : Type*} -variable {E' : Type*} [NormedAddCommGroup E'] [InnerProductSpace 𝕜 E'] -variable {E'' : Type*} [NormedAddCommGroup E''] [InnerProductSpace 𝕜 E''] - -@[simp] -theorem Orthonormal.equiv_refl {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) : - hv.equiv hv (Equiv.refl ι) = LinearIsometryEquiv.refl 𝕜 E := - v.ext_linearIsometryEquiv fun i => by - simp only [Orthonormal.equiv_apply, Equiv.coe_refl, id, LinearIsometryEquiv.coe_refl] - -@[simp] -theorem Orthonormal.equiv_symm {v : Basis ι 𝕜 E} (hv : Orthonormal 𝕜 v) {v' : Basis ι' 𝕜 E'} - (hv' : Orthonormal 𝕜 v') (e : ι ≃ ι') : (hv.equiv hv' e).symm = hv'.equiv hv e.symm := - v'.ext_linearIsometryEquiv fun i => - (hv.equiv hv' e).injective <| by - simp only [LinearIsometryEquiv.apply_symm_apply, Orthonormal.equiv_apply, e.apply_symm_apply] - -end - /-- The inner product of a nonzero vector with a nonzero multiple of itself, divided by the product of their norms, has absolute value 1. -/ @@ -1804,62 +1874,6 @@ theorem eq_of_norm_le_re_inner_eq_norm_sq {x y : E} (hle : ‖x‖ ≤ ‖y‖) have H₂ : re ⟪y, x⟫ = ‖y‖ ^ 2 := by rwa [← inner_conj_symm, conj_re] simpa [inner_sub_left, inner_sub_right, ← norm_sq_eq_inner, h, H₂] using H₁ -/-- The inner product of two weighted sums, where the weights in each -sum add to 0, in terms of the norms of pairwise differences. -/ -theorem inner_sum_smul_sum_smul_of_sum_eq_zero {ι₁ : Type*} {s₁ : Finset ι₁} {w₁ : ι₁ → ℝ} - (v₁ : ι₁ → F) (h₁ : ∑ i ∈ s₁, w₁ i = 0) {ι₂ : Type*} {s₂ : Finset ι₂} {w₂ : ι₂ → ℝ} - (v₂ : ι₂ → F) (h₂ : ∑ i ∈ s₂, w₂ i = 0) : - ⟪∑ i₁ ∈ s₁, w₁ i₁ • v₁ i₁, ∑ i₂ ∈ s₂, w₂ i₂ • v₂ i₂⟫_ℝ = - (-∑ i₁ ∈ s₁, ∑ i₂ ∈ s₂, w₁ i₁ * w₂ i₂ * (‖v₁ i₁ - v₂ i₂‖ * ‖v₁ i₁ - v₂ i₂‖)) / 2 := by - simp_rw [sum_inner, inner_sum, real_inner_smul_left, real_inner_smul_right, - real_inner_eq_norm_mul_self_add_norm_mul_self_sub_norm_sub_mul_self_div_two, ← div_sub_div_same, - ← div_add_div_same, mul_sub_left_distrib, left_distrib, Finset.sum_sub_distrib, - Finset.sum_add_distrib, ← Finset.mul_sum, ← Finset.sum_mul, h₁, h₂, zero_mul, - mul_zero, Finset.sum_const_zero, zero_add, zero_sub, Finset.mul_sum, neg_div, - Finset.sum_div, mul_div_assoc, mul_assoc] - -variable (𝕜) - -/-- `innerSL` is an isometry. Note that the associated `LinearIsometry` is defined in -`InnerProductSpace.Dual` as `toDualMap`. -/ -@[simp] -theorem innerSL_apply_norm (x : E) : ‖innerSL 𝕜 x‖ = ‖x‖ := by - refine - le_antisymm ((innerSL 𝕜 x).opNorm_le_bound (norm_nonneg _) fun y => norm_inner_le_norm _ _) ?_ - rcases eq_or_ne x 0 with (rfl | h) - · simp - · refine (mul_le_mul_right (norm_pos_iff.2 h)).mp ?_ - calc - ‖x‖ * ‖x‖ = ‖(⟪x, x⟫ : 𝕜)‖ := by - rw [← sq, inner_self_eq_norm_sq_to_K, norm_pow, norm_ofReal, abs_norm] - _ ≤ ‖innerSL 𝕜 x‖ * ‖x‖ := (innerSL 𝕜 x).le_opNorm _ - -lemma norm_innerSL_le : ‖innerSL 𝕜 (E := E)‖ ≤ 1 := - ContinuousLinearMap.opNorm_le_bound _ zero_le_one (by simp) - -variable {𝕜} - -/-- When an inner product space `E` over `𝕜` is considered as a real normed space, its inner -product satisfies `IsBoundedBilinearMap`. - -In order to state these results, we need a `NormedSpace ℝ E` instance. We will later establish -such an instance by restriction-of-scalars, `InnerProductSpace.rclikeToReal 𝕜 E`, but this -instance may be not definitionally equal to some other “natural” instance. So, we assume -`[NormedSpace ℝ E]`. --/ -theorem _root_.isBoundedBilinearMap_inner [NormedSpace ℝ E] : - IsBoundedBilinearMap ℝ fun p : E × E => ⟪p.1, p.2⟫ := - { add_left := inner_add_left - smul_left := fun r x y => by - simp only [← algebraMap_smul 𝕜 r x, algebraMap_eq_ofReal, inner_smul_real_left] - add_right := inner_add_right - smul_right := fun r x y => by - simp only [← algebraMap_smul 𝕜 r y, algebraMap_eq_ofReal, inner_smul_real_right] - bound := - ⟨1, zero_lt_one, fun x y => by - rw [one_mul] - exact norm_inner_le_norm x y⟩ } - end Norm section BesselsInequality @@ -2268,7 +2282,7 @@ end RCLikeToReal section Continuous -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2283,6 +2297,7 @@ local postfix:90 "†" => starRingEnd _ theorem continuous_inner : Continuous fun p : E × E => ⟪p.1, p.2⟫ := letI : InnerProductSpace ℝ E := InnerProductSpace.rclikeToReal 𝕜 E + letI : IsScalarTower ℝ 𝕜 E := RestrictScalars.isScalarTower _ _ _ isBoundedBilinearMap_inner.continuous variable {α : Type*} @@ -2333,7 +2348,7 @@ end ReApplyInnerSelf section ReApplyInnerSelf_Seminormed -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2353,9 +2368,36 @@ theorem ContinuousLinearMap.reApplyInnerSelf_smul (T : E →L[𝕜] E) (x : E) { end ReApplyInnerSelf_Seminormed +section SeparationQuotient +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] + +theorem Inseparable.inner_eq_inner {x₁ x₂ y₁ y₂ : E} + (hx : Inseparable x₁ x₂) (hy : Inseparable y₁ y₂) : + inner x₁ y₁ = (inner x₂ y₂ : 𝕜) := + ((hx.prod hy).map continuous_inner).eq + +namespace SeparationQuotient + +instance : Inner 𝕜 (SeparationQuotient E) where + inner := SeparationQuotient.lift₂ Inner.inner fun _ _ _ _ => Inseparable.inner_eq_inner + +@[simp] +theorem inner_mk_mk (x y : E) : + inner (mk x) (mk y) = (inner x y : 𝕜) := rfl + +instance : InnerProductSpace 𝕜 (SeparationQuotient E) where + norm_sq_eq_inner := Quotient.ind norm_sq_eq_inner + conj_symm := Quotient.ind₂ inner_conj_symm + add_left := Quotient.ind fun x => Quotient.ind₂ <| inner_add_left x + smul_left := Quotient.ind₂ inner_smul_left + +end SeparationQuotient + +end SeparationQuotient + section UniformSpace.Completion -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -2369,11 +2411,11 @@ open UniformSpace Function instance toInner {𝕜' E' : Type*} [TopologicalSpace 𝕜'] [UniformSpace E'] [Inner 𝕜' E'] : Inner 𝕜' (Completion E') where - inner := curry <| (denseInducing_coe.prod denseInducing_coe).extend (uncurry inner) + inner := curry <| (isDenseInducing_coe.prodMap isDenseInducing_coe).extend (uncurry inner) @[simp] theorem inner_coe (a b : E) : inner (a : Completion E) (b : Completion E) = (inner a b : 𝕜) := - (denseInducing_coe.prod denseInducing_coe).extend_eq + (isDenseInducing_coe.prodMap isDenseInducing_coe).extend_eq (continuous_inner : Continuous (uncurry inner : E × E → 𝕜)) (a, b) protected theorem continuous_inner : @@ -2386,9 +2428,9 @@ protected theorem continuous_inner : rw [Completion.toInner, inner, uncurry_curry _] change Continuous - (((denseInducing_toCompl E).prod (denseInducing_toCompl E)).extend fun p : E × E => + (((isDenseInducing_toCompl E).prodMap (isDenseInducing_toCompl E)).extend fun p : E × E => inner' p.1 p.2) - exact (denseInducing_toCompl E).extend_Z_bilin (denseInducing_toCompl E) this + exact (isDenseInducing_toCompl E).extend_Z_bilin (isDenseInducing_toCompl E) this protected theorem Continuous.inner {α : Type*} [TopologicalSpace α] {f g : α → Completion E} (hf : Continuous f) (hg : Continuous g) : Continuous (fun x : α => inner (f x) (g x) : α → 𝕜) := diff --git a/Mathlib/Analysis/InnerProductSpace/Dual.lean b/Mathlib/Analysis/InnerProductSpace/Dual.lean index e6af204a8c575..58aba1f6281ae 100644 --- a/Mathlib/Analysis/InnerProductSpace/Dual.lean +++ b/Mathlib/Analysis/InnerProductSpace/Dual.lean @@ -45,8 +45,10 @@ namespace InnerProductSpace open RCLike ContinuousLinearMap -variable (𝕜 : Type*) -variable (E : Type*) [RCLike 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable (𝕜 E : Type*) + +section Seminormed +variable [RCLike 𝕜] [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] local notation "⟪" x ", " y "⟫" => @inner 𝕜 E _ x y @@ -67,10 +69,19 @@ variable {E} theorem toDualMap_apply {x y : E} : toDualMap 𝕜 E x y = ⟪x, y⟫ := rfl +end Seminormed + +section Normed +variable [RCLike 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] + +local notation "⟪" x ", " y "⟫" => @inner 𝕜 E _ x y + +local postfix:90 "†" => starRingEnd _ + theorem innerSL_norm [Nontrivial E] : ‖(innerSL 𝕜 : E →L⋆[𝕜] E →L[𝕜] 𝕜)‖ = 1 := show ‖(toDualMap 𝕜 E).toContinuousLinearMap‖ = 1 from LinearIsometry.norm_toContinuousLinearMap _ -variable {𝕜} +variable {E 𝕜} theorem ext_inner_left_basis {ι : Type*} {x y : E} (b : Basis ι 𝕜 E) (h : ∀ i : ι, ⟪b i, x⟫ = ⟪b i, y⟫) : x = y := by @@ -170,4 +181,6 @@ theorem unique_continuousLinearMapOfBilin {v f : E} (is_lax_milgram : ∀ w, ⟪ rw [continuousLinearMapOfBilin_apply] exact is_lax_milgram w +end Normed + end InnerProductSpace diff --git a/Mathlib/Analysis/InnerProductSpace/EuclideanDist.lean b/Mathlib/Analysis/InnerProductSpace/EuclideanDist.lean index 69889f1ed8e41..50173dd6a64c2 100644 --- a/Mathlib/Analysis/InnerProductSpace/EuclideanDist.lean +++ b/Mathlib/Analysis/InnerProductSpace/EuclideanDist.lean @@ -29,7 +29,7 @@ variable {E : Type*} [AddCommGroup E] [TopologicalSpace E] [TopologicalAddGroup noncomputable section -open FiniteDimensional +open Module /-- If `E` is a finite dimensional space over `ℝ`, then `toEuclidean` is a continuous `ℝ`-linear equivalence between `E` and the Euclidean space of the same dimension. -/ diff --git a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean index a3c9277c121f4..b0351cdc69d46 100644 --- a/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean +++ b/Mathlib/Analysis/InnerProductSpace/GramSchmidtOrtho.lean @@ -35,7 +35,7 @@ and outputs a set of orthogonal vectors which have the same span. -/ -open Finset Submodule FiniteDimensional +open Finset Submodule Module variable (𝕜 : Type*) {E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] variable {ι : Type*} [LinearOrder ι] [LocallyFiniteOrderBot ι] [IsWellOrder ι (· < ·)] diff --git a/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean index 868496a0b3462..049ba1532a238 100644 --- a/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean +++ b/Mathlib/Analysis/InnerProductSpace/JointEigenspace.lean @@ -49,7 +49,7 @@ variable {α : 𝕜} {A B : E →ₗ[𝕜] E} theorem eigenspace_invariant_of_commute (hAB : A ∘ₗ B = B ∘ₗ A) (α : 𝕜) : ∀ v ∈ (eigenspace A α), (B v ∈ eigenspace A α) := by intro v hv - rw [eigenspace, mem_ker, sub_apply, Module.algebraMap_end_apply, ← comp_apply A B v, hAB, + rw [eigenspace_def, mem_ker, sub_apply, smul_apply, one_apply, ← comp_apply A B v, hAB, comp_apply B A v, ← map_smul, ← map_sub, hv, map_zero] at * /--The simultaneous eigenspaces of a pair of commuting symmetric operators form an diff --git a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean index 7ac440395d2e8..9aa623e738fae 100644 --- a/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean +++ b/Mathlib/Analysis/InnerProductSpace/LaxMilgram.lean @@ -64,7 +64,7 @@ theorem antilipschitz (coercive : IsCoercive B) : ∃ C : ℝ≥0, 0 < C ∧ Ant refine ⟨C⁻¹.toNNReal, Real.toNNReal_pos.mpr (inv_pos.mpr C_pos), ?_⟩ refine ContinuousLinearMap.antilipschitz_of_bound B♯ ?_ simp_rw [Real.coe_toNNReal', max_eq_left_of_lt (inv_pos.mpr C_pos), ← - inv_mul_le_iff (inv_pos.mpr C_pos)] + inv_mul_le_iff₀ (inv_pos.mpr C_pos)] simpa using below_bound theorem ker_eq_bot (coercive : IsCoercive B) : ker B♯ = ⊥ := by diff --git a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean index 4fa2bc6e39428..13396afdb97d0 100644 --- a/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean +++ b/Mathlib/Analysis/InnerProductSpace/LinearPMap.lean @@ -103,7 +103,7 @@ variable (hT : Dense (T.domain : Set E)) /-- The unique continuous extension of the operator `adjointDomainMkCLM` to `E`. -/ def adjointDomainMkCLMExtend (y : T.adjointDomain) : E →L[𝕜] 𝕜 := (T.adjointDomainMkCLM y).extend (Submodule.subtypeL T.domain) hT.denseRange_val - uniformEmbedding_subtype_val.toUniformInducing + isUniformEmbedding_subtype_val.isUniformInducing @[simp] theorem adjointDomainMkCLMExtend_apply (y : T.adjointDomain) (x : T.domain) : diff --git a/Mathlib/Analysis/InnerProductSpace/OfNorm.lean b/Mathlib/Analysis/InnerProductSpace/OfNorm.lean index 2616c07526d0b..e2e23c0b46a9d 100644 --- a/Mathlib/Analysis/InnerProductSpace/OfNorm.lean +++ b/Mathlib/Analysis/InnerProductSpace/OfNorm.lean @@ -5,6 +5,8 @@ Authors: Heather Macbeth -/ import Mathlib.Topology.Algebra.Algebra import Mathlib.Analysis.InnerProductSpace.Basic +import Mathlib.Algebra.Module.LinearMap.Rat +import Mathlib.Tactic.Module /-! # Inner product space derived from a norm @@ -97,199 +99,118 @@ private def innerProp' (r : 𝕜) : Prop := variable {E} -theorem innerProp_neg_one : innerProp' E ((-1 : ℤ) : 𝕜) := by - intro x y - simp only [inner_, neg_mul_eq_neg_mul, one_mul, Int.cast_one, one_smul, RingHom.map_one, map_neg, - Int.cast_neg, neg_smul, neg_one_mul] - rw [neg_mul_comm] - congr 1 - have h₁ : ‖-x - y‖ = ‖x + y‖ := by rw [← neg_add', norm_neg] - have h₂ : ‖-x + y‖ = ‖x - y‖ := by rw [← neg_sub, norm_neg, sub_eq_neg_add] - have h₃ : ‖(I : 𝕜) • -x + y‖ = ‖(I : 𝕜) • x - y‖ := by - rw [← neg_sub, norm_neg, sub_eq_neg_add, ← smul_neg] - have h₄ : ‖(I : 𝕜) • -x - y‖ = ‖(I : 𝕜) • x + y‖ := by rw [smul_neg, ← neg_add', norm_neg] - rw [h₁, h₂, h₃, h₄] - ring - theorem _root_.Continuous.inner_ {f g : ℝ → E} (hf : Continuous f) (hg : Continuous g) : Continuous fun x => inner_ 𝕜 (f x) (g x) := by - unfold inner_ + unfold _root_.inner_ fun_prop theorem inner_.norm_sq (x : E) : ‖x‖ ^ 2 = re (inner_ 𝕜 x x) := by - simp only [inner_] - have h₁ : RCLike.normSq (4 : 𝕜) = 16 := by - have : ((4 : ℝ) : 𝕜) = (4 : 𝕜) := by norm_cast - rw [← this, normSq_eq_def', RCLike.norm_of_nonneg (by norm_num : (0 : ℝ) ≤ 4)] - norm_num - have h₂ : ‖x + x‖ = 2 * ‖x‖ := by rw [← two_smul 𝕜, norm_smul, RCLike.norm_two] - simp only [h₁, h₂, algebraMap_eq_ofReal, sub_self, norm_zero, mul_re, inv_re, ofNat_re, map_sub, - map_add, ofReal_re, ofNat_im, ofReal_im, mul_im, I_re, inv_im] + simp only [inner_, normSq_apply, ofNat_re, ofNat_im, map_sub, map_add, map_zero, map_mul, + ofReal_re, ofReal_im, mul_re, inv_re, mul_im, I_re, inv_im] + have h₁ : ‖x - x‖ = 0 := by simp + have h₂ : ‖x + x‖ = 2 • ‖x‖ := by convert norm_nsmul 𝕜 2 x using 2; module + rw [h₁, h₂] ring -attribute [local simp] map_ofNat in -- use `ofNat` simp theorem with bad keys theorem inner_.conj_symm (x y : E) : conj (inner_ 𝕜 y x) = inner_ 𝕜 x y := by - simp only [inner_] - have h4 : conj (4⁻¹ : 𝕜) = 4⁻¹ := by norm_num - rw [map_mul, h4] - congr 1 - simp only [map_sub, map_add, conj_ofReal, map_mul, conj_I] + simp only [inner_, map_sub, map_add, map_mul, map_inv₀, map_ofNat, conj_ofReal, conj_I] rw [add_comm y x, norm_sub_rev] by_cases hI : (I : 𝕜) = 0 · simp only [hI, neg_zero, zero_mul] - -- Porting note: this replaces `norm_I_of_ne_zero` which does not exist in Lean 4 - have : ‖(I : 𝕜)‖ = 1 := by - rw [← mul_self_inj_of_nonneg (norm_nonneg I) zero_le_one, one_mul, ← norm_mul, - I_mul_I_of_nonzero hI, norm_neg, norm_one] + have hI' := I_mul_I_of_nonzero hI + have I_smul (v : E) : ‖(I : 𝕜) • v‖ = ‖v‖ := by rw [norm_smul, norm_I_of_ne_zero hI, one_mul] have h₁ : ‖(I : 𝕜) • y - x‖ = ‖(I : 𝕜) • x + y‖ := by - trans ‖(I : 𝕜) • ((I : 𝕜) • y - x)‖ - · rw [norm_smul, this, one_mul] - · rw [smul_sub, smul_smul, I_mul_I_of_nonzero hI, neg_one_smul, ← neg_add', add_comm, norm_neg] + convert I_smul ((I : 𝕜) • x + y) using 2 + linear_combination (norm := module) congr(-$hI' • x) have h₂ : ‖(I : 𝕜) • y + x‖ = ‖(I : 𝕜) • x - y‖ := by - trans ‖(I : 𝕜) • ((I : 𝕜) • y + x)‖ - · rw [norm_smul, this, one_mul] - · rw [smul_add, smul_smul, I_mul_I_of_nonzero hI, neg_one_smul, ← neg_add_eq_sub] - rw [h₁, h₂, ← sub_add_eq_add_sub] - simp only [neg_mul, sub_eq_add_neg, neg_neg] + convert (I_smul ((I : 𝕜) • y + x)).symm using 2 + linear_combination (norm := module) congr(-$hI' • y) + rw [h₁, h₂] + ring variable [InnerProductSpaceable E] -private theorem add_left_aux1 (x y z : E) : ‖x + y + z‖ * ‖x + y + z‖ = - (‖2 • x + y‖ * ‖2 • x + y‖ + ‖2 • z + y‖ * ‖2 • z + y‖) / 2 - ‖x - z‖ * ‖x - z‖ := by - rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm] - convert parallelogram_identity (x + y + z) (x - z) using 4 <;> · rw [two_smul]; abel - -private theorem add_left_aux2 (x y z : E) : ‖x + y - z‖ * ‖x + y - z‖ = - (‖2 • x + y‖ * ‖2 • x + y‖ + ‖y - 2 • z‖ * ‖y - 2 • z‖) / 2 - ‖x + z‖ * ‖x + z‖ := by - rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm] - have h₀ := parallelogram_identity (x + y - z) (x + z) - convert h₀ using 4 <;> · rw [two_smul]; abel +private theorem add_left_aux1 (x y z : E) : + ‖2 • x + y‖ * ‖2 • x + y‖ + ‖2 • z + y‖ * ‖2 • z + y‖ + = 2 * (‖x + y + z‖ * ‖x + y + z‖ + ‖x - z‖ * ‖x - z‖) := by + convert parallelogram_identity (x + y + z) (x - z) using 4 <;> abel -private theorem add_left_aux2' (x y z : E) : - ‖x + y + z‖ * ‖x + y + z‖ - ‖x + y - z‖ * ‖x + y - z‖ = - ‖x + z‖ * ‖x + z‖ - ‖x - z‖ * ‖x - z‖ + - (‖2 • z + y‖ * ‖2 • z + y‖ - ‖y - 2 • z‖ * ‖y - 2 • z‖) / 2 := by - rw [add_left_aux1, add_left_aux2]; ring +private theorem add_left_aux2 (x y z : E) : ‖2 • x + y‖ * ‖2 • x + y‖ + ‖y - 2 • z‖ * ‖y - 2 • z‖ + = 2 * (‖x + y - z‖ * ‖x + y - z‖ + ‖x + z‖ * ‖x + z‖) := by + convert parallelogram_identity (x + y - z) (x + z) using 4 <;> abel private theorem add_left_aux3 (y z : E) : - ‖2 • z + y‖ * ‖2 • z + y‖ = 2 * (‖y + z‖ * ‖y + z‖ + ‖z‖ * ‖z‖) - ‖y‖ * ‖y‖ := by - apply eq_sub_of_add_eq - convert parallelogram_identity (y + z) z using 4 <;> (try rw [two_smul]) <;> abel + ‖2 • z + y‖ * ‖2 • z + y‖ + ‖y‖ * ‖y‖ = 2 * (‖y + z‖ * ‖y + z‖ + ‖z‖ * ‖z‖) := by + convert parallelogram_identity (y + z) z using 4 <;> abel private theorem add_left_aux4 (y z : E) : - ‖y - 2 • z‖ * ‖y - 2 • z‖ = 2 * (‖y - z‖ * ‖y - z‖ + ‖z‖ * ‖z‖) - ‖y‖ * ‖y‖ := by - apply eq_sub_of_add_eq' - have h₀ := parallelogram_identity (y - z) z - convert h₀ using 4 <;> (try rw [two_smul]) <;> abel + ‖y‖ * ‖y‖ + ‖y - 2 • z‖ * ‖y - 2 • z‖ = 2 * (‖y - z‖ * ‖y - z‖ + ‖z‖ * ‖z‖) := by + convert parallelogram_identity (y - z) z using 4 <;> abel -private theorem add_left_aux4' (y z : E) : - (‖2 • z + y‖ * ‖2 • z + y‖ - ‖y - 2 • z‖ * ‖y - 2 • z‖) / 2 = - ‖y + z‖ * ‖y + z‖ - ‖y - z‖ * ‖y - z‖ := by - rw [add_left_aux3, add_left_aux4]; ring +variable (𝕜) private theorem add_left_aux5 (x y z : E) : - ‖(I : 𝕜) • (x + y) + z‖ * ‖(I : 𝕜) • (x + y) + z‖ = - (‖(I : 𝕜) • (2 • x + y)‖ * ‖(I : 𝕜) • (2 • x + y)‖ + - ‖(I : 𝕜) • y + 2 • z‖ * ‖(I : 𝕜) • y + 2 • z‖) / 2 - - ‖(I : 𝕜) • x - z‖ * ‖(I : 𝕜) • x - z‖ := by - rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm] - have h₀ := parallelogram_identity ((I : 𝕜) • (x + y) + z) ((I : 𝕜) • x - z) - convert h₀ using 4 <;> · try simp only [two_smul, smul_add]; abel + ‖(I : 𝕜) • (2 • x + y)‖ * ‖(I : 𝕜) • (2 • x + y)‖ + + ‖(I : 𝕜) • y + 2 • z‖ * ‖(I : 𝕜) • y + 2 • z‖ + = 2 * (‖(I : 𝕜) • (x + y) + z‖ * ‖(I : 𝕜) • (x + y) + z‖ + + ‖(I : 𝕜) • x - z‖ * ‖(I : 𝕜) • x - z‖) := by + convert parallelogram_identity ((I : 𝕜) • (x + y) + z) ((I : 𝕜) • x - z) using 4 <;> module private theorem add_left_aux6 (x y z : E) : - ‖(I : 𝕜) • (x + y) - z‖ * ‖(I : 𝕜) • (x + y) - z‖ = (‖(I : 𝕜) • (2 • x + y)‖ * ‖(I : 𝕜) • (2 • x + y)‖ + - ‖(I : 𝕜) • y - 2 • z‖ * ‖(I : 𝕜) • y - 2 • z‖) / 2 - - ‖(I : 𝕜) • x + z‖ * ‖(I : 𝕜) • x + z‖ := by - rw [eq_sub_iff_add_eq, eq_div_iff (two_ne_zero' ℝ), mul_comm _ (2 : ℝ), eq_comm] - have h₀ := parallelogram_identity ((I : 𝕜) • (x + y) - z) ((I : 𝕜) • x + z) - convert h₀ using 4 <;> · try simp only [two_smul, smul_add]; abel + ‖(I : 𝕜) • y - 2 • z‖ * ‖(I : 𝕜) • y - 2 • z‖) + = 2 * (‖(I : 𝕜) • (x + y) - z‖ * ‖(I : 𝕜) • (x + y) - z‖ + + ‖(I : 𝕜) • x + z‖ * ‖(I : 𝕜) • x + z‖) := by + convert parallelogram_identity ((I : 𝕜) • (x + y) - z) ((I : 𝕜) • x + z) using 4 <;> module private theorem add_left_aux7 (y z : E) : - ‖(I : 𝕜) • y + 2 • z‖ * ‖(I : 𝕜) • y + 2 • z‖ = - 2 * (‖(I : 𝕜) • y + z‖ * ‖(I : 𝕜) • y + z‖ + ‖z‖ * ‖z‖) - ‖(I : 𝕜) • y‖ * ‖(I : 𝕜) • y‖ := by - apply eq_sub_of_add_eq - have h₀ := parallelogram_identity ((I : 𝕜) • y + z) z - convert h₀ using 4 <;> · (try simp only [two_smul, smul_add]); abel + ‖(I : 𝕜) • y + 2 • z‖ * ‖(I : 𝕜) • y + 2 • z‖ + ‖(I : 𝕜) • y‖ * ‖(I : 𝕜) • y‖ = + 2 * (‖(I : 𝕜) • y + z‖ * ‖(I : 𝕜) • y + z‖ + ‖z‖ * ‖z‖) := by + convert parallelogram_identity ((I : 𝕜) • y + z) z using 4 <;> module private theorem add_left_aux8 (y z : E) : - ‖(I : 𝕜) • y - 2 • z‖ * ‖(I : 𝕜) • y - 2 • z‖ = - 2 * (‖(I : 𝕜) • y - z‖ * ‖(I : 𝕜) • y - z‖ + ‖z‖ * ‖z‖) - ‖(I : 𝕜) • y‖ * ‖(I : 𝕜) • y‖ := by - apply eq_sub_of_add_eq' - have h₀ := parallelogram_identity ((I : 𝕜) • y - z) z - convert h₀ using 4 <;> · (try simp only [two_smul, smul_add]); abel + ‖(I : 𝕜) • y‖ * ‖(I : 𝕜) • y‖ + ‖(I : 𝕜) • y - 2 • z‖ * ‖(I : 𝕜) • y - 2 • z‖ = + 2 * (‖(I : 𝕜) • y - z‖ * ‖(I : 𝕜) • y - z‖ + ‖z‖ * ‖z‖) := by + convert parallelogram_identity ((I : 𝕜) • y - z) z using 4 <;> module + +variable {𝕜} theorem add_left (x y z : E) : inner_ 𝕜 (x + y) z = inner_ 𝕜 x z + inner_ 𝕜 y z := by - simp only [inner_, ← mul_add] - congr - simp only [mul_assoc, ← map_mul, add_sub_assoc, ← mul_sub, ← map_sub] - rw [add_add_add_comm] - simp only [← map_add, ← mul_add] - congr - · rw [← add_sub_assoc, add_left_aux2', add_left_aux4'] - · rw [add_left_aux5, add_left_aux6, add_left_aux7, add_left_aux8] - simp only [map_sub, map_mul, map_add, div_eq_mul_inv] - ring - -theorem nat (n : ℕ) (x y : E) : inner_ 𝕜 ((n : 𝕜) • x) y = (n : 𝕜) * inner_ 𝕜 x y := by - induction' n with n ih - · simp only [inner_, zero_sub, Nat.cast_zero, zero_mul, - eq_self_iff_true, zero_smul, zero_add, mul_zero, sub_self, norm_neg, smul_zero] - · simp only [Nat.cast_succ, add_smul, one_smul] - rw [add_left, ih, add_mul, one_mul] - -private theorem nat_prop (r : ℕ) : innerProp' E (r : 𝕜) := fun x y => by - simp only [map_natCast]; exact nat r x y - -private theorem int_prop (n : ℤ) : innerProp' E (n : 𝕜) := by - intro x y - rw [← n.sign_mul_natAbs] - simp only [Int.cast_natCast, map_natCast, map_intCast, Int.cast_mul, map_mul, mul_smul] - obtain hn | rfl | hn := lt_trichotomy n 0 - · rw [Int.sign_eq_neg_one_of_neg hn, innerProp_neg_one ((n.natAbs : 𝕜) • x), nat] - simp only [map_neg, neg_mul, one_mul, mul_eq_mul_left_iff, Int.natAbs_eq_zero, - eq_self_iff_true, Int.cast_one, map_one, neg_inj, Nat.cast_eq_zero, Int.cast_neg] - · simp only [inner_, Int.cast_zero, zero_sub, Nat.cast_zero, zero_mul, - eq_self_iff_true, Int.sign_zero, zero_smul, zero_add, mul_zero, smul_zero, - sub_self, norm_neg, Int.natAbs_zero] - · rw [Int.sign_eq_one_of_pos hn] - simp only [one_mul, mul_eq_mul_left_iff, Int.natAbs_eq_zero, eq_self_iff_true, - Int.cast_one, one_smul, Nat.cast_eq_zero, nat] + have H_re := congr(- $(add_left_aux1 x y z) + $(add_left_aux2 x y z) + + $(add_left_aux3 y z) - $(add_left_aux4 y z)) + have H_im := congr(- $(add_left_aux5 𝕜 x y z) + $(add_left_aux6 𝕜 x y z) + + $(add_left_aux7 𝕜 y z) - $(add_left_aux8 𝕜 y z)) + have H := congr(𝓚 $H_re + I * 𝓚 $H_im) + simp only [inner_, map_add, map_sub, map_neg, map_mul, map_ofNat] at H ⊢ + linear_combination H / 8 private theorem rat_prop (r : ℚ) : innerProp' E (r : 𝕜) := by intro x y - have : (r.den : 𝕜) ≠ 0 := by - haveI : CharZero 𝕜 := RCLike.charZero_rclike - exact mod_cast r.pos.ne' - rw [← r.num_div_den, ← mul_right_inj' this, ← nat r.den _ y, smul_smul, Rat.cast_div] - simp only [map_natCast, Rat.cast_natCast, map_intCast, Rat.cast_intCast, map_div₀] - rw [← mul_assoc, mul_div_cancel₀ _ this, int_prop _ x, map_intCast] + let hom : 𝕜 →ₗ[ℚ] 𝕜 := AddMonoidHom.toRatLinearMap <| + AddMonoidHom.mk' (fun r ↦ inner_ 𝕜 (r • x) y) <| fun a b ↦ by + simpa [add_smul] using add_left (a • x) (b • x) y + simpa [hom, Rat.smul_def] using map_smul hom r 1 private theorem real_prop (r : ℝ) : innerProp' E (r : 𝕜) := by intro x y revert r rw [← Function.funext_iff] - refine Rat.denseEmbedding_coe_real.dense.equalizer ?_ ?_ (funext fun X => ?_) + refine Rat.isDenseEmbedding_coe_real.dense.equalizer ?_ ?_ (funext fun X => ?_) · exact (continuous_ofReal.smul continuous_const).inner_ continuous_const · exact (continuous_conj.comp continuous_ofReal).mul continuous_const · simp only [Function.comp_apply, RCLike.ofReal_ratCast, rat_prop _ _] private theorem I_prop : innerProp' E (I : 𝕜) := by by_cases hI : (I : 𝕜) = 0 - · rw [hI, ← Nat.cast_zero]; exact nat_prop _ + · rw [hI] + simpa using real_prop (𝕜 := 𝕜) 0 intro x y - have hI' : (-I : 𝕜) * I = 1 := by rw [← inv_I, inv_mul_cancel₀ hI] - rw [conj_I, inner_, inner_, mul_left_comm] - congr 1 - rw [smul_smul, I_mul_I_of_nonzero hI, neg_one_smul] - rw [mul_sub, mul_add, mul_sub, mul_assoc I (𝓚 ‖I • x - y‖), ← mul_assoc (-I) I, hI', one_mul, - mul_assoc I (𝓚 ‖I • x + y‖), ← mul_assoc (-I) I, hI', one_mul] + have hI' := I_mul_I_of_nonzero hI + rw [conj_I, inner_, inner_, mul_left_comm, smul_smul, hI', neg_one_smul] have h₁ : ‖-x - y‖ = ‖x + y‖ := by rw [← neg_add', norm_neg] have h₂ : ‖-x + y‖ = ‖x - y‖ := by rw [← neg_sub, norm_neg, sub_eq_neg_add] rw [h₁, h₂] - simp only [sub_eq_add_neg, mul_assoc] - rw [← neg_mul_eq_neg_mul, ← neg_mul_eq_neg_mul] - abel + linear_combination (- 𝓚 ‖(I : 𝕜) • x - y‖ ^ 2 + 𝓚 ‖(I : 𝕜) • x + y‖ ^ 2) * hI' / 4 theorem innerProp (r : 𝕜) : innerProp' E r := by intro x y diff --git a/Mathlib/Analysis/InnerProductSpace/Orientation.lean b/Mathlib/Analysis/InnerProductSpace/Orientation.lean index 60b27da658fe3..fb73168b5bab2 100644 --- a/Mathlib/Analysis/InnerProductSpace/Orientation.lean +++ b/Mathlib/Analysis/InnerProductSpace/Orientation.lean @@ -38,7 +38,7 @@ noncomputable section variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] -open FiniteDimensional +open Module open scoped RealInnerProductSpace diff --git a/Mathlib/Analysis/InnerProductSpace/PiL2.lean b/Mathlib/Analysis/InnerProductSpace/PiL2.lean index 12ea8605df263..5fb4aa1c20293 100644 --- a/Mathlib/Analysis/InnerProductSpace/PiL2.lean +++ b/Mathlib/Analysis/InnerProductSpace/PiL2.lean @@ -144,11 +144,11 @@ variable [Fintype ι] @[simp] theorem finrank_euclideanSpace : - FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 ι) = Fintype.card ι := by + Module.finrank 𝕜 (EuclideanSpace 𝕜 ι) = Fintype.card ι := by simp [EuclideanSpace, PiLp, WithLp] theorem finrank_euclideanSpace_fin {n : ℕ} : - FiniteDimensional.finrank 𝕜 (EuclideanSpace 𝕜 (Fin n)) = n := by simp + Module.finrank 𝕜 (EuclideanSpace 𝕜 (Fin n)) = n := by simp theorem EuclideanSpace.inner_eq_star_dotProduct (x y : EuclideanSpace 𝕜 ι) : ⟪x, y⟫ = Matrix.dotProduct (star <| WithLp.equiv _ _ x) (WithLp.equiv _ _ y) := @@ -669,7 +669,7 @@ theorem Complex.isometryOfOrthonormal_apply (v : OrthonormalBasis (Fin 2) ℝ F) end Complex -open FiniteDimensional +open Module /-! ### Matrix representation of an orthonormal basis with respect to another -/ @@ -679,6 +679,28 @@ section ToMatrix variable [DecidableEq ι] section +open scoped Matrix + +/-- A version of `OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary` that works for bases with +different index types. -/ +@[simp] +theorem OrthonormalBasis.toMatrix_orthonormalBasis_conjTranspose_mul_self [Fintype ι'] + (a : OrthonormalBasis ι' 𝕜 E) (b : OrthonormalBasis ι 𝕜 E) : + (a.toBasis.toMatrix b)ᴴ * a.toBasis.toMatrix b = 1 := by + ext i j + convert a.repr.inner_map_map (b i) (b j) + rw [orthonormal_iff_ite.mp b.orthonormal i j] + rfl + +/-- A version of `OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary` that works for bases with +different index types. -/ +@[simp] +theorem OrthonormalBasis.toMatrix_orthonormalBasis_self_mul_conjTranspose [Fintype ι'] + (a : OrthonormalBasis ι 𝕜 E) (b : OrthonormalBasis ι' 𝕜 E) : + a.toBasis.toMatrix b * (a.toBasis.toMatrix b)ᴴ = 1 := by + classical + rw [Matrix.mul_eq_one_comm_of_equiv (a.toBasis.indexEquiv b.toBasis), + a.toMatrix_orthonormalBasis_conjTranspose_mul_self b] variable (a b : OrthonormalBasis ι 𝕜 E) @@ -686,10 +708,7 @@ variable (a b : OrthonormalBasis ι 𝕜 E) theorem OrthonormalBasis.toMatrix_orthonormalBasis_mem_unitary : a.toBasis.toMatrix b ∈ Matrix.unitaryGroup ι 𝕜 := by rw [Matrix.mem_unitaryGroup_iff'] - ext i j - convert a.repr.inner_map_map (b i) (b j) - rw [orthonormal_iff_ite.mp b.orthonormal i j] - rfl + exact a.toMatrix_orthonormalBasis_conjTranspose_mul_self b /-- The determinant of the change-of-basis matrix between two orthonormal bases `a`, `b` has unit length. -/ @@ -773,7 +792,7 @@ theorem Orthonormal.exists_orthonormalBasis_extension_of_card_eq {ι : Type*} [F obtain ⟨Y, b₀, hX, hb₀⟩ := hX.exists_orthonormalBasis_extension have hιY : Fintype.card ι = Y.card := by refine card_ι.symm.trans ?_ - exact FiniteDimensional.finrank_eq_card_finset_basis b₀.toBasis + exact Module.finrank_eq_card_finset_basis b₀.toBasis have hvsY : s.MapsTo v Y := (s.mapsTo_image v).mono_right (by rwa [← range_restrict]) have hsv' : Set.InjOn v s := by rw [Set.injOn_iff_injective] @@ -821,7 +840,7 @@ irreducible_def DirectSum.IsInternal.sigmaOrthonormalBasisIndexEquiv (hV' : OrthogonalFamily 𝕜 (fun i => V i) fun i => (V i).subtypeₗᵢ) : (Σi, Fin (finrank 𝕜 (V i))) ≃ Fin n := let b := hV.collectedOrthonormalBasis hV' fun i => stdOrthonormalBasis 𝕜 (V i) - Fintype.equivFinOfCardEq <| (FiniteDimensional.finrank_eq_card_basis b.toBasis).symm.trans hn + Fintype.equivFinOfCardEq <| (Module.finrank_eq_card_basis b.toBasis).symm.trans hn /-- An `n`-dimensional `InnerProductSpace` equipped with a decomposition as an internal direct sum has an orthonormal basis indexed by `Fin n` and subordinate to that direct sum. -/ @@ -866,7 +885,7 @@ section LinearIsometry variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace 𝕜 V] [FiniteDimensional 𝕜 V] variable {S : Submodule 𝕜 V} {L : S →ₗᵢ[𝕜] V} -open FiniteDimensional +open Module /-- Let `S` be a subspace of a finite-dimensional complex inner product space `V`. A linear isometry mapping `S` into `V` can be extended to a full isometry of `V`. @@ -928,7 +947,7 @@ theorem LinearIsometry.extend_apply (L : S →ₗᵢ[𝕜] V) (s : S) : L.extend simp only [add_right_eq_self, LinearIsometry.coe_toLinearMap, LinearIsometryEquiv.coe_toLinearIsometry, LinearIsometry.coe_comp, Function.comp_apply, orthogonalProjection_mem_subspace_eq_self, LinearMap.coe_comp, ContinuousLinearMap.coe_coe, - Submodule.coeSubtype, LinearMap.add_apply, Submodule.coe_eq_zero, + Submodule.coe_subtype, LinearMap.add_apply, Submodule.coe_eq_zero, LinearIsometryEquiv.map_eq_zero_iff, Submodule.coe_subtypeₗᵢ, orthogonalProjection_mem_subspace_orthogonalComplement_eq_zero, Submodule.orthogonal_orthogonal, Submodule.coe_mem] diff --git a/Mathlib/Analysis/InnerProductSpace/Projection.lean b/Mathlib/Analysis/InnerProductSpace/Projection.lean index dff8bfa3ecd3d..28ef290eefc60 100644 --- a/Mathlib/Analysis/InnerProductSpace/Projection.lean +++ b/Mathlib/Analysis/InnerProductSpace/Projection.lean @@ -863,12 +863,13 @@ theorem orthogonalProjection_orthogonalProjection_of_le {U V : Submodule 𝕜 E} /-- Given a monotone family `U` of complete submodules of `E` and a fixed `x : E`, the orthogonal projection of `x` on `U i` tends to the orthogonal projection of `x` on `(⨆ i, U i).topologicalClosure` along `atTop`. -/ -theorem orthogonalProjection_tendsto_closure_iSup [CompleteSpace E] {ι : Type*} [SemilatticeSup ι] - (U : ι → Submodule 𝕜 E) [∀ i, CompleteSpace (U i)] (hU : Monotone U) (x : E) : +theorem orthogonalProjection_tendsto_closure_iSup {ι : Type*} [Preorder ι] + (U : ι → Submodule 𝕜 E) [∀ i, HasOrthogonalProjection (U i)] + [HasOrthogonalProjection (⨆ i, U i).topologicalClosure] (hU : Monotone U) (x : E) : Filter.Tendsto (fun i => (orthogonalProjection (U i) x : E)) atTop (𝓝 (orthogonalProjection (⨆ i, U i).topologicalClosure x : E)) := by - cases isEmpty_or_nonempty ι - · exact tendsto_of_isEmpty + refine .of_neBot_imp fun h ↦ ?_ + cases atTop_neBot_iff.mp h let y := (orthogonalProjection (⨆ i, U i).topologicalClosure x : E) have proj_x : ∀ i, orthogonalProjection (U i) x = orthogonalProjection (U i) y := fun i => (orthogonalProjection_orthogonalProjection_of_le @@ -890,14 +891,15 @@ theorem orthogonalProjection_tendsto_closure_iSup [CompleteSpace E] {ι : Type*} /-- Given a monotone family `U` of complete submodules of `E` with dense span supremum, and a fixed `x : E`, the orthogonal projection of `x` on `U i` tends to `x` along `at_top`. -/ -theorem orthogonalProjection_tendsto_self [CompleteSpace E] {ι : Type*} [SemilatticeSup ι] - (U : ι → Submodule 𝕜 E) [∀ t, CompleteSpace (U t)] (hU : Monotone U) (x : E) +theorem orthogonalProjection_tendsto_self {ι : Type*} [Preorder ι] + (U : ι → Submodule 𝕜 E) [∀ t, HasOrthogonalProjection (U t)] (hU : Monotone U) (x : E) (hU' : ⊤ ≤ (⨆ t, U t).topologicalClosure) : Filter.Tendsto (fun t => (orthogonalProjection (U t) x : E)) atTop (𝓝 x) := by - rw [← eq_top_iff] at hU' + have : HasOrthogonalProjection (⨆ i, U i).topologicalClosure := by + rw [top_unique hU'] + infer_instance convert orthogonalProjection_tendsto_closure_iSup U hU x - rw [orthogonalProjection_eq_self_iff.mpr _] - rw [hU'] + rw [eq_comm, orthogonalProjection_eq_self_iff, top_unique hU'] trivial /-- The orthogonal complement satisfies `Kᗮᗮᗮ = Kᗮ`. -/ @@ -1029,7 +1031,7 @@ theorem orthogonalProjection_isSymmetric [HasOrthogonalProjection K] : (K.subtypeL ∘L orthogonalProjection K : E →ₗ[𝕜] E).IsSymmetric := inner_orthogonalProjection_left_eq_right K -open FiniteDimensional +open Module /-- Given a finite-dimensional subspace `K₂`, and a subspace `K₁` contained in it, the dimensions of `K₁` and the intersection of its @@ -1038,7 +1040,7 @@ theorem Submodule.finrank_add_inf_finrank_orthogonal {K₁ K₂ : Submodule 𝕜 [FiniteDimensional 𝕜 K₂] (h : K₁ ≤ K₂) : finrank 𝕜 K₁ + finrank 𝕜 (K₁ᗮ ⊓ K₂ : Submodule 𝕜 E) = finrank 𝕜 K₂ := by haveI : FiniteDimensional 𝕜 K₁ := Submodule.finiteDimensional_of_le h - haveI := proper_rclike 𝕜 K₁ + haveI := FiniteDimensional.proper_rclike 𝕜 K₁ have hd := Submodule.finrank_sup_add_finrank_inf_eq K₁ (K₁ᗮ ⊓ K₂) rw [← inf_assoc, (Submodule.orthogonal_disjoint K₁).eq_bot, bot_inf_eq, finrank_bot, Submodule.sup_orthogonal_inf_of_completeSpace h] at hd @@ -1270,7 +1272,7 @@ section OrthonormalBasis variable {v : Set E} -open FiniteDimensional Submodule Set +open Module Submodule Set /-- An orthonormal set in an `InnerProductSpace` is maximal, if and only if the orthogonal complement of its span is empty. -/ @@ -1341,7 +1343,7 @@ variable [FiniteDimensional 𝕜 E] is a basis. -/ theorem maximal_orthonormal_iff_basis_of_finiteDimensional (hv : Orthonormal 𝕜 ((↑) : v → E)) : (∀ u ⊇ v, Orthonormal 𝕜 ((↑) : u → E) → u = v) ↔ ∃ b : Basis v 𝕜 E, ⇑b = ((↑) : v → E) := by - haveI := proper_rclike 𝕜 (span 𝕜 v) + haveI := FiniteDimensional.proper_rclike 𝕜 (span 𝕜 v) rw [maximal_orthonormal_iff_orthogonalComplement_eq_bot hv] rw [Submodule.orthogonal_eq_bot_iff] have hv_coe : range ((↑) : v → E) = v := by simp diff --git a/Mathlib/Analysis/InnerProductSpace/Spectrum.lean b/Mathlib/Analysis/InnerProductSpace/Spectrum.lean index 68d1c7ecfc1b4..0f4bd55b7bae8 100644 --- a/Mathlib/Analysis/InnerProductSpace/Spectrum.lean +++ b/Mathlib/Analysis/InnerProductSpace/Spectrum.lean @@ -184,7 +184,7 @@ end Version1 section Version2 -variable {n : ℕ} (hn : FiniteDimensional.finrank 𝕜 E = n) +variable {n : ℕ} (hn : Module.finrank 𝕜 E = n) /-- A choice of orthonormal basis of eigenvectors for self-adjoint operator `T` on a finite-dimensional inner product space `E`. diff --git a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean index 4928bc0cac733..9acf7b33a0635 100644 --- a/Mathlib/Analysis/InnerProductSpace/Symmetric.lean +++ b/Mathlib/Analysis/InnerProductSpace/Symmetric.lean @@ -36,11 +36,13 @@ open RCLike open ComplexConjugate +section Seminormed + variable {𝕜 E E' F G : Type*} [RCLike 𝕜] -variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] -variable [NormedAddCommGroup F] [InnerProductSpace 𝕜 F] -variable [NormedAddCommGroup G] [InnerProductSpace 𝕜 G] -variable [NormedAddCommGroup E'] [InnerProductSpace ℝ E'] +variable [SeminormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [SeminormedAddCommGroup F] [InnerProductSpace 𝕜 F] +variable [SeminormedAddCommGroup G] [InnerProductSpace 𝕜 G] +variable [SeminormedAddCommGroup E'] [InnerProductSpace ℝ E'] local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y @@ -72,33 +74,47 @@ theorem IsSymmetric.apply_clm {T : E →L[𝕜] E} (hT : IsSymmetric (T : E → ⟪T x, y⟫ = ⟪x, T y⟫ := hT x y -theorem isSymmetric_zero : (0 : E →ₗ[𝕜] E).IsSymmetric := fun x y => +@[simp] +protected theorem IsSymmetric.zero : (0 : E →ₗ[𝕜] E).IsSymmetric := fun x y => (inner_zero_right x : ⟪x, 0⟫ = 0).symm ▸ (inner_zero_left y : ⟪0, y⟫ = 0) -theorem isSymmetric_id : (LinearMap.id : E →ₗ[𝕜] E).IsSymmetric := fun _ _ => rfl +@[deprecated (since := "2024-09-30")] alias isSymmetric_zero := IsSymmetric.zero + +@[simp] +protected theorem IsSymmetric.id : (LinearMap.id : E →ₗ[𝕜] E).IsSymmetric := fun _ _ => rfl + +@[deprecated (since := "2024-09-30")] alias isSymmetric_id := IsSymmetric.id +@[aesop safe apply] theorem IsSymmetric.add {T S : E →ₗ[𝕜] E} (hT : T.IsSymmetric) (hS : S.IsSymmetric) : (T + S).IsSymmetric := by intro x y rw [LinearMap.add_apply, inner_add_left, hT x y, hS x y, ← inner_add_right] rfl -/-- The **Hellinger--Toeplitz theorem**: if a symmetric operator is defined on a complete space, - then it is automatically continuous. -/ -theorem IsSymmetric.continuous [CompleteSpace E] {T : E →ₗ[𝕜] E} (hT : IsSymmetric T) : - Continuous T := by - -- We prove it by using the closed graph theorem - refine T.continuous_of_seq_closed_graph fun u x y hu hTu => ?_ - rw [← sub_eq_zero, ← @inner_self_eq_zero 𝕜] - have hlhs : ∀ k : ℕ, ⟪T (u k) - T x, y - T x⟫ = ⟪u k - x, T (y - T x)⟫ := by - intro k - rw [← T.map_sub, hT] - refine tendsto_nhds_unique ((hTu.sub_const _).inner tendsto_const_nhds) ?_ - simp_rw [Function.comp_apply, hlhs] - rw [← inner_zero_left (T (y - T x))] - refine Filter.Tendsto.inner ?_ tendsto_const_nhds - rw [← sub_self x] - exact hu.sub_const _ +@[aesop safe apply] +theorem IsSymmetric.sub {T S : E →ₗ[𝕜] E} (hT : T.IsSymmetric) (hS : S.IsSymmetric) : + (T - S).IsSymmetric := by + intro x y + rw [LinearMap.sub_apply, inner_sub_left, hT x y, hS x y, ← inner_sub_right] + rfl + +@[aesop safe apply] +theorem IsSymmetric.smul {c : 𝕜} (hc : conj c = c) {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) : + c • T |>.IsSymmetric := by + intro x y + simp only [smul_apply, inner_smul_left, hc, hT x y, inner_smul_right] + +@[aesop 30% apply] +lemma IsSymmetric.mul_of_commute {S T : E →ₗ[𝕜] E} (hS : S.IsSymmetric) (hT : T.IsSymmetric) + (hST : Commute S T) : (S * T).IsSymmetric := + fun _ _ ↦ by rw [mul_apply, hS, hT, hST, mul_apply] + +@[aesop safe apply] +lemma IsSymmetric.pow {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) (n : ℕ) : (T ^ n).IsSymmetric := by + refine Nat.le_induction (by simp [one_eq_id]) (fun k _ ih ↦ ?_) n n.zero_le + rw [iterate_succ, ← mul_eq_comp] + exact ih.mul_of_commute hT <| .pow_left rfl k /-- For a symmetric operator `T`, the function `fun x ↦ ⟪T x, x⟫` is real-valued. -/ @[simp] @@ -115,14 +131,14 @@ theorem IsSymmetric.restrict_invariant {T : E →ₗ[𝕜] E} (hT : IsSymmetric (hV : ∀ v ∈ V, T v ∈ V) : IsSymmetric (T.restrict hV) := fun v w => hT v w theorem IsSymmetric.restrictScalars {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) : - @LinearMap.IsSymmetric ℝ E _ _ (InnerProductSpace.rclikeToReal 𝕜 E) - (@LinearMap.restrictScalars ℝ 𝕜 _ _ _ _ _ _ (InnerProductSpace.rclikeToReal 𝕜 E).toModule - (InnerProductSpace.rclikeToReal 𝕜 E).toModule _ _ _ T) := + letI := InnerProductSpace.rclikeToReal 𝕜 E + letI : IsScalarTower ℝ 𝕜 E := RestrictScalars.isScalarTower _ _ _ + (T.restrictScalars ℝ).IsSymmetric := fun x y => by simp [hT x y, real_inner_eq_re_inner, LinearMap.coe_restrictScalars ℝ] section Complex -variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℂ V] +variable {V : Type*} [SeminormedAddCommGroup V] [InnerProductSpace ℂ V] attribute [local simp] map_ofNat in -- use `ofNat` simp theorem with bad keys open scoped InnerProductSpace in @@ -167,6 +183,39 @@ theorem IsSymmetric.inner_map_polarization {T : E →ₗ[𝕜] E} (hT : T.IsSymm sub_sub, ← mul_assoc, mul_neg, h, neg_neg, one_mul, neg_one_mul] ring +end LinearMap + +end Seminormed + +section Normed + +variable {𝕜 E E' F G : Type*} [RCLike 𝕜] +variable [NormedAddCommGroup E] [InnerProductSpace 𝕜 E] +variable [NormedAddCommGroup F] [InnerProductSpace 𝕜 F] +variable [NormedAddCommGroup G] [InnerProductSpace 𝕜 G] +variable [NormedAddCommGroup E'] [InnerProductSpace ℝ E'] + +local notation "⟪" x ", " y "⟫" => @inner 𝕜 _ _ x y + +namespace LinearMap + +/-- The **Hellinger--Toeplitz theorem**: if a symmetric operator is defined on a complete space, + then it is automatically continuous. -/ +theorem IsSymmetric.continuous [CompleteSpace E] {T : E →ₗ[𝕜] E} (hT : IsSymmetric T) : + Continuous T := by + -- We prove it by using the closed graph theorem + refine T.continuous_of_seq_closed_graph fun u x y hu hTu => ?_ + rw [← sub_eq_zero, ← @inner_self_eq_zero 𝕜] + have hlhs : ∀ k : ℕ, ⟪T (u k) - T x, y - T x⟫ = ⟪u k - x, T (y - T x)⟫ := by + intro k + rw [← T.map_sub, hT] + refine tendsto_nhds_unique ((hTu.sub_const _).inner tendsto_const_nhds) ?_ + simp_rw [Function.comp_apply, hlhs] + rw [← inner_zero_left (T (y - T x))] + refine Filter.Tendsto.inner ?_ tendsto_const_nhds + rw [← sub_self x] + exact hu.sub_const _ + /-- A symmetric linear map `T` is zero if and only if `⟪T x, x⟫_ℝ = 0` for all `x`. See `inner_map_self_eq_zero` for the complex version without the symmetric assumption. -/ theorem IsSymmetric.inner_map_self_eq_zero {T : E →ₗ[𝕜] E} (hT : T.IsSymmetric) : @@ -178,3 +227,5 @@ theorem IsSymmetric.inner_map_self_eq_zero {T : E →ₗ[𝕜] E} (hT : T.IsSymm ring end LinearMap + +end Normed diff --git a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean index 1f3cbc87585d7..329dd441e2adc 100644 --- a/Mathlib/Analysis/InnerProductSpace/TwoDim.lean +++ b/Mathlib/Analysis/InnerProductSpace/TwoDim.lean @@ -71,7 +71,7 @@ noncomputable section open scoped RealInnerProductSpace ComplexConjugate -open FiniteDimensional +open Module lemma FiniteDimensional.of_fact_finrank_eq_two {K V : Type*} [DivisionRing K] [AddCommGroup V] [Module K V] [Fact (finrank K V = 2)] : FiniteDimensional K V := @@ -204,7 +204,7 @@ def rightAngleRotationAux₂ : E →ₗᵢ[ℝ] E := exact o.areaForm_le x (o.rightAngleRotationAux₁ x) · let K : Submodule ℝ E := ℝ ∙ x have : Nontrivial Kᗮ := by - apply @FiniteDimensional.nontrivial_of_finrank_pos ℝ + apply nontrivial_of_finrank_pos (R := ℝ) have : finrank ℝ K ≤ Finset.card {x} := by rw [← Set.toFinset_singleton] exact finrank_span_le_card ({x} : Set E) diff --git a/Mathlib/Analysis/InnerProductSpace/l2Space.lean b/Mathlib/Analysis/InnerProductSpace/l2Space.lean index 9eb925f593b03..54a08fc3d190b 100644 --- a/Mathlib/Analysis/InnerProductSpace/l2Space.lean +++ b/Mathlib/Analysis/InnerProductSpace/l2Space.lean @@ -249,7 +249,7 @@ protected theorem range_linearIsometry [∀ i, CompleteSpace (G i)] : rintro i x ⟨x, rfl⟩ use lp.single 2 i x exact hV.linearIsometry_apply_single x - exact hV.linearIsometry.isometry.uniformInducing.isComplete_range.isClosed + exact hV.linearIsometry.isometry.isUniformInducing.isComplete_range.isClosed end OrthogonalFamily diff --git a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean index 5667478982a21..08b82218840f4 100644 --- a/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean +++ b/Mathlib/Analysis/LocallyConvex/BalancedCoreHull.lean @@ -131,7 +131,7 @@ theorem balancedHull.balanced (s : Set E) : Balanced 𝕜 (balancedHull 𝕜 s) simp_rw [balancedHull, smul_set_iUnion₂, subset_def, mem_iUnion₂] rintro x ⟨r, hr, hx⟩ rw [← smul_assoc] at hx - exact ⟨a • r, (SeminormedRing.norm_mul _ _).trans (mul_le_one ha (norm_nonneg r) hr), hx⟩ + exact ⟨a • r, (SeminormedRing.norm_mul _ _).trans (mul_le_one₀ ha (norm_nonneg r) hr), hx⟩ end Module @@ -158,7 +158,7 @@ theorem balancedCoreAux_balanced (h0 : (0 : E) ∈ balancedCoreAux 𝕜 s) : intro r hr have h'' : 1 ≤ ‖a⁻¹ • r‖ := by rw [norm_smul, norm_inv] - exact one_le_mul_of_one_le_of_one_le (one_le_inv (norm_pos_iff.mpr h) ha) hr + exact one_le_mul_of_one_le_of_one_le ((one_le_inv₀ (norm_pos_iff.mpr h)).2 ha) hr have h' := hy (a⁻¹ • r) h'' rwa [smul_assoc, mem_inv_smul_set_iff₀ h] at h' @@ -167,7 +167,7 @@ theorem balancedCoreAux_maximal (h : t ⊆ s) (ht : Balanced 𝕜 t) : t ⊆ bal rw [mem_smul_set_iff_inv_smul_mem₀ (norm_pos_iff.mp <| zero_lt_one.trans_le hr)] refine h (ht.smul_mem ?_ hx) rw [norm_inv] - exact inv_le_one hr + exact inv_le_one_of_one_le₀ hr theorem balancedCore_subset_balancedCoreAux : balancedCore 𝕜 s ⊆ balancedCoreAux 𝕜 s := balancedCoreAux_maximal (balancedCore_subset s) (balancedCore_balanced s) @@ -185,7 +185,7 @@ theorem subset_balancedCore (ht : (0 : E) ∈ t) (hst : ∀ a : 𝕜, ‖a‖ rw [subset_set_smul_iff₀ (norm_pos_iff.mp <| zero_lt_one.trans_le ha)] apply hst rw [norm_inv] - exact inv_le_one ha + exact inv_le_one_of_one_le₀ ha end NormedField diff --git a/Mathlib/Analysis/LocallyConvex/Basic.lean b/Mathlib/Analysis/LocallyConvex/Basic.lean index 03bfae8efd21d..4b242d6809928 100644 --- a/Mathlib/Analysis/LocallyConvex/Basic.lean +++ b/Mathlib/Analysis/LocallyConvex/Basic.lean @@ -183,7 +183,7 @@ theorem Balanced.smul_mono (hs : Balanced 𝕝 s) {a : 𝕝} {b : 𝕜} (h : ‖ a • s = b • (b⁻¹ • a) • s := by rw [smul_assoc, smul_inv_smul₀ hb] _ ⊆ b • s := smul_set_mono <| hs _ <| by rw [norm_smul, norm_inv, ← div_eq_inv_mul] - exact div_le_one_of_le h (norm_nonneg _) + exact div_le_one_of_le₀ h (norm_nonneg _) theorem Balanced.smul_mem_mono [SMulCommClass 𝕝 𝕜 E] (hs : Balanced 𝕝 s) {a : 𝕜} {b : 𝕝} (ha : a • x ∈ s) (hba : ‖b‖ ≤ ‖a‖) : b • x ∈ s := by @@ -193,7 +193,7 @@ theorem Balanced.smul_mem_mono [SMulCommClass 𝕝 𝕜 E] (hs : Balanced 𝕝 s (a⁻¹ • b) • a • x ∈ s := by refine hs.smul_mem ?_ ha rw [norm_smul, norm_inv, ← div_eq_inv_mul] - exact div_le_one_of_le hba (norm_nonneg _) + exact div_le_one_of_le₀ hba (norm_nonneg _) (a⁻¹ • b) • a • x = b • x := by rw [smul_comm, smul_assoc, smul_inv_smul₀ ha₀] theorem Balanced.subset_smul (hA : Balanced 𝕜 A) (ha : 1 ≤ ‖a‖) : A ⊆ a • A := by diff --git a/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean b/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean index a61d1ac3cdcf5..d1b8d23fb2ca3 100644 --- a/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean +++ b/Mathlib/Analysis/LocallyConvex/ContinuousOfBounded.lean @@ -109,7 +109,7 @@ theorem LinearMap.continuousAt_zero_of_locally_bounded (f : E →ₛₗ[σ] F) refine (bE1 (n + 1)).2.smul_mem ?_ hx have h' : 0 < (n : ℝ) + 1 := n.cast_add_one_pos rw [norm_inv, ← Nat.cast_one, ← Nat.cast_add, RCLike.norm_natCast, Nat.cast_add, - Nat.cast_one, inv_le h' zero_lt_one] + Nat.cast_one, inv_le_comm₀ h' zero_lt_one] simp intro n hn -- The converse direction follows from continuity of the scalar multiplication diff --git a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean index ae6a4a37290bc..b4165a1a77053 100644 --- a/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean +++ b/Mathlib/Analysis/LocallyConvex/WithSeminorms.lean @@ -135,7 +135,7 @@ theorem basisSets_smul_right (v : E) (U : Set E) (hU : U ∈ p.basisSets) : rw [hU, Filter.eventually_iff] simp_rw [(s.sup p).mem_ball_zero, map_smul_eq_mul] by_cases h : 0 < (s.sup p) v - · simp_rw [(lt_div_iff h).symm] + · simp_rw [(lt_div_iff₀ h).symm] rw [← _root_.ball_zero_eq] exact Metric.ball_mem_nhds 0 (div_pos hr h) simp_rw [le_antisymm (not_lt.mp h) (apply_nonneg _ v), mul_zero, hr] diff --git a/Mathlib/Analysis/MeanInequalities.lean b/Mathlib/Analysis/MeanInequalities.lean index 2426536d2bcae..ebc7bb9056c0f 100644 --- a/Mathlib/Analysis/MeanInequalities.lean +++ b/Mathlib/Analysis/MeanInequalities.lean @@ -3,6 +3,7 @@ Copyright (c) 2019 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Sébastien Gouëzel, Rémy Degenne -/ +import Mathlib.Algebra.BigOperators.Expect import Mathlib.Analysis.Convex.Jensen import Mathlib.Analysis.Convex.SpecificFunctions.Basic import Mathlib.Analysis.SpecialFunctions.Pow.NNReal @@ -105,6 +106,7 @@ less than or equal to the sum of the maximum values of the summands. universe u v open Finset NNReal ENNReal +open scoped BigOperators noncomputable section @@ -270,11 +272,11 @@ theorem harm_mean_le_geom_mean_weighted (w z : ι → ℝ) (hs : s.Nonempty) (hw have s_pos : 0 < ∑ i in s, w i * (z i)⁻¹ := sum_pos (fun i hi => mul_pos (hw i hi) (inv_pos.2 (hz i hi))) hs norm_num at this - rw [← inv_le_inv s_pos p_pos] at this + rw [← inv_le_inv₀ s_pos p_pos] at this apply le_trans this have p_pos₂ : 0 < (∏ i in s, (z i) ^ w i)⁻¹ := inv_pos.2 (prod_pos fun i hi => rpow_pos_of_pos ((hz i hi)) _ ) - rw [← inv_inv (∏ i in s, z i ^ w i), inv_le_inv p_pos p_pos₂, ← Finset.prod_inv_distrib] + rw [← inv_inv (∏ i in s, z i ^ w i), inv_le_inv₀ p_pos p_pos₂, ← Finset.prod_inv_distrib] gcongr · exact fun i hi ↦ inv_nonneg.mpr (Real.rpow_nonneg (le_of_lt (hz i hi)) _) · rw [Real.inv_rpow]; apply fun i hi ↦ le_of_lt (hz i hi); assumption @@ -660,6 +662,18 @@ lemma inner_le_weight_mul_Lp_of_nonneg (s : Finset ι) {p : ℝ} (hp : 1 ≤ p) norm_cast at * exact NNReal.inner_le_weight_mul_Lp _ hp _ _ +/-- **Weighted Hölder inequality** in terms of `Finset.expect`. -/ +lemma compact_inner_le_weight_mul_Lp_of_nonneg (s : Finset ι) {p : ℝ} (hp : 1 ≤ p) {w f : ι → ℝ} + (hw : ∀ i, 0 ≤ w i) (hf : ∀ i, 0 ≤ f i) : + 𝔼 i ∈ s, w i * f i ≤ (𝔼 i ∈ s, w i) ^ (1 - p⁻¹) * (𝔼 i ∈ s, w i * f i ^ p) ^ p⁻¹ := by + simp_rw [expect_eq_sum_div_card] + rw [div_rpow, div_rpow, div_mul_div_comm, ← rpow_add', sub_add_cancel, rpow_one] + · gcongr + exact inner_le_weight_mul_Lp_of_nonneg s hp _ _ hw hf + any_goals simp + · exact sum_nonneg fun i _ ↦ by have := hw i; have := hf i; positivity + · exact sum_nonneg fun i _ ↦ by have := hw i; positivity + /-- **Hölder inequality**: the scalar product of two functions is bounded by the product of their `L^p` and `L^q` norms when `p` and `q` are conjugate exponents. A version for `ℝ`-valued functions. For an alternative version, convenient if the infinite sums are already expressed as `p`-th powers, @@ -807,7 +821,7 @@ lemma inner_le_weight_mul_Lp_of_nonneg (s : Finset ι) {p : ℝ} (hp : 1 ≤ p) obtain rfl | hp := hp.eq_or_lt · simp have hp₀ : 0 < p := by positivity - have hp₁ : p⁻¹ < 1 := inv_lt_one hp + have hp₁ : p⁻¹ < 1 := inv_lt_one_of_one_lt₀ hp by_cases H : (∑ i ∈ s, w i) ^ (1 - p⁻¹) = 0 ∨ (∑ i ∈ s, w i * f i ^ p) ^ p⁻¹ = 0 · replace H : (∀ i ∈ s, w i = 0) ∨ ∀ i ∈ s, w i = 0 ∨ f i = 0 := by simpa [hp₀, hp₁, hp₀.not_lt, hp₁.not_lt, sum_eq_zero_iff_of_nonneg] using H diff --git a/Mathlib/Analysis/MeanInequalitiesPow.lean b/Mathlib/Analysis/MeanInequalitiesPow.lean index daa489d39347c..fdee6d8fdbe46 100644 --- a/Mathlib/Analysis/MeanInequalitiesPow.lean +++ b/Mathlib/Analysis/MeanInequalitiesPow.lean @@ -61,23 +61,6 @@ theorem pow_arith_mean_le_arith_mean_pow_of_even (w z : ι → ℝ) (hw : ∀ i (∑ i ∈ s, w i * z i) ^ n ≤ ∑ i ∈ s, w i * z i ^ n := hn.convexOn_pow.map_sum_le hw hw' fun _ _ => Set.mem_univ _ -/-- Specific case of Jensen's inequality for sums of powers -/ -theorem pow_sum_div_card_le_sum_pow {f : ι → ℝ} (n : ℕ) (hf : ∀ a ∈ s, 0 ≤ f a) : - (∑ x ∈ s, f x) ^ (n + 1) / (s.card : ℝ) ^ n ≤ ∑ x ∈ s, f x ^ (n + 1) := by - rcases s.eq_empty_or_nonempty with (rfl | hs) - · simp_rw [Finset.sum_empty, zero_pow n.succ_ne_zero, zero_div]; rfl - · have hs0 : 0 < (s.card : ℝ) := Nat.cast_pos.2 hs.card_pos - suffices (∑ x ∈ s, f x / s.card) ^ (n + 1) ≤ ∑ x ∈ s, f x ^ (n + 1) / s.card by - rwa [← Finset.sum_div, ← Finset.sum_div, div_pow, pow_succ (s.card : ℝ), ← div_div, - div_le_iff₀ hs0, div_mul, div_self hs0.ne', div_one] at this - have := - @ConvexOn.map_sum_le ℝ ℝ ℝ ι _ _ _ _ _ _ (Set.Ici 0) (fun x => x ^ (n + 1)) s - (fun _ => 1 / s.card) ((↑) ∘ f) (convexOn_pow (n + 1)) ?_ ?_ fun i hi => - Set.mem_Ici.2 (hf i hi) - · simpa only [inv_mul_eq_div, one_div, Algebra.id.smul_eq_mul] using this - · simp only [one_div, inv_nonneg, Nat.cast_nonneg, imp_true_iff] - · simpa only [one_div, Finset.sum_const, nsmul_eq_mul] using mul_inv_cancel₀ hs0.ne' - theorem zpow_arith_mean_le_arith_mean_zpow (w z : ι → ℝ) (hw : ∀ i ∈ s, 0 ≤ w i) (hw' : ∑ i ∈ s, w i = 1) (hz : ∀ i ∈ s, 0 < z i) (m : ℤ) : (∑ i ∈ s, w i * z i) ^ m ≤ ∑ i ∈ s, w i * z i ^ m := @@ -111,11 +94,6 @@ theorem pow_arith_mean_le_arith_mean_pow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ Real.pow_arith_mean_le_arith_mean_pow s _ _ (fun i _ => (w i).coe_nonneg) (mod_cast hw') (fun i _ => (z i).coe_nonneg) n -theorem pow_sum_div_card_le_sum_pow (f : ι → ℝ≥0) (n : ℕ) : - (∑ x ∈ s, f x) ^ (n + 1) / (s.card : ℝ) ^ n ≤ ∑ x ∈ s, f x ^ (n + 1) := by - simpa only [← NNReal.coe_le_coe, NNReal.coe_sum, Nonneg.coe_div, NNReal.coe_pow] using - @Real.pow_sum_div_card_le_sum_pow ι s (((↑) : ℝ≥0 → ℝ) ∘ f) n fun _ _ => NNReal.coe_nonneg _ - /-- Weighted generalized mean inequality, version for sums over finite sets, with `ℝ≥0`-valued functions and real exponents. -/ theorem rpow_arith_mean_le_arith_mean_rpow (w z : ι → ℝ≥0) (hw' : ∑ i ∈ s, w i = 1) {p : ℝ} diff --git a/Mathlib/Analysis/MellinTransform.lean b/Mathlib/Analysis/MellinTransform.lean index 6712829f036dc..2f9f2d152d5db 100644 --- a/Mathlib/Analysis/MellinTransform.lean +++ b/Mathlib/Analysis/MellinTransform.lean @@ -96,7 +96,7 @@ def mellinInv (σ : ℝ) (f : ℂ → E) (x : ℝ) : E := -- next few lemmas don't require convergence of the Mellin transform (they are just 0 = 0 otherwise) theorem mellin_cpow_smul (f : ℝ → E) (s a : ℂ) : mellin (fun t => (t : ℂ) ^ a • f t) s = mellin f (s + a) := by - refine setIntegral_congr measurableSet_Ioi fun t ht => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun t ht => ?_ simp_rw [← sub_add_eq_add_sub, cpow_add _ _ (ofReal_ne_zero.2 <| ne_of_gt ht), mul_smul] theorem mellin_const_smul (f : ℝ → E) (s : ℂ) {𝕜 : Type*} [NontriviallyNormedField 𝕜] @@ -116,7 +116,7 @@ theorem mellin_comp_rpow (f : ℝ → E) (s : ℂ) (a : ℝ) : · simp [integral, mellin, hE] simp_rw [mellin] conv_rhs => rw [← integral_comp_rpow_Ioi _ ha, ← integral_smul] - refine setIntegral_congr measurableSet_Ioi fun t ht => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun t ht => ?_ dsimp only rw [← mul_smul, ← mul_assoc, inv_mul_cancel₀ (mt abs_eq_zero.1 ha), one_mul, ← smul_assoc, real_smul] @@ -135,7 +135,7 @@ theorem mellin_comp_mul_left (f : ℝ → E) (s : ℂ) {a : ℝ} (ha : 0 < a) : (by ring : 1 - s = -(s - 1)), cpow_neg, inv_mul_cancel_left₀] rw [Ne, cpow_eq_zero_iff, ofReal_eq_zero, not_and_or] exact Or.inl ha.ne' - rw [setIntegral_congr measurableSet_Ioi this, integral_smul, + rw [setIntegral_congr_fun measurableSet_Ioi this, integral_smul, integral_comp_mul_left_Ioi (fun u ↦ (u : ℂ) ^ (s - 1) • f u) _ ha, mul_zero, ← Complex.coe_smul, ← mul_smul, sub_eq_add_neg, cpow_add _ _ (ofReal_ne_zero.mpr ha.ne'), cpow_one, ofReal_inv, diff --git a/Mathlib/Analysis/Normed/Affine/AddTorsor.lean b/Mathlib/Analysis/Normed/Affine/AddTorsor.lean index caa4e080fffdf..2e2257c96f378 100644 --- a/Mathlib/Analysis/Normed/Affine/AddTorsor.lean +++ b/Mathlib/Analysis/Normed/Affine/AddTorsor.lean @@ -220,7 +220,7 @@ theorem eventually_homothety_mem_of_mem_interior (x : Q) {s : Set Q} {y : Q} (hy obtain ⟨u, hu₁, hu₂, hu₃⟩ := mem_interior.mp hy obtain ⟨ε, hε, hyε⟩ := Metric.isOpen_iff.mp hu₂ y hu₃ refine ⟨ε / ‖y -ᵥ x‖, div_pos hε hxy, fun δ (hδ : ‖δ - 1‖ < ε / ‖y -ᵥ x‖) => hu₁ (hyε ?_)⟩ - rw [lt_div_iff hxy, ← norm_smul, sub_smul, one_smul] at hδ + rw [lt_div_iff₀ hxy, ← norm_smul, sub_smul, one_smul] at hδ rwa [homothety_apply, Metric.mem_ball, dist_eq_norm_vsub W, vadd_vsub_eq_sub_vsub] theorem eventually_homothety_image_subset_of_finite_subset_interior (x : Q) {s : Set Q} {t : Set Q} diff --git a/Mathlib/Analysis/Normed/Affine/Isometry.lean b/Mathlib/Analysis/Normed/Affine/Isometry.lean index f0545ea11cc87..67f6a72b44673 100644 --- a/Mathlib/Analysis/Normed/Affine/Isometry.lean +++ b/Mathlib/Analysis/Normed/Affine/Isometry.lean @@ -69,9 +69,9 @@ theorem linear_eq_linearIsometry : f.linear = f.linearIsometry.toLinearMap := by ext rfl -instance : FunLike (P →ᵃⁱ[𝕜] P₂) P P₂ := - { coe := fun f => f.toFun, - coe_injective' := fun f g => by cases f; cases g; simp } +instance : FunLike (P →ᵃⁱ[𝕜] P₂) P P₂ where + coe f := f.toFun + coe_injective' f g := by cases f; cases g; simp @[simp] theorem coe_toAffineMap : ⇑f.toAffineMap = f := by @@ -282,16 +282,16 @@ theorem linear_eq_linear_isometry : e.linear = e.linearIsometryEquiv.toLinearEqu ext rfl -instance : EquivLike (P ≃ᵃⁱ[𝕜] P₂) P P₂ := - { coe := fun f => f.toFun - inv := fun f => f.invFun - left_inv := fun f => f.left_inv - right_inv := fun f => f.right_inv, - coe_injective' := fun f g h _ => by - cases f - cases g - congr - simpa [DFunLike.coe_injective.eq_iff] using h } +instance : EquivLike (P ≃ᵃⁱ[𝕜] P₂) P P₂ where + coe f := f.toFun + inv f := f.invFun + left_inv f := f.left_inv + right_inv f := f.right_inv + coe_injective' f g h _ := by + cases f + cases g + congr + 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/Normed/Affine/MazurUlam.lean b/Mathlib/Analysis/Normed/Affine/MazurUlam.lean index b3a9fcf2d073a..3f25c5ae3d8b8 100644 --- a/Mathlib/Analysis/Normed/Affine/MazurUlam.lean +++ b/Mathlib/Analysis/Normed/Affine/MazurUlam.lean @@ -53,7 +53,7 @@ theorem midpoint_fixed {x y : PE} : calc dist (e z) z ≤ dist (e z) x + dist x z := dist_triangle (e z) x z _ = dist (e x) (e z) + dist x z := by rw [hx, dist_comm] - _ = dist x z + dist x z := by erw [e.dist_eq x z] + _ = dist x z + dist x z := by rw [e.dist_eq x z] -- On the other hand, consider the map `f : (E ≃ᵢ E) → (E ≃ᵢ E)` -- sending each `e` to `R ∘ e⁻¹ ∘ R ∘ e`, where `R` is the point reflection in the -- midpoint `z` of `[x, y]`. diff --git a/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean b/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean index 2f0463ab0aa36..a481e6f7c4823 100644 --- a/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean +++ b/Mathlib/Analysis/Normed/Algebra/MatrixExponential.lean @@ -145,17 +145,15 @@ nonrec theorem isUnit_exp (A : Matrix m m 𝔸) : IsUnit (exp 𝕂 A) := by letI : NormedAlgebra 𝕂 (Matrix m m 𝔸) := Matrix.linftyOpNormedAlgebra exact isUnit_exp _ A --- TODO(mathlib4#6607): fix elaboration so `val` isn't needed nonrec theorem exp_units_conj (U : (Matrix m m 𝔸)ˣ) (A : Matrix m m 𝔸) : - exp 𝕂 (U.val * A * (U⁻¹).val) = U.val * exp 𝕂 A * (U⁻¹).val := by + exp 𝕂 (U * A * U⁻¹) = U * exp 𝕂 A * U⁻¹ := by letI : SeminormedRing (Matrix m m 𝔸) := Matrix.linftyOpSemiNormedRing letI : NormedRing (Matrix m m 𝔸) := Matrix.linftyOpNormedRing letI : NormedAlgebra 𝕂 (Matrix m m 𝔸) := Matrix.linftyOpNormedAlgebra exact exp_units_conj _ U A --- TODO(mathlib4#6607): fix elaboration so `val` isn't needed theorem exp_units_conj' (U : (Matrix m m 𝔸)ˣ) (A : Matrix m m 𝔸) : - exp 𝕂 ((U⁻¹).val * A * U.val) = (U⁻¹).val * exp 𝕂 A * U.val := + exp 𝕂 (U⁻¹ * A * U) = U⁻¹ * exp 𝕂 A * U := exp_units_conj 𝕂 U⁻¹ A end Normed diff --git a/Mathlib/Analysis/Normed/Algebra/Norm.lean b/Mathlib/Analysis/Normed/Algebra/Norm.lean new file mode 100644 index 0000000000000..eb815ac91298e --- /dev/null +++ b/Mathlib/Analysis/Normed/Algebra/Norm.lean @@ -0,0 +1,202 @@ +/- +Copyright (c) 2024 María Inés de Frutos-Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: María Inés de Frutos-Fernández +-/ +import Mathlib.Analysis.Normed.Ring.Seminorm +import Mathlib.Analysis.Seminorm + +/-! +# Algebra norms + +We define algebra norms and multiplicative algebra norms. + +## Main Definitions +* `AlgebraNorm` : an algebra norm on an `R`-algebra `S` is a ring norm on `S` compatible with + the action of `R`. +* `MulAlgebraNorm` : a multiplicative algebra norm on an `R`-algebra `S` is a multiplicative + ring norm on `S` compatible with the action of `R`. + +## Tags + +norm, algebra norm +-/ + +/-- An algebra norm on an `R`-algebra `S` is a ring norm on `S` compatible with the +action of `R`. -/ +structure AlgebraNorm (R : Type*) [SeminormedCommRing R] (S : Type*) [Ring S] [Algebra R S] extends + RingNorm S, Seminorm R S + +attribute [nolint docBlame] AlgebraNorm.toSeminorm AlgebraNorm.toRingNorm + +instance (K : Type*) [NormedField K] : Inhabited (AlgebraNorm K K) := + ⟨{ toFun := norm + map_zero' := norm_zero + add_le' := norm_add_le + neg' := norm_neg + smul' := norm_mul + mul_le' := norm_mul_le + eq_zero_of_map_eq_zero' := fun _ => norm_eq_zero.mp }⟩ + +/-- `AlgebraNormClass F R S` states that `F` is a type of `R`-algebra norms on the ring `S`. +You should extend this class when you extend `AlgebraNorm`. -/ +class AlgebraNormClass (F : Type*) (R : outParam <| Type*) [SeminormedCommRing R] + (S : outParam <| Type*) [Ring S] [Algebra R S] [FunLike F S ℝ] extends RingNormClass F S ℝ, + SeminormClass F R S : Prop + +namespace AlgebraNorm + +variable {R : Type*} [SeminormedCommRing R] {S : Type*} [Ring S] [Algebra R S] {f : AlgebraNorm R S} + +/-- The ring seminorm underlying an algebra norm. -/ +def toRingSeminorm' (f : AlgebraNorm R S) : RingSeminorm S := + f.toRingNorm.toRingSeminorm + +instance : FunLike (AlgebraNorm R S) S ℝ where + coe f := f.toFun + coe_injective' f f' h := by + simp only [AddGroupSeminorm.toFun_eq_coe, RingSeminorm.toFun_eq_coe] at h + cases f; cases f'; congr; + simp only at h + ext s + erw [h] + rfl + +instance algebraNormClass : AlgebraNormClass (AlgebraNorm R S) R S where + map_zero f := f.map_zero' + map_add_le_add f := f.add_le' + map_mul_le_mul f := f.mul_le' + map_neg_eq_map f := f.neg' + eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ + map_smul_eq_mul f := f.smul' + +/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun`. -/ +instance : CoeFun (AlgebraNorm R S) fun _ => S → ℝ := + DFunLike.hasCoeToFun + +theorem toFun_eq_coe (p : AlgebraNorm R S) : p.toFun = p := rfl + +@[ext] +theorem ext {p q : AlgebraNorm R S} : (∀ x, p x = q x) → p = q := + DFunLike.ext p q + +/-- An `R`-algebra norm such that `f 1 = 1` extends the norm on `R`. -/ +theorem extends_norm' (hf1 : f 1 = 1) (a : R) : f (a • (1 : S)) = ‖a‖ := by + rw [← mul_one ‖a‖, ← hf1]; exact f.smul' _ _ + +/-- An `R`-algebra norm such that `f 1 = 1` extends the norm on `R`. -/ +theorem extends_norm (hf1 : f 1 = 1) (a : R) : f (algebraMap R S a) = ‖a‖ := by + rw [Algebra.algebraMap_eq_smul_one]; exact extends_norm' hf1 _ + +/-- The restriction of an algebra norm to a subalgebra. -/ +def restriction (A : Subalgebra R S) (f : AlgebraNorm R S) : AlgebraNorm R A where + toFun := fun x : A => f x.val + map_zero' := map_zero f + add_le' x y := map_add_le_add _ _ _ + neg' x := map_neg_eq_map _ _ + mul_le' x y := map_mul_le_mul _ _ _ + eq_zero_of_map_eq_zero' x hx := by + rw [← ZeroMemClass.coe_eq_zero]; exact eq_zero_of_map_eq_zero f hx + smul' r x := map_smul_eq_mul _ _ _ + +/-- The restriction of an algebra norm in a scalar tower. -/ +def isScalarTower_restriction {A : Type*} [CommRing A] [Algebra R A] [Algebra A S] + [IsScalarTower R A S] (hinj : Function.Injective (algebraMap A S)) (f : AlgebraNorm R S) : + AlgebraNorm R A where + toFun := fun x : A => f (algebraMap A S x) + map_zero' := by simp only [map_zero] + add_le' x y := by simp only [map_add, map_add_le_add] + neg' x := by simp only [map_neg, map_neg_eq_map] + mul_le' x y := by simp only [map_mul, map_mul_le_mul] + eq_zero_of_map_eq_zero' x hx := by + rw [← map_eq_zero_iff (algebraMap A S) hinj] + exact eq_zero_of_map_eq_zero f hx + smul' r x := by + simp only [Algebra.smul_def, map_mul, ← IsScalarTower.algebraMap_apply] + simp only [← smul_eq_mul, algebraMap_smul, map_smul_eq_mul] + +end AlgebraNorm + +/-- A multiplicative algebra norm on an `R`-algebra norm `S` is a multiplicative ring norm on `S` + compatible with the action of `R`. -/ +structure MulAlgebraNorm (R : Type*) [SeminormedCommRing R] (S : Type*) [Ring S] [Algebra R S] + extends MulRingNorm S, Seminorm R S + +attribute [nolint docBlame] MulAlgebraNorm.toSeminorm MulAlgebraNorm.toMulRingNorm + +instance (K : Type*) [NormedField K] : Inhabited (MulAlgebraNorm K K) := + ⟨{ toFun := norm + map_zero' := norm_zero + add_le' := norm_add_le + neg' := norm_neg + smul' := norm_mul + map_one' := norm_one + map_mul' := norm_mul + eq_zero_of_map_eq_zero' := fun _ => norm_eq_zero.mp }⟩ + +/-- `MulAlgebraNormClass F R S` states that `F` is a type of multiplicative `R`-algebra norms on +the ring `S`. You should extend this class when you extend `MulAlgebraNorm`. -/ +class MulAlgebraNormClass (F : Type*) (R : outParam <| Type*) [SeminormedCommRing R] + (S : outParam <| Type*) [Ring S] [Algebra R S] [FunLike F S ℝ] extends MulRingNormClass F S ℝ, + SeminormClass F R S : Prop + +namespace MulAlgebraNorm + +variable {R S : outParam <| Type*} [SeminormedCommRing R] [Ring S] [Algebra R S] + {f : AlgebraNorm R S} + +instance : FunLike (MulAlgebraNorm R S) S ℝ where + coe f := f.toFun + coe_injective' f f' h:= by + simp only [AddGroupSeminorm.toFun_eq_coe, MulRingSeminorm.toFun_eq_coe, DFunLike.coe_fn_eq] at h + obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := f'; congr; + +instance mulAlgebraNormClass : MulAlgebraNormClass (MulAlgebraNorm R S) R S where + map_zero f := f.map_zero' + map_add_le_add f := f.add_le' + map_one f := f.map_one' + map_mul f := f.map_mul' + map_neg_eq_map f := f.neg' + eq_zero_of_map_eq_zero f := f.eq_zero_of_map_eq_zero' _ + map_smul_eq_mul f := f.smul' + +/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun`. -/ +instance : CoeFun (MulAlgebraNorm R S) fun _ => S → ℝ := + DFunLike.hasCoeToFun + +theorem toFun_eq_coe (p : MulAlgebraNorm R S) : p.toFun = p := rfl + +@[ext] +theorem ext {p q : MulAlgebraNorm R S} : (∀ x, p x = q x) → p = q := + DFunLike.ext p q + +/-- A multiplicative `R`-algebra norm extends the norm on `R`. -/ +theorem extends_norm' (f : MulAlgebraNorm R S) (a : R) : f (a • (1 : S)) = ‖a‖ := by + rw [← mul_one ‖a‖, ← f.map_one', ← f.smul']; rfl + +/-- A multiplicative `R`-algebra norm extends the norm on `R`. -/ +theorem extends_norm (f : MulAlgebraNorm R S) (a : R) : f (algebraMap R S a) = ‖a‖ := by + rw [Algebra.algebraMap_eq_smul_one]; exact extends_norm' _ _ + +end MulAlgebraNorm + +namespace MulRingNorm + +variable {R : Type*} [NonAssocRing R] + +/-- The ring norm underlying a multiplicative ring norm. -/ +def toRingNorm (f : MulRingNorm R) : RingNorm R where + toFun := f + map_zero' := f.map_zero' + add_le' := f.add_le' + neg' := f.neg' + mul_le' x y := le_of_eq (f.map_mul' x y) + eq_zero_of_map_eq_zero' := f.eq_zero_of_map_eq_zero' + +/-- A multiplicative ring norm is power-multiplicative. -/ +theorem isPowMul {A : Type*} [Ring A] (f : MulRingNorm A) : IsPowMul f := fun x n hn => by + cases n + · exfalso; linarith + · rw [map_pow] + +end MulRingNorm diff --git a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean index f967929332fbd..fa49b3701161c 100644 --- a/Mathlib/Analysis/Normed/Algebra/Spectrum.lean +++ b/Mathlib/Analysis/Normed/Algebra/Spectrum.lean @@ -101,7 +101,7 @@ theorem mem_resolventSet_of_norm_lt_mul {a : A} {k : 𝕜} (h : ‖a‖ * ‖(1 ne_zero_of_norm_ne_zero ((mul_nonneg (norm_nonneg _) (norm_nonneg _)).trans_lt h).ne' letI ku := Units.map ↑ₐ.toMonoidHom (Units.mk0 k hk) rw [← inv_inv ‖(1 : A)‖, - mul_inv_lt_iff (inv_pos.2 <| norm_pos_iff.2 (one_ne_zero : (1 : A) ≠ 0))] at h + mul_inv_lt_iff₀' (inv_pos.2 <| norm_pos_iff.2 (one_ne_zero : (1 : A) ≠ 0))] at h have hku : ‖-a‖ < ‖(↑ku⁻¹ : A)‖⁻¹ := by simpa [ku, norm_algebraMap] using h simpa [ku, sub_eq_add_neg, Algebra.algebraMap_eq_smul_one] using (ku.add (-a) hku).isUnit @@ -203,11 +203,9 @@ theorem spectralRadius_le_liminf_pow_nnnorm_pow_one_div (a : A) : refine ENNReal.le_of_forall_lt_one_mul_le fun ε hε => ?_ by_cases h : ε = 0 · simp only [h, zero_mul, zero_le'] - have hε' : ε⁻¹ ≠ ∞ := fun h' => - h (by simpa only [inv_inv, inv_top] using congr_arg (fun x : ℝ≥0∞ => x⁻¹) h') simp only [ENNReal.mul_le_iff_le_inv h (hε.trans_le le_top).ne, mul_comm ε⁻¹, liminf_eq_iSup_iInf_of_nat', ENNReal.iSup_mul] - conv_rhs => arg 1; intro i; rw [ENNReal.iInf_mul hε'] + conv_rhs => arg 1; intro i; rw [ENNReal.iInf_mul (by simp [h])] rw [← ENNReal.inv_lt_inv, inv_one] at hε obtain ⟨N, hN⟩ := eventually_atTop.mp (ENNReal.eventually_pow_one_div_le (ENNReal.coe_ne_top : ↑‖(1 : A)‖₊ ≠ ∞) hε) diff --git a/Mathlib/Analysis/Normed/Algebra/Unitization.lean b/Mathlib/Analysis/Normed/Algebra/Unitization.lean index 90fcffffc0c67..de8b39cdbddce 100644 --- a/Mathlib/Analysis/Normed/Algebra/Unitization.lean +++ b/Mathlib/Analysis/Normed/Algebra/Unitization.lean @@ -184,8 +184,8 @@ open scoped Uniformity Topology theorem uniformity_eq_aux : 𝓤[instUniformSpaceProd.comap <| addEquiv 𝕜 A] = 𝓤 (Unitization 𝕜 A) := by - have key : UniformInducing (addEquiv 𝕜 A) := - antilipschitzWith_addEquiv.uniformInducing lipschitzWith_addEquiv.uniformContinuous + have key : IsUniformInducing (addEquiv 𝕜 A) := + antilipschitzWith_addEquiv.isUniformInducing lipschitzWith_addEquiv.uniformContinuous rw [← key.comap_uniformity] rfl @@ -202,21 +202,24 @@ instance instUniformSpace : UniformSpace (Unitization 𝕜 A) := /-- The natural equivalence between `Unitization 𝕜 A` and `𝕜 × A` as a uniform equivalence. -/ def uniformEquivProd : (Unitization 𝕜 A) ≃ᵤ (𝕜 × A) := - Equiv.toUniformEquivOfUniformInducing (addEquiv 𝕜 A) ⟨rfl⟩ + Equiv.toUniformEquivOfIsUniformInducing (addEquiv 𝕜 A) ⟨rfl⟩ /-- The bornology on `Unitization 𝕜 A` is inherited from `𝕜 × A`. -/ instance instBornology : Bornology (Unitization 𝕜 A) := Bornology.induced <| addEquiv 𝕜 A -theorem uniformEmbedding_addEquiv {𝕜} [NontriviallyNormedField 𝕜] : - UniformEmbedding (addEquiv 𝕜 A) where +theorem isUniformEmbedding_addEquiv {𝕜} [NontriviallyNormedField 𝕜] : + IsUniformEmbedding (addEquiv 𝕜 A) where comap_uniformity := rfl inj := (addEquiv 𝕜 A).injective +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_addEquiv := isUniformEmbedding_addEquiv + /-- `Unitization 𝕜 A` is complete whenever `𝕜` and `A` are also. -/ instance instCompleteSpace [CompleteSpace 𝕜] [CompleteSpace A] : CompleteSpace (Unitization 𝕜 A) := - (completeSpace_congr uniformEmbedding_addEquiv).mpr CompleteSpace.prod + uniformEquivProd.completeSpace_iff.2 .prod /-- Pull back the metric structure from `𝕜 × (A →L[𝕜] A)` to `Unitization 𝕜 A` using the algebra homomorphism `Unitization.splitMul 𝕜 A`, but replace the bornology and the uniformity so diff --git a/Mathlib/Analysis/Normed/Algebra/UnitizationL1.lean b/Mathlib/Analysis/Normed/Algebra/UnitizationL1.lean index 4a0ab143ce2a1..bb8f42626297c 100644 --- a/Mathlib/Analysis/Normed/Algebra/UnitizationL1.lean +++ b/Mathlib/Analysis/Normed/Algebra/UnitizationL1.lean @@ -50,7 +50,7 @@ noncomputable def uniformEquiv_unitization_addEquiv_prod : instance instCompleteSpace [CompleteSpace 𝕜] [CompleteSpace A] : CompleteSpace (WithLp 1 (Unitization 𝕜 A)) := - completeSpace_congr (uniformEquiv_unitization_addEquiv_prod 𝕜 A).uniformEmbedding |>.mpr + completeSpace_congr (uniformEquiv_unitization_addEquiv_prod 𝕜 A).isUniformEmbedding |>.mpr CompleteSpace.prod variable {𝕜 A} diff --git a/Mathlib/Analysis/Normed/Field/Basic.lean b/Mathlib/Analysis/Normed/Field/Basic.lean index 56b1e27ee82ae..405b9ae12e4fa 100644 --- a/Mathlib/Analysis/Normed/Field/Basic.lean +++ b/Mathlib/Analysis/Normed/Field/Basic.lean @@ -348,7 +348,7 @@ theorem List.norm_prod_le' : ∀ {l : List α}, l ≠ [] → ‖l.prod‖ ≤ (l | [], h => (h rfl).elim | [a], _ => by simp | a::b::l, _ => by - rw [List.map_cons, List.prod_cons, @List.prod_cons _ _ _ ‖a‖] + rw [List.map_cons, List.prod_cons, List.prod_cons (a := ‖a‖)] refine le_trans (norm_mul_le _ _) (mul_le_mul_of_nonneg_left ?_ (norm_nonneg _)) exact List.norm_prod_le' (List.cons_ne_nil b l) @@ -443,6 +443,12 @@ lemma nnnorm_sub_mul_le (ha : ‖a‖₊ ≤ 1) : ‖c - a * b‖₊ ≤ ‖c - chord length is a metric on the unit complex numbers. -/ lemma nnnorm_sub_mul_le' (hb : ‖b‖₊ ≤ 1) : ‖c - a * b‖₊ ≤ ‖1 - a‖₊ + ‖c - b‖₊ := norm_sub_mul_le' hb +/-- A homomorphism `f` between semi_normed_rings is bounded if there exists a positive + constant `C` such that for all `x` in `α`, `norm (f x) ≤ C * norm x`. -/ +def RingHom.IsBounded {α : Type*} [SeminormedRing α] {β : Type*} [SeminormedRing β] + (f : α →+* β) : Prop := + ∃ C : ℝ, 0 < C ∧ ∀ x : α, norm (f x) ≤ C * norm x + end SeminormedRing section NonUnitalNormedRing @@ -586,6 +592,12 @@ instance MulOpposite.instNormedCommRing : NormedCommRing αᵐᵒᵖ where __ := instNormedRing __ := instSeminormedCommRing +/-- The restriction of a power-multiplicative function to a subalgebra is power-multiplicative. -/ +theorem IsPowMul.restriction {R S : Type*} [NormedCommRing R] [CommRing S] [Algebra R S] + (A : Subalgebra R S) {f : S → ℝ} (hf_pm : IsPowMul f) : + IsPowMul fun x : A => f x.val := fun x n hn => by + simpa [SubsemiringClass.coe_pow] using hf_pm (↑x) hn + end NormedCommRing section NormedDivisionRing @@ -689,7 +701,7 @@ lemma norm_eq_one_iff_ne_zero_of_discrete {x : 𝕜} : ‖x‖ = 1 ↔ x ≠ 0 : · push_neg at h rcases h.eq_or_lt with h|h · rw [h] - replace h := norm_inv x ▸ inv_lt_one h + replace h := norm_inv x ▸ inv_lt_one_of_one_lt₀ h rw [← inv_inj, inv_one, ← norm_inv] exact H (by simpa) h' h obtain ⟨k, hk⟩ : ∃ k : ℕ, ‖x‖ ^ k < ε := exists_pow_lt_of_lt_one εpos h @@ -838,7 +850,7 @@ def NontriviallyNormedField.ofNormNeOne {𝕜 : Type*} [h' : NormedField 𝕜] rcases hx1.lt_or_lt with hlt | hlt · use x⁻¹ rw [norm_inv] - exact one_lt_inv (norm_pos_iff.2 hx) hlt + exact (one_lt_inv₀ (norm_pos_iff.2 hx)).2 hlt · exact ⟨x, hlt⟩ instance Real.normedCommRing : NormedCommRing ℝ := @@ -887,16 +899,16 @@ theorem nnnorm_norm [SeminormedAddCommGroup α] (a : α) : ‖‖a‖‖₊ = rw [Real.nnnorm_of_nonneg (norm_nonneg a)]; rfl /-- A restatement of `MetricSpace.tendsto_atTop` in terms of the norm. -/ -theorem NormedAddCommGroup.tendsto_atTop [Nonempty α] [SemilatticeSup α] {β : Type*} - [SeminormedAddCommGroup β] {f : α → β} {b : β} : +theorem NormedAddCommGroup.tendsto_atTop [Nonempty α] [Preorder α] [IsDirected α (· ≤ ·)] + {β : Type*} [SeminormedAddCommGroup β] {f : α → β} {b : β} : Tendsto f atTop (𝓝 b) ↔ ∀ ε, 0 < ε → ∃ N, ∀ n, N ≤ n → ‖f n - b‖ < ε := (atTop_basis.tendsto_iff Metric.nhds_basis_ball).trans (by simp [dist_eq_norm]) /-- A variant of `NormedAddCommGroup.tendsto_atTop` that uses `∃ N, ∀ n > N, ...` rather than `∃ N, ∀ n ≥ N, ...` -/ -theorem NormedAddCommGroup.tendsto_atTop' [Nonempty α] [SemilatticeSup α] [NoMaxOrder α] - {β : Type*} [SeminormedAddCommGroup β] {f : α → β} {b : β} : +theorem NormedAddCommGroup.tendsto_atTop' [Nonempty α] [Preorder α] [IsDirected α (· ≤ ·)] + [NoMaxOrder α] {β : Type*} [SeminormedAddCommGroup β] {f : α → β} {b : β} : Tendsto f atTop (𝓝 b) ↔ ∀ ε, 0 < ε → ∃ N, ∀ n, N < n → ‖f n - b‖ < ε := (atTop_basis_Ioi.tendsto_iff Metric.nhds_basis_ball).trans (by simp [dist_eq_norm]) diff --git a/Mathlib/Analysis/Normed/Field/Lemmas.lean b/Mathlib/Analysis/Normed/Field/Lemmas.lean index 7b97a37837eb7..a2236fabdefec 100644 --- a/Mathlib/Analysis/Normed/Field/Lemmas.lean +++ b/Mathlib/Analysis/Normed/Field/Lemmas.lean @@ -148,7 +148,7 @@ instance Pi.normedCommutativeRing {π : ι → Type*} [Fintype ι] [∀ i, Norme end NormedCommRing -- see Note [lower instance priority] -instance (priority := 100) semi_normed_ring_top_monoid [NonUnitalSeminormedRing α] : +instance (priority := 100) NonUnitalSeminormedRing.toContinuousMul [NonUnitalSeminormedRing α] : ContinuousMul α := ⟨continuous_iff_continuousAt.2 fun x => tendsto_iff_norm_sub_tendsto_zero.2 <| by @@ -174,9 +174,37 @@ instance (priority := 100) semi_normed_ring_top_monoid [NonUnitalSeminormedRing -- see Note [lower instance priority] /-- A seminormed ring is a topological ring. -/ -instance (priority := 100) semi_normed_top_ring [NonUnitalSeminormedRing α] : +instance (priority := 100) NonUnitalSeminormedRing.toTopologicalRing [NonUnitalSeminormedRing α] : TopologicalRing α where +namespace SeparationQuotient + +instance [NonUnitalSeminormedRing α] : NonUnitalNormedRing (SeparationQuotient α) where + __ : NonUnitalRing (SeparationQuotient α) := inferInstance + __ : NormedAddCommGroup (SeparationQuotient α) := inferInstance + norm_mul := Quotient.ind₂ norm_mul_le + +instance [NonUnitalSeminormedCommRing α] : NonUnitalNormedCommRing (SeparationQuotient α) where + __ : NonUnitalCommRing (SeparationQuotient α) := inferInstance + __ : NormedAddCommGroup (SeparationQuotient α) := inferInstance + norm_mul := Quotient.ind₂ norm_mul_le + +instance [SeminormedRing α] : NormedRing (SeparationQuotient α) where + __ : Ring (SeparationQuotient α) := inferInstance + __ : NormedAddCommGroup (SeparationQuotient α) := inferInstance + norm_mul := Quotient.ind₂ norm_mul_le + +instance [SeminormedCommRing α] : NormedCommRing (SeparationQuotient α) where + __ : CommRing (SeparationQuotient α) := inferInstance + __ : NormedAddCommGroup (SeparationQuotient α) := inferInstance + norm_mul := Quotient.ind₂ norm_mul_le + +instance [SeminormedAddCommGroup α] [One α] [NormOneClass α] : + NormOneClass (SeparationQuotient α) where + norm_one := norm_one (α := α) + +end SeparationQuotient + section NormedDivisionRing variable [NormedDivisionRing α] {a : α} diff --git a/Mathlib/Analysis/Normed/Field/ProperSpace.lean b/Mathlib/Analysis/Normed/Field/ProperSpace.lean index 2c8c91cffa8cd..58a51d47a39f0 100644 --- a/Mathlib/Analysis/Normed/Field/ProperSpace.lean +++ b/Mathlib/Analysis/Normed/Field/ProperSpace.lean @@ -42,7 +42,7 @@ lemma ProperSpace.of_nontriviallyNormedField_of_weaklyLocallyCompactSpace ext simp only [mem_closedBall, dist_zero_right, Set.mem_smul_set_iff_inv_smul_mem₀ this, smul_eq_mul, norm_mul, norm_inv, norm_pow, - inv_mul_le_iff (by simpa only [norm_pow] using norm_pos_iff.mpr this)] + inv_mul_le_iff₀ (by simpa only [norm_pow] using norm_pos_iff.mpr this)] have hTop : Tendsto (fun n ↦ ‖c‖^n * r) atTop atTop := Tendsto.atTop_mul_const rpos (tendsto_pow_atTop_atTop_of_one_lt hc) exact .of_seq_closedBall hTop (Eventually.of_forall hC) diff --git a/Mathlib/Analysis/Normed/Field/UnitBall.lean b/Mathlib/Analysis/Normed/Field/UnitBall.lean index 2817b533b7761..146e37b0e5af2 100644 --- a/Mathlib/Analysis/Normed/Field/UnitBall.lean +++ b/Mathlib/Analysis/Normed/Field/UnitBall.lean @@ -51,7 +51,7 @@ def Subsemigroup.unitClosedBall (𝕜 : Type*) [NonUnitalSeminormedRing 𝕜] : carrier := closedBall 0 1 mul_mem' hx hy := by rw [mem_closedBall_zero_iff] at * - exact (norm_mul_le _ _).trans (mul_le_one hx (norm_nonneg _) hy) + exact (norm_mul_le _ _).trans (mul_le_one₀ hx (norm_nonneg _) hy) instance Metric.unitClosedBall.semigroup [NonUnitalSeminormedRing 𝕜] : Semigroup (closedBall (0 : 𝕜) 1) := diff --git a/Mathlib/Analysis/Normed/Group/Basic.lean b/Mathlib/Analysis/Normed/Group/Basic.lean index bde983756cf20..04e1413e4bea8 100644 --- a/Mathlib/Analysis/Normed/Group/Basic.lean +++ b/Mathlib/Analysis/Normed/Group/Basic.lean @@ -770,6 +770,16 @@ theorem continuous_norm' : Continuous fun a : E => ‖a‖ := by theorem continuous_nnnorm' : Continuous fun a : E => ‖a‖₊ := continuous_norm'.subtype_mk _ +set_option linter.docPrime false in +@[to_additive Inseparable.norm_eq_norm] +theorem Inseparable.norm_eq_norm' {u v : E} (h : Inseparable u v) : ‖u‖ = ‖v‖ := + h.map continuous_norm' |>.eq + +set_option linter.docPrime false in +@[to_additive Inseparable.nnnorm_eq_nnnorm] +theorem Inseparable.nnnorm_eq_nnnorm' {u v : E} (h : Inseparable u v) : ‖u‖₊ = ‖v‖₊ := + h.map continuous_nnnorm' |>.eq + @[to_additive] theorem mem_closure_one_iff_norm {x : E} : x ∈ closure ({1} : Set E) ↔ ‖x‖ = 0 := by rw [← closedBall_zero', mem_closedBall_one_iff, (norm_nonneg' x).le_iff_eq] @@ -1129,7 +1139,7 @@ theorem nnnorm_prod_le (s : Finset ι) (f : ι → E) : ‖∏ a ∈ s, f a‖ @[to_additive] theorem nnnorm_prod_le_of_le (s : Finset ι) {f : ι → E} {n : ι → ℝ≥0} (h : ∀ b ∈ s, ‖f b‖₊ ≤ n b) : ‖∏ b ∈ s, f b‖₊ ≤ ∑ b ∈ s, n b := - (norm_prod_le_of_le s h).trans_eq NNReal.coe_sum.symm + (norm_prod_le_of_le s h).trans_eq (NNReal.coe_sum ..).symm namespace Real diff --git a/Mathlib/Analysis/Normed/Group/CocompactMap.lean b/Mathlib/Analysis/Normed/Group/CocompactMap.lean index ff947f47393ef..40889eae41c45 100644 --- a/Mathlib/Analysis/Normed/Group/CocompactMap.lean +++ b/Mathlib/Analysis/Normed/Group/CocompactMap.lean @@ -5,7 +5,7 @@ Authors: Moritz Doll -/ import Mathlib.Analysis.Normed.Group.Basic -import Mathlib.Topology.ContinuousFunction.CocompactMap +import Mathlib.Topology.ContinuousMap.CocompactMap import Mathlib.Topology.MetricSpace.Bounded /-! diff --git a/Mathlib/Analysis/Normed/Group/Constructions.lean b/Mathlib/Analysis/Normed/Group/Constructions.lean index a43e9e963c9ee..c9ee9cc5d178f 100644 --- a/Mathlib/Analysis/Normed/Group/Constructions.lean +++ b/Mathlib/Analysis/Normed/Group/Constructions.lean @@ -362,7 +362,7 @@ lemma Pi.sum_norm_apply_le_norm' : ∑ i, ‖f i‖ ≤ Fintype.card ι • ‖f @[to_additive Pi.sum_nnnorm_apply_le_nnnorm "The $L^1$ norm is less than the $L^\\infty$ norm scaled by the cardinality."] lemma Pi.sum_nnnorm_apply_le_nnnorm' : ∑ i, ‖f i‖₊ ≤ Fintype.card ι • ‖f‖₊ := - NNReal.coe_sum.trans_le <| Pi.sum_norm_apply_le_norm' _ + (NNReal.coe_sum ..).trans_le <| Pi.sum_norm_apply_le_norm' _ end SeminormedGroup diff --git a/Mathlib/Analysis/Normed/Group/Hom.lean b/Mathlib/Analysis/Normed/Group/Hom.lean index 9f1984fa88764..36439765ebe21 100644 --- a/Mathlib/Analysis/Normed/Group/Hom.lean +++ b/Mathlib/Analysis/Normed/Group/Hom.lean @@ -82,7 +82,7 @@ def ofLipschitz (f : V₁ →+ V₂) {K : ℝ≥0} (h : LipschitzWith K f) : Nor instance funLike : FunLike (NormedAddGroupHom V₁ V₂) V₁ V₂ where coe := toFun - coe_injective' := fun f g h => by cases f; cases g; congr + coe_injective' f g h := by cases f; cases g; congr -- Porting note: moved this declaration up so we could get a `FunLike` instance sooner. instance toAddMonoidHomClass : AddMonoidHomClass (NormedAddGroupHom V₁ V₂) V₁ V₂ where @@ -231,7 +231,7 @@ protected theorem continuous (f : NormedAddGroupHom V₁ V₂) : Continuous f := f.uniformContinuous.continuous theorem ratio_le_opNorm (x : V₁) : ‖f x‖ / ‖x‖ ≤ ‖f‖ := - div_le_of_nonneg_of_le_mul (norm_nonneg _) f.opNorm_nonneg (le_opNorm _ _) + div_le_of_le_mul₀ (norm_nonneg _) f.opNorm_nonneg (le_opNorm _ _) /-- If one controls the norm of every `f x`, then one controls the norm of `f`. -/ theorem opNorm_le_bound {M : ℝ} (hMp : 0 ≤ M) (hM : ∀ x, ‖f x‖ ≤ M * ‖x‖) : ‖f‖ ≤ M := diff --git a/Mathlib/Analysis/Normed/Group/HomCompletion.lean b/Mathlib/Analysis/Normed/Group/HomCompletion.lean index ca780e00bbd2c..3ef2814acd733 100644 --- a/Mathlib/Analysis/Normed/Group/HomCompletion.lean +++ b/Mathlib/Analysis/Normed/Group/HomCompletion.lean @@ -132,7 +132,7 @@ theorem NormedAddCommGroup.norm_toCompl (x : G) : ‖toCompl x‖ = ‖x‖ := Completion.norm_coe x theorem NormedAddCommGroup.denseRange_toCompl : DenseRange (toCompl : G → Completion G) := - Completion.denseInducing_coe.dense + Completion.isDenseInducing_coe.dense @[simp] theorem NormedAddGroupHom.completion_toCompl (f : NormedAddGroupHom G H) : @@ -158,7 +158,7 @@ theorem NormedAddGroupHom.ker_completion {f : NormedAddGroupHom G H} {C : ℝ} rcases h.exists_pos with ⟨C', C'_pos, hC'⟩ rcases exists_pos_mul_lt ε_pos (1 + C' * ‖f‖) with ⟨δ, δ_pos, hδ⟩ obtain ⟨_, ⟨g : G, rfl⟩, hg : ‖hatg - g‖ < δ⟩ := - SeminormedAddCommGroup.mem_closure_iff.mp (Completion.denseInducing_coe.dense hatg) δ δ_pos + SeminormedAddCommGroup.mem_closure_iff.mp (Completion.isDenseInducing_coe.dense hatg) δ δ_pos obtain ⟨g' : G, hgg' : f g' = f g, hfg : ‖g'‖ ≤ C' * ‖f g‖⟩ := hC' (f g) (mem_range_self _ g) have mem_ker : g - g' ∈ f.ker := by rw [f.mem_ker, map_sub, sub_eq_zero.mpr hgg'.symm] refine ⟨_, ⟨⟨g - g', mem_ker⟩, rfl⟩, ?_⟩ diff --git a/Mathlib/Analysis/Normed/Group/Quotient.lean b/Mathlib/Analysis/Normed/Group/Quotient.lean index 085dab581687e..9acc022a5fcfb 100644 --- a/Mathlib/Analysis/Normed/Group/Quotient.lean +++ b/Mathlib/Analysis/Normed/Group/Quotient.lean @@ -156,7 +156,7 @@ theorem quotient_norm_mk_eq (S : AddSubgroup M) (m : M) : /-- The quotient norm is nonnegative. -/ theorem quotient_norm_nonneg (S : AddSubgroup M) (x : M ⧸ S) : 0 ≤ ‖x‖ := - Real.sInf_nonneg _ <| forall_mem_image.2 fun _ _ ↦ norm_nonneg _ + Real.sInf_nonneg <| forall_mem_image.2 fun _ _ ↦ norm_nonneg _ /-- The quotient norm is nonnegative. -/ theorem norm_mk_nonneg (S : AddSubgroup M) (m : M) : 0 ≤ ‖mk' S m‖ := @@ -282,9 +282,9 @@ theorem _root_.QuotientAddGroup.norm_lift_apply_le {S : AddSubgroup M} (f : Norm rcases mk_surjective x with ⟨x, rfl⟩ simpa [h] using le_opNorm f x | inr h => - rw [← not_lt, ← _root_.lt_div_iff' h, norm_lt_iff] + rw [← not_lt, ← lt_div_iff₀' h, norm_lt_iff] rintro ⟨x, rfl, hx⟩ - exact ((lt_div_iff' h).1 hx).not_le (le_opNorm f x) + exact ((lt_div_iff₀' h).1 hx).not_le (le_opNorm f x) /-- The operator norm of the projection is `1` if the subspace is not dense. -/ theorem norm_normedMk (S : AddSubgroup M) (h : (S.topologicalClosure : Set M) ≠ univ) : diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean index 2e56d519dc3b2..f63a09356056d 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp.lean @@ -56,7 +56,7 @@ instance (M : SemiNormedGrp) : SeminormedAddCommGroup M := -- Porting note (#10754): added instance instance funLike {V W : SemiNormedGrp} : FunLike (V ⟶ W) V W where coe := (forget SemiNormedGrp).map - coe_injective' := fun f g h => by cases f; cases g; congr + coe_injective' f g h := by cases f; cases g; congr instance toAddMonoidHomClass {V W : SemiNormedGrp} : AddMonoidHomClass (V ⟶ W) V W where map_add f := f.map_add' diff --git a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean index ffdb4b1697738..ca858da92cd33 100644 --- a/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean +++ b/Mathlib/Analysis/Normed/Group/SemiNormedGrp/Completion.lean @@ -102,12 +102,8 @@ instance : Preadditive SemiNormedGrp.{u} where ext -- Porting note: failing simps probably due to instance synthesis issues with concrete -- cats; see the gymnastics below for what used to be - -- simp only [add_apply, comp_apply. map_add] - rw [NormedAddGroupHom.add_apply] - -- This used to be a single `rw`, but we need `erw` after leanprover/lean4#2644 - erw [CategoryTheory.comp_apply, CategoryTheory.comp_apply, + rw [NormedAddGroupHom.add_apply, CategoryTheory.comp_apply, CategoryTheory.comp_apply, CategoryTheory.comp_apply, @NormedAddGroupHom.add_apply _ _ (_) (_)] - rfl instance : Functor.Additive completion where map_add := NormedAddGroupHom.completion_add _ _ diff --git a/Mathlib/Analysis/Normed/Group/Seminorm.lean b/Mathlib/Analysis/Normed/Group/Seminorm.lean index ca8445c51637b..06d80361d16b3 100644 --- a/Mathlib/Analysis/Normed/Group/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Group/Seminorm.lean @@ -48,7 +48,7 @@ open Set open NNReal -variable {ι R R' E F G : Type*} +variable {R R' E F G : Type*} /-- A seminorm on an additive group `G` is a function `f : G → ℝ` that preserves zero, is subadditive and such that `f (-x) = f x` for all `x`. -/ @@ -325,7 +325,7 @@ end Group section CommGroup -variable [CommGroup E] [CommGroup F] (p q : GroupSeminorm E) (x y : E) +variable [CommGroup E] [CommGroup F] (p q : GroupSeminorm E) (x : E) @[to_additive] theorem comp_mul_le (f g : F →* E) : p.comp (f * g) ≤ p.comp f + p.comp g := fun _ => @@ -381,7 +381,7 @@ end GroupSeminorm see that `SMul R ℝ` should be fixed because `ℝ` is fixed. -/ namespace AddGroupSeminorm -variable [AddGroup E] [SMul R ℝ] [SMul R ℝ≥0] [IsScalarTower R ℝ≥0 ℝ] (p : AddGroupSeminorm E) +variable [AddGroup E] [SMul R ℝ] [SMul R ℝ≥0] [IsScalarTower R ℝ≥0 ℝ] instance toOne [DecidableEq E] : One (AddGroupSeminorm E) := ⟨{ toFun := fun x => if x = 0 then 0 else 1 @@ -435,7 +435,7 @@ namespace NonarchAddGroupSeminorm section AddGroup -variable [AddGroup E] [AddGroup F] [AddGroup G] {p q : NonarchAddGroupSeminorm E} +variable [AddGroup E] {p q : NonarchAddGroupSeminorm E} instance funLike : FunLike (NonarchAddGroupSeminorm E) E ℝ where coe f := f.toFun @@ -477,7 +477,7 @@ theorem coe_le_coe : (p : E → ℝ) ≤ q ↔ p ≤ q := theorem coe_lt_coe : (p : E → ℝ) < q ↔ p < q := Iff.rfl -variable (p q) (f : F →+ E) +variable (p q) instance : Zero (NonarchAddGroupSeminorm E) := ⟨{ toFun := 0 @@ -522,7 +522,7 @@ end AddGroup section AddCommGroup -variable [AddCommGroup E] [AddCommGroup F] (p q : NonarchAddGroupSeminorm E) (x y : E) +variable [AddCommGroup E] theorem add_bddBelow_range_add {p q : NonarchAddGroupSeminorm E} {x : E} : BddBelow (range fun y => p y + q (x - y)) := @@ -653,7 +653,7 @@ namespace GroupNorm section Group -variable [Group E] [Group F] [Group G] {p q : GroupNorm E} +variable [Group E] {p q : GroupNorm E} @[to_additive] instance funLike : FunLike (GroupNorm E) E ℝ where @@ -703,7 +703,7 @@ theorem coe_le_coe : (p : E → ℝ) ≤ q ↔ p ≤ q := theorem coe_lt_coe : (p : E → ℝ) < q ↔ p < q := Iff.rfl -variable (p q) (f : F →* E) +variable (p q) @[to_additive] instance : Add (GroupNorm E) := @@ -787,7 +787,7 @@ namespace NonarchAddGroupNorm section AddGroup -variable [AddGroup E] [AddGroup F] {p q : NonarchAddGroupNorm E} +variable [AddGroup E] {p q : NonarchAddGroupNorm E} instance funLike : FunLike (NonarchAddGroupNorm E) E ℝ where coe f := f.toFun @@ -829,7 +829,7 @@ theorem coe_le_coe : (p : E → ℝ) ≤ q ↔ p ≤ q := theorem coe_lt_coe : (p : E → ℝ) < q ↔ p < q := Iff.rfl -variable (p q) (f : F →+ E) +variable (p q) instance : Sup (NonarchAddGroupNorm E) := ⟨fun p q => diff --git a/Mathlib/Analysis/Normed/Group/Ultra.lean b/Mathlib/Analysis/Normed/Group/Ultra.lean new file mode 100644 index 0000000000000..8e83b3535e430 --- /dev/null +++ b/Mathlib/Analysis/Normed/Group/Ultra.lean @@ -0,0 +1,240 @@ +/- +Copyright (c) 2024 Yakov Pechersky. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yakov Pechersky, David Loeffler +-/ +import Mathlib.Analysis.Normed.Group.Uniform +import Mathlib.Topology.Algebra.Nonarchimedean.Basic +import Mathlib.Topology.MetricSpace.Ultra.Basic + +/-! +# Ultrametric norms + +This file contains results on the behavior of norms in ultrametric groups. + +## Main results + +* `IsUltrametricDist.isUltrametricDist_of_isNonarchimedean_norm`: + a normed additive group has an ultrametric iff the norm is nonarchimedean +* `IsUltrametricDist.nonarchimedeanGroup` and its additive version: instance showing that a + commutative group with a nonarchimedean seminorm is a nonarchimedean topological group (i.e. + there is a neighbourhood basis of the identity consisting of open subgroups). + +## Implementation details + +Some results are proved first about `nnnorm : X → ℝ≥0` because the bottom element +in `NNReal` is 0, so easier to make statements about maxima of empty sets. + +## Tags + +ultrametric, nonarchimedean +-/ +open Metric NNReal + +namespace IsUltrametricDist + +section Group + +variable {S S' ι : Type*} [SeminormedGroup S] [SeminormedGroup S'] [IsUltrametricDist S] + +@[to_additive] +lemma norm_mul_le_max (x y : S) : + ‖x * y‖ ≤ max ‖x‖ ‖y‖ := by + simpa only [le_max_iff, dist_eq_norm_div, div_inv_eq_mul, div_one, one_mul] using + dist_triangle_max x 1 y⁻¹ + +@[to_additive] +lemma isUltrametricDist_of_forall_norm_mul_le_max_norm + (h : ∀ x y : S', ‖x * y‖ ≤ max ‖x‖ ‖y‖) : IsUltrametricDist S' where + dist_triangle_max x y z := by + simpa only [dist_eq_norm_div, le_max_iff, div_mul_div_cancel] using h (x / y) (y / z) + +lemma isUltrametricDist_of_isNonarchimedean_norm {S' : Type*} [SeminormedAddGroup S'] + (h : IsNonarchimedean (norm : S' → ℝ)) : IsUltrametricDist S' := + isUltrametricDist_of_forall_norm_add_le_max_norm h + +@[to_additive] +lemma nnnorm_mul_le_max (x y : S) : + ‖x * y‖₊ ≤ max ‖x‖₊ ‖y‖₊ := + norm_mul_le_max _ _ + +@[to_additive] +lemma isUltrametricDist_of_forall_nnnorm_mul_le_max_nnnorm + (h : ∀ x y : S', ‖x * y‖₊ ≤ max ‖x‖₊ ‖y‖₊) : IsUltrametricDist S' := + isUltrametricDist_of_forall_norm_mul_le_max_norm h + +lemma isUltrametricDist_of_isNonarchimedean_nnnorm {S' : Type*} [SeminormedAddGroup S'] + (h : IsNonarchimedean ((↑) ∘ (nnnorm : S' → ℝ≥0))) : IsUltrametricDist S' := + isUltrametricDist_of_forall_nnnorm_add_le_max_nnnorm h + +/-- All triangles are isosceles in an ultrametric normed group. -/ +@[to_additive "All triangles are isosceles in an ultrametric normed additive group."] +lemma norm_mul_eq_max_of_norm_ne_norm + {x y : S} (h : ‖x‖ ≠ ‖y‖) : ‖x * y‖ = max ‖x‖ ‖y‖ := by + rw [← div_inv_eq_mul, ← dist_eq_norm_div, dist_eq_max_of_dist_ne_dist _ 1 _ (by simp [h])] + simp only [dist_one_right, dist_one_left, norm_inv'] + +@[to_additive] +lemma norm_eq_of_mul_norm_lt_max {x y : S} (h : ‖x * y‖ < max ‖x‖ ‖y‖) : + ‖x‖ = ‖y‖ := + not_ne_iff.mp (h.ne ∘ norm_mul_eq_max_of_norm_ne_norm) + +/-- All triangles are isosceles in an ultrametric normed group. -/ +@[to_additive "All triangles are isosceles in an ultrametric normed additive group."] +lemma nnnorm_mul_eq_max_of_nnnorm_ne_nnnorm + {x y : S} (h : ‖x‖₊ ≠ ‖y‖₊) : ‖x * y‖₊ = max ‖x‖₊ ‖y‖₊ := by + simpa only [← NNReal.coe_inj, NNReal.coe_max] using + norm_mul_eq_max_of_norm_ne_norm (NNReal.coe_injective.ne h) + +@[to_additive] +lemma nnnorm_eq_of_mul_nnnorm_lt_max {x y : S} (h : ‖x * y‖₊ < max ‖x‖₊ ‖y‖₊) : + ‖x‖₊ = ‖y‖₊ := + not_ne_iff.mp (h.ne ∘ nnnorm_mul_eq_max_of_nnnorm_ne_nnnorm) + +/-- All triangles are isosceles in an ultrametric normed group. -/ +@[to_additive "All triangles are isosceles in an ultrametric normed additive group."] +lemma norm_div_eq_max_of_norm_div_ne_norm_div (x y z : S) (h : ‖x / y‖ ≠ ‖y / z‖) : + ‖x / z‖ = max ‖x / y‖ ‖y / z‖ := by + simpa only [div_mul_div_cancel] using norm_mul_eq_max_of_norm_ne_norm h + +/-- All triangles are isosceles in an ultrametric normed group. -/ +@[to_additive "All triangles are isosceles in an ultrametric normed additive group."] +lemma nnnorm_div_eq_max_of_nnnorm_div_ne_nnnorm_div (x y z : S) (h : ‖x / y‖₊ ≠ ‖y / z‖₊) : + ‖x / z‖₊ = max ‖x / y‖₊ ‖y / z‖₊ := by + simpa only [← NNReal.coe_inj, NNReal.coe_max] using + norm_div_eq_max_of_norm_div_ne_norm_div _ _ _ (NNReal.coe_injective.ne h) + +@[to_additive] +lemma nnnorm_pow_le (x : S) (n : ℕ) : + ‖x ^ n‖₊ ≤ ‖x‖₊ := by + induction n with + | zero => simp + | succ n hn => simpa [pow_add, hn] using nnnorm_mul_le_max (x ^ n) x + +@[to_additive] +lemma norm_pow_le (x : S) (n : ℕ) : + ‖x ^ n‖ ≤ ‖x‖ := + nnnorm_pow_le x n + +@[to_additive] +lemma nnnorm_zpow_le (x : S) (z : ℤ) : + ‖x ^ z‖₊ ≤ ‖x‖₊ := by + cases z <;> + simpa using nnnorm_pow_le _ _ + +@[to_additive] +lemma norm_zpow_le (x : S) (z : ℤ) : + ‖x ^ z‖ ≤ ‖x‖ := + nnnorm_zpow_le x z + +section nonarch + +variable (S) +/-- +In a group with an ultrametric norm, open balls around 1 of positive radius are open subgroups. +-/ +@[to_additive "In an additive group with an ultrametric norm, open balls around 0 of +positive radius are open subgroups."] +def ball_openSubgroup {r : ℝ} (hr : 0 < r) : OpenSubgroup S where + carrier := Metric.ball (1 : S) r + mul_mem' {x} {y} hx hy := by + simp only [Metric.mem_ball, dist_eq_norm_div, div_one] at hx hy ⊢ + exact (norm_mul_le_max x y).trans_lt (max_lt hx hy) + one_mem' := Metric.mem_ball_self hr + inv_mem' := by simp only [Metric.mem_ball, dist_one_right, norm_inv', imp_self, implies_true] + isOpen' := Metric.isOpen_ball + +/-- +In a group with an ultrametric norm, closed balls around 1 of positive radius are open subgroups. +-/ +@[to_additive "In an additive group with an ultrametric norm, closed balls around 0 of positive +radius are open subgroups."] +def closedBall_openSubgroup {r : ℝ} (hr : 0 < r) : OpenSubgroup S where + carrier := Metric.closedBall (1 : S) r + mul_mem' {x} {y} hx hy := by + simp only [Metric.mem_closedBall, dist_eq_norm_div, div_one] at hx hy ⊢ + exact (norm_mul_le_max x y).trans (max_le hx hy) + one_mem' := Metric.mem_closedBall_self hr.le + inv_mem' := by simp only [mem_closedBall, dist_one_right, norm_inv', imp_self, implies_true] + isOpen' := IsUltrametricDist.isOpen_closedBall _ hr.ne' + +end nonarch + +end Group + +section CommGroup + +variable {M ι : Type*} [SeminormedCommGroup M] [IsUltrametricDist M] + +/-- A commutative group with an ultrametric group seminorm is nonarchimedean (as a topological +group, i.e. every neighborhood of 1 contains an open subgroup). -/ +@[to_additive "A commutative additive group with an ultrametric group seminorm is nonarchimedean +(as a topological group, i.e. every neighborhood of 0 contains an open subgroup)."] +instance nonarchimedeanGroup : NonarchimedeanGroup M where + is_nonarchimedean := by simpa only [Metric.mem_nhds_iff] + using fun U ⟨ε, hεp, hεU⟩ ↦ ⟨ball_openSubgroup M hεp, hεU⟩ + +/-- Nonarchimedean norm of a product is less than or equal the norm of any term in the product. +This version is phrased using `Finset.sup'` and `Finset.Nonempty` due to `Finset.sup` +operating over an `OrderBot`, which `ℝ` is not. +-/ +@[to_additive "Nonarchimedean norm of a sum is less than or equal the norm of any term in the sum. +This version is phrased using `Finset.sup'` and `Finset.Nonempty` due to `Finset.sup` +operating over an `OrderBot`, which `ℝ` is not. "] +lemma _root_.Finset.Nonempty.norm_prod_le_sup'_norm {s : Finset ι} (hs : s.Nonempty) (f : ι → M) : + ‖∏ i ∈ s, f i‖ ≤ s.sup' hs (‖f ·‖) := by + simp only [Finset.le_sup'_iff] + induction hs using Finset.Nonempty.cons_induction with + | singleton j => simp only [Finset.mem_singleton, Finset.prod_singleton, exists_eq_left, le_refl] + | cons j t hj _ IH => + simp only [Finset.prod_cons, Finset.mem_cons, exists_eq_or_imp] + refine (le_total ‖∏ i ∈ t, f i‖ ‖f j‖).imp ?_ ?_ <;> intro h + · exact (norm_mul_le_max _ _).trans (max_eq_left h).le + · exact ⟨_, IH.choose_spec.left, (norm_mul_le_max _ _).trans <| + ((max_eq_right h).le.trans IH.choose_spec.right)⟩ + +/-- Nonarchimedean norm of a product is less than or equal to the largest norm of a term in the +product. -/ +@[to_additive "Nonarchimedean norm of a sum is less than or equal to the largest norm of a term in +the sum."] +lemma _root_.Finset.nnnorm_prod_le_sup_nnnorm (s : Finset ι) (f : ι → M) : + ‖∏ i ∈ s, f i‖₊ ≤ s.sup (‖f ·‖₊) := by + rcases s.eq_empty_or_nonempty with rfl|hs + · simp only [Finset.prod_empty, nnnorm_one', Finset.sup_empty, bot_eq_zero', le_refl] + · simpa only [← Finset.sup'_eq_sup hs, Finset.le_sup'_iff, coe_le_coe, coe_nnnorm'] + using hs.norm_prod_le_sup'_norm f + +/-- +Generalised ultrametric triangle inequality for finite products in commutative groups with +an ultrametric norm. +-/ +@[to_additive "Generalised ultrametric triangle inequality for finite sums in additive commutative +groups with an ultrametric norm."] +lemma nnnorm_prod_le_of_forall_le {s : Finset ι} {f : ι → M} {C : ℝ≥0} + (hC : ∀ i ∈ s, ‖f i‖₊ ≤ C) : ‖∏ i ∈ s, f i‖₊ ≤ C := + (s.nnnorm_prod_le_sup_nnnorm f).trans <| Finset.sup_le hC + +/-- +Generalised ultrametric triangle inequality for nonempty finite products in commutative groups with +an ultrametric norm. +-/ +@[to_additive "Generalised ultrametric triangle inequality for nonempty finite sums in additive +commutative groups with an ultrametric norm."] +lemma norm_prod_le_of_forall_le_of_nonempty {s : Finset ι} (hs : s.Nonempty) {f : ι → M} {C : ℝ} + (hC : ∀ i ∈ s, ‖f i‖ ≤ C) : ‖∏ i ∈ s, f i‖ ≤ C := + (hs.norm_prod_le_sup'_norm f).trans (Finset.sup'_le hs _ hC) + +/-- +Generalised ultrametric triangle inequality for finite products in commutative groups with +an ultrametric norm. +-/ +@[to_additive "Generalised ultrametric triangle inequality for finite sums in additive commutative +groups with an ultrametric norm."] +lemma norm_prod_le_of_forall_le_of_nonneg {s : Finset ι} {f : ι → M} {C : ℝ} + (h_nonneg : 0 ≤ C) (hC : ∀ i ∈ s, ‖f i‖ ≤ C) : ‖∏ i ∈ s, f i‖ ≤ C := by + lift C to NNReal using h_nonneg + exact nnnorm_prod_le_of_forall_le hC + +end CommGroup + +end IsUltrametricDist diff --git a/Mathlib/Analysis/Normed/Group/Uniform.lean b/Mathlib/Analysis/Normed/Group/Uniform.lean index 7ec9757016b86..f8e72a4535b45 100644 --- a/Mathlib/Analysis/Normed/Group/Uniform.lean +++ b/Mathlib/Analysis/Normed/Group/Uniform.lean @@ -365,6 +365,29 @@ instance (priority := 100) SeminormedCommGroup.to_uniformGroup : UniformGroup E instance (priority := 100) SeminormedCommGroup.toTopologicalGroup : TopologicalGroup E := inferInstance +/-! ### SeparationQuotient -/ + +namespace SeparationQuotient + +@[to_additive instNorm] +instance instMulNorm : Norm (SeparationQuotient E) where + norm := lift Norm.norm fun _ _ h => h.norm_eq_norm' + +set_option linter.docPrime false in +@[to_additive (attr := simp) norm_mk] +theorem norm_mk' (p : E) : ‖mk p‖ = ‖p‖ := rfl + +@[to_additive] +instance : NormedCommGroup (SeparationQuotient E) where + __ : CommGroup (SeparationQuotient E) := instCommGroup + dist_eq := Quotient.ind₂ dist_eq_norm_div + +set_option linter.docPrime false in +@[to_additive (attr := simp) nnnorm_mk] +theorem nnnorm_mk' (p : E) : ‖mk p‖₊ = ‖p‖₊ := rfl + +end SeparationQuotient + @[to_additive] theorem cauchySeq_prod_of_eventually_eq {u v : ℕ → E} {N : ℕ} (huv : ∀ n ≥ N, u n = v n) (hv : CauchySeq fun n => ∏ k ∈ range (n + 1), v k) : diff --git a/Mathlib/Analysis/Normed/Group/ZeroAtInfty.lean b/Mathlib/Analysis/Normed/Group/ZeroAtInfty.lean index a2cabd37f31d1..825bb7c7941a6 100644 --- a/Mathlib/Analysis/Normed/Group/ZeroAtInfty.lean +++ b/Mathlib/Analysis/Normed/Group/ZeroAtInfty.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Moritz Doll -/ -import Mathlib.Topology.ContinuousFunction.ZeroAtInfty +import Mathlib.Topology.ContinuousMap.ZeroAtInfty /-! # ZeroAtInftyContinuousMapClass in normed additive groups diff --git a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean index 8be09ea3634f1..144ad83e536db 100644 --- a/Mathlib/Analysis/Normed/Lp/LpEquiv.lean +++ b/Mathlib/Analysis/Normed/Lp/LpEquiv.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Analysis.Normed.Lp.lpSpace import Mathlib.Analysis.Normed.Lp.PiLp -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded /-! # Equivalences among $L^p$ spaces diff --git a/Mathlib/Analysis/Normed/Lp/PiLp.lean b/Mathlib/Analysis/Normed/Lp/PiLp.lean index aed43fb34f51d..decc915289980 100644 --- a/Mathlib/Analysis/Normed/Lp/PiLp.lean +++ b/Mathlib/Analysis/Normed/Lp/PiLp.lean @@ -354,7 +354,7 @@ abbrev pseudoMetricAux : PseudoMetricSpace (PiLp p α) := PseudoMetricSpace.edist_dist] -- Porting note: `le_iSup` needed some help exact le_iSup (fun k => edist (f k) (g k)) i - · refine ENNReal.toReal_le_of_le_ofReal (Real.sSup_nonneg _ ?_) (iSup_le fun i => ?_) + · refine ENNReal.toReal_le_of_le_ofReal (Real.sSup_nonneg ?_) (iSup_le fun i => ?_) · rintro - ⟨i, rfl⟩ exact dist_nonneg · change PseudoMetricSpace.edist _ _ ≤ _ @@ -413,8 +413,8 @@ theorem antilipschitzWith_equiv_aux : rw [this, ENNReal.coe_rpow_of_nonneg _ nonneg] theorem aux_uniformity_eq : 𝓤 (PiLp p β) = 𝓤[Pi.uniformSpace _] := by - have A : UniformInducing (WithLp.equiv p (∀ i, β i)) := - (antilipschitzWith_equiv_aux p β).uniformInducing + have A : IsUniformInducing (WithLp.equiv p (∀ i, β i)) := + (antilipschitzWith_equiv_aux p β).isUniformInducing (lipschitzWith_equiv_aux p β).uniformContinuous have : (fun x : PiLp p β × PiLp p β => (WithLp.equiv p _ x.fst, WithLp.equiv p _ x.snd)) = id := by ext i <;> rfl diff --git a/Mathlib/Analysis/Normed/Lp/ProdLp.lean b/Mathlib/Analysis/Normed/Lp/ProdLp.lean index 9cc05f4783196..23d86ced09013 100644 --- a/Mathlib/Analysis/Normed/Lp/ProdLp.lean +++ b/Mathlib/Analysis/Normed/Lp/ProdLp.lean @@ -424,8 +424,8 @@ theorem prod_antilipschitzWith_equiv_aux [PseudoEMetricSpace α] [PseudoEMetricS theorem prod_aux_uniformity_eq [PseudoEMetricSpace α] [PseudoEMetricSpace β] : 𝓤 (WithLp p (α × β)) = 𝓤[instUniformSpaceProd] := by - have A : UniformInducing (WithLp.equiv p (α × β)) := - (prod_antilipschitzWith_equiv_aux p α β).uniformInducing + have A : IsUniformInducing (WithLp.equiv p (α × β)) := + (prod_antilipschitzWith_equiv_aux p α β).isUniformInducing (prod_lipschitzWith_equiv_aux p α β).uniformContinuous have : (fun x : WithLp p (α × β) × WithLp p (α × β) => ((WithLp.equiv p (α × β)) x.fst, (WithLp.equiv p (α × β)) x.snd)) = id := by diff --git a/Mathlib/Analysis/Normed/Module/Basic.lean b/Mathlib/Analysis/Normed/Module/Basic.lean index a14d459bc6280..d1bb26f18316d 100644 --- a/Mathlib/Analysis/Normed/Module/Basic.lean +++ b/Mathlib/Analysis/Normed/Module/Basic.lean @@ -119,6 +119,9 @@ instance Pi.normedSpace {ι : Type*} {E : ι → Type*} [Fintype ι] [∀ i, Sem NNReal.mul_finset_sup] exact Finset.sup_mono_fun fun _ _ => norm_smul_le a _ +instance SeparationQuotient.instNormedSpace : NormedSpace 𝕜 (SeparationQuotient E) where + norm_smul_le := norm_smul_le + instance MulOpposite.instNormedSpace : NormedSpace 𝕜 Eᵐᵒᵖ where norm_smul_le _ x := norm_smul_le _ x.unop @@ -186,7 +189,7 @@ theorem NormedSpace.exists_lt_norm (c : ℝ) : ∃ x : E, c < ‖x‖ := by rcases exists_ne (0 : E) with ⟨x, hx⟩ rcases NormedField.exists_lt_norm 𝕜 (c / ‖x‖) with ⟨r, hr⟩ use r • x - rwa [norm_smul, ← _root_.div_lt_iff] + rwa [norm_smul, ← div_lt_iff₀] rwa [norm_pos_iff] protected theorem NormedSpace.unbounded_univ : ¬Bornology.IsBounded (univ : Set E) := fun h => @@ -348,6 +351,10 @@ instance Pi.normedAlgebra {ι : Type*} {E : ι → Type*} [Fintype ι] [∀ i, S variable [SeminormedRing E] [NormedAlgebra 𝕜 E] +instance SeparationQuotient.instNormedAlgebra : NormedAlgebra 𝕜 (SeparationQuotient E) where + __ : NormedSpace 𝕜 (SeparationQuotient E) := inferInstance + __ : Algebra 𝕜 (SeparationQuotient E) := inferInstance + instance MulOpposite.instNormedAlgebra {E : Type*} [SeminormedRing E] [NormedAlgebra 𝕜 E] : NormedAlgebra 𝕜 Eᵐᵒᵖ where __ := instAlgebra diff --git a/Mathlib/Analysis/Normed/Module/Completion.lean b/Mathlib/Analysis/Normed/Module/Completion.lean index 451aed37e833c..f0a8fdeed667d 100644 --- a/Mathlib/Analysis/Normed/Module/Completion.lean +++ b/Mathlib/Analysis/Normed/Module/Completion.lean @@ -27,20 +27,16 @@ namespace UniformSpace namespace Completion -variable (𝕜 E : Type*) [NormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] +variable (𝕜 E : Type*) -instance (priority := 100) NormedSpace.to_uniformContinuousConstSMul : - UniformContinuousConstSMul 𝕜 E := - ⟨fun c => (lipschitzWith_smul c).uniformContinuous⟩ +instance [NormedField 𝕜] [SeminormedAddCommGroup E] [NormedSpace 𝕜 E] : + NormedSpace 𝕜 (Completion E) where + norm_smul_le := norm_smul_le -instance : NormedSpace 𝕜 (Completion E) := - { Completion.instModule with - norm_smul_le := fun c x => - induction_on x - (isClosed_le (continuous_const_smul _).norm (continuous_const.mul continuous_norm)) fun y => - by simp only [← coe_smul, norm_coe, norm_smul, le_rfl] } +section Module variable {𝕜 E} +variable [Semiring 𝕜] [SeminormedAddCommGroup E] [Module 𝕜 E] [UniformContinuousConstSMul 𝕜 E] /-- Embedding of a normed space to its completion as a linear isometry. -/ def toComplₗᵢ : E →ₗᵢ[𝕜] Completion E := @@ -66,46 +62,35 @@ theorem norm_toComplL {𝕜 E : Type*} [NontriviallyNormedField 𝕜] [NormedAdd [NormedSpace 𝕜 E] [Nontrivial E] : ‖(toComplL : E →L[𝕜] Completion E)‖ = 1 := (toComplₗᵢ : E →ₗᵢ[𝕜] Completion E).norm_toContinuousLinearMap +end Module + section Algebra -variable (𝕜) (A : Type*) - -instance [SeminormedRing A] : NormedRing (Completion A) := - { Completion.ring, - Completion.instMetricSpace with - dist_eq := fun x y => by - refine Completion.induction_on₂ x y ?_ ?_ <;> clear x y - · refine isClosed_eq (Completion.uniformContinuous_extension₂ _).continuous ?_ - exact Continuous.comp Completion.continuous_extension continuous_sub - · intro x y - rw [← Completion.coe_sub, norm_coe, Completion.dist_eq, dist_eq_norm] - norm_mul := fun x y => by - refine Completion.induction_on₂ x y ?_ ?_ <;> clear x y - · exact - isClosed_le (Continuous.comp continuous_norm continuous_mul) - (Continuous.comp _root_.continuous_mul - (Continuous.prod_map continuous_norm continuous_norm)) - · intro x y - simp only [← coe_mul, norm_coe] - exact norm_mul_le x y } - -instance [SeminormedCommRing A] [NormedAlgebra 𝕜 A] [UniformContinuousConstSMul 𝕜 A] : - NormedAlgebra 𝕜 (Completion A) := - { Completion.algebra A 𝕜 with - norm_smul_le := fun r x => by - refine Completion.induction_on x ?_ ?_ <;> clear x - · exact - isClosed_le (Continuous.comp continuous_norm (continuous_const_smul r)) - (Continuous.comp (continuous_mul_left _) continuous_norm) - · intro x - simp only [← coe_smul, norm_coe] - exact norm_smul_le r x } +variable (A : Type*) + +instance [SeminormedRing A] : NormedRing (Completion A) where + __ : NormedAddCommGroup (Completion A) := inferInstance + __ : Ring (Completion A) := inferInstance + norm_mul x y := by + induction x, y using induction_on₂ with + | hp => + apply isClosed_le <;> fun_prop + | ih x y => + simp only [← coe_mul, norm_coe] + exact norm_mul_le x y + +instance [SeminormedCommRing A] : NormedCommRing (Completion A) where + __ : CommRing (Completion A) := inferInstance + __ : NormedRing (Completion A) := inferInstance + +instance [NormedField 𝕜] [SeminormedCommRing A] [NormedAlgebra 𝕜 A] : + NormedAlgebra 𝕜 (Completion A) where + norm_smul_le := norm_smul_le instance [NormedField A] [CompletableTopField A] : NormedField (UniformSpace.Completion A) where - dist_eq x y := by - refine induction_on₂ x y ?_ (by simp [← coe_sub, dist_eq_norm]) - exact isClosed_eq (uniformContinuous_extension₂ _).continuous (by fun_prop) + __ : NormedCommRing (Completion A) := inferInstance + __ : Field (Completion A) := inferInstance norm_mul' x y := induction_on₂ x y (isClosed_eq (by fun_prop) (by fun_prop)) (by simp [← coe_mul]) end Algebra diff --git a/Mathlib/Analysis/Normed/Module/Dual.lean b/Mathlib/Analysis/Normed/Module/Dual.lean index 2892b13b82927..f8115711046c5 100644 --- a/Mathlib/Analysis/Normed/Module/Dual.lean +++ b/Mathlib/Analysis/Normed/Module/Dual.lean @@ -212,7 +212,7 @@ theorem polar_ball_subset_closedBall_div {c : 𝕜} (hc : 1 < ‖c‖) {r : ℝ} refine ContinuousLinearMap.opNorm_le_of_shell hr hcr.le hc fun x h₁ h₂ => ?_ calc ‖x' x‖ ≤ 1 := hx' _ h₂ - _ ≤ ‖c‖ / r * ‖x‖ := (inv_pos_le_iff_one_le_mul' hcr).1 (by rwa [inv_div]) + _ ≤ ‖c‖ / r * ‖x‖ := (inv_le_iff_one_le_mul₀' hcr).1 (by rwa [inv_div]) variable (𝕜) @@ -245,11 +245,11 @@ theorem polar_ball {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [Normed intro a ha rw [← mem_closedBall_zero_iff, ← (mul_div_cancel_left₀ a (Ne.symm (ne_of_lt hr)))] rw [← RCLike.norm_of_nonneg (K := 𝕜) (le_trans zero_le_one - (le_of_lt ((inv_pos_lt_iff_one_lt_mul' hr).mp ha)))] + (le_of_lt ((inv_lt_iff_one_lt_mul₀' hr).mp ha)))] apply polar_ball_subset_closedBall_div _ hr hx rw [RCLike.norm_of_nonneg (K := 𝕜) (le_trans zero_le_one - (le_of_lt ((inv_pos_lt_iff_one_lt_mul' hr).mp ha)))] - exact (inv_pos_lt_iff_one_lt_mul' hr).mp ha + (le_of_lt ((inv_lt_iff_one_lt_mul₀' hr).mp ha)))] + exact (inv_lt_iff_one_lt_mul₀' hr).mp ha · rw [← polar_closedBall hr] exact LinearMap.polar_antitone _ ball_subset_closedBall diff --git a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean index 4c55f7d09dafa..4735888f210dd 100644 --- a/Mathlib/Analysis/Normed/Module/FiniteDimension.lean +++ b/Mathlib/Analysis/Normed/Module/FiniteDimension.lean @@ -48,7 +48,7 @@ universe u v w x noncomputable section -open Set FiniteDimensional TopologicalSpace Filter Asymptotics Topology NNReal Metric +open Asymptotics Filter Module Metric Module NNReal Set TopologicalSpace Topology namespace LinearIsometry @@ -323,14 +323,14 @@ theorem Basis.exists_opNorm_le {ι : Type*} [Finite ι] (v : Basis ι 𝕜 E) : instance [FiniteDimensional 𝕜 E] [SecondCountableTopology F] : SecondCountableTopology (E →L[𝕜] F) := by - set d := FiniteDimensional.finrank 𝕜 E + set d := Module.finrank 𝕜 E suffices ∀ ε > (0 : ℝ), ∃ n : (E →L[𝕜] F) → Fin d → ℕ, ∀ f g : E →L[𝕜] F, n f = n g → dist f g ≤ ε from Metric.secondCountable_of_countable_discretization fun ε ε_pos => ⟨Fin d → ℕ, by infer_instance, this ε ε_pos⟩ intro ε ε_pos obtain ⟨u : ℕ → F, hu : DenseRange u⟩ := exists_dense_seq F - let v := FiniteDimensional.finBasis 𝕜 E + let v := Module.finBasis 𝕜 E obtain ⟨C : ℝ, C_pos : 0 < C, hC : ∀ {φ : E →L[𝕜] F} {M : ℝ}, 0 ≤ M → (∀ i, ‖φ (v i)‖ ≤ M) → ‖φ‖ ≤ C * M⟩ := @@ -647,7 +647,7 @@ theorem summable_norm_iff {α E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ refine ⟨Summable.of_norm, fun hf ↦ ?_⟩ -- First we use a finite basis to reduce the problem to the case `E = Fin N → ℝ` suffices ∀ {N : ℕ} {g : α → Fin N → ℝ}, Summable g → Summable fun x => ‖g x‖ by - obtain v := finBasis ℝ E + obtain v := Module.finBasis ℝ E set e := v.equivFunL have H : Summable fun x => ‖e (f x)‖ := this (e.summable.2 hf) refine .of_norm_bounded _ (H.mul_left ↑‖(e.symm : (Fin (finrank ℝ E) → ℝ) →L[ℝ] E)‖₊) fun i ↦ ?_ diff --git a/Mathlib/Analysis/Normed/MulAction.lean b/Mathlib/Analysis/Normed/MulAction.lean index 1c42cc236b1e9..2c9c706fdb6c1 100644 --- a/Mathlib/Analysis/Normed/MulAction.lean +++ b/Mathlib/Analysis/Normed/MulAction.lean @@ -5,6 +5,7 @@ Authors: Eric Wieser -/ import Mathlib.Analysis.Normed.Field.Basic import Mathlib.Topology.MetricSpace.Algebra +import Mathlib.Topology.Algebra.UniformMulAction /-! # Lemmas for `BoundedSMul` over normed additive groups diff --git a/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean b/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean index eedbaba72b905..64c5ba0eb60b5 100644 --- a/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean +++ b/Mathlib/Analysis/Normed/Operator/ContinuousLinearMap.lean @@ -153,9 +153,13 @@ variable [Ring 𝕜] [Ring 𝕜₂] variable [NormedAddCommGroup E] [NormedAddCommGroup F] [Module 𝕜 E] [Module 𝕜₂ F] variable {σ : 𝕜 →+* 𝕜₂} (f g : E →SL[σ] F) (x y z : E) -theorem ContinuousLinearMap.uniformEmbedding_of_bound {K : ℝ≥0} (hf : ∀ x, ‖x‖ ≤ K * ‖f x‖) : - UniformEmbedding f := - (AddMonoidHomClass.antilipschitz_of_bound f hf).uniformEmbedding f.uniformContinuous +theorem ContinuousLinearMap.isUniformEmbedding_of_bound {K : ℝ≥0} (hf : ∀ x, ‖x‖ ≤ K * ‖f x‖) : + IsUniformEmbedding f := + (AddMonoidHomClass.antilipschitz_of_bound f hf).isUniformEmbedding f.uniformContinuous + +@[deprecated (since := "2024-10-01")] +alias ContinuousLinearMap.uniformEmbedding_of_bound := + ContinuousLinearMap.isUniformEmbedding_of_bound end Normed diff --git a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean index 578fd81859e6d..92b76035981f0 100644 --- a/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean +++ b/Mathlib/Analysis/Normed/Operator/LinearIsometry.lean @@ -205,10 +205,12 @@ theorem nnnorm_map (x : E) : ‖f x‖₊ = ‖x‖₊ := protected theorem isometry : Isometry f := AddMonoidHomClass.isometry_of_norm f.toLinearMap (norm_map _) +protected lemma embedding (f : F →ₛₗᵢ[σ₁₂] E₂) : Embedding f := f.isometry.embedding + -- Should be `@[simp]` but it doesn't fire due to `lean4#3107`. theorem isComplete_image_iff [SemilinearIsometryClass 𝓕 σ₁₂ E E₂] (f : 𝓕) {s : Set E} : IsComplete (f '' s) ↔ IsComplete s := - _root_.isComplete_image_iff (SemilinearIsometryClass.isometry f).uniformInducing + _root_.isComplete_image_iff (SemilinearIsometryClass.isometry f).isUniformInducing @[simp] -- Should be replaced with `LinearIsometry.isComplete_image_iff` when `lean4#3107` is fixed. theorem isComplete_image_iff' (f : LinearIsometry σ₁₂ E E₂) {s : Set E} : diff --git a/Mathlib/Analysis/Normed/Ring/IsPowMulFaithful.lean b/Mathlib/Analysis/Normed/Ring/IsPowMulFaithful.lean new file mode 100644 index 0000000000000..f460ba8405dda --- /dev/null +++ b/Mathlib/Analysis/Normed/Ring/IsPowMulFaithful.lean @@ -0,0 +1,96 @@ +/- +Copyright (c) 2024 María Inés de Frutos-Fernández. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: María Inés de Frutos-Fernández +-/ +import Mathlib.Analysis.Normed.Algebra.Norm +import Mathlib.Analysis.SpecialFunctions.Pow.Continuity + +/-! +# Equivalent power-multiplicative norms + +In this file, we prove [BGR, Proposition 3.1.5/1][bosch-guntzer-remmert]: if `R` is a normed +commutative ring and `f₁` and `f₂` are two power-multiplicative `R`-algebra norms on `S`, then if +`f₁` and `f₂` are equivalent on every subring `R[y]` for `y : S`, it follows that `f₁ = f₂`. + +## Main Results +* `eq_of_powMul_faithful` : the proof of [BGR, Proposition 3.1.5/1][bosch-guntzer-remmert]. + +## References +* [S. Bosch, U. Güntzer, R. Remmert, *Non-Archimedean Analysis*][bosch-guntzer-remmert] + +## Tags + +norm, equivalent, power-multiplicative +-/ + +open Filter Real +open scoped Topology + +/-- If `f : α →+* β` is bounded with respect to a ring seminorm `nα` on `α` and a + power-multiplicative function `nβ : β → ℝ`, then `∀ x : α, nβ (f x) ≤ nα x`. -/ +theorem contraction_of_isPowMul_of_boundedWrt {F : Type*} {α : outParam (Type*)} [Ring α] + [FunLike F α ℝ] [RingSeminormClass F α ℝ] {β : Type*} [Ring β] (nα : F) {nβ : β → ℝ} + (hβ : IsPowMul nβ) {f : α →+* β} (hf : f.IsBoundedWrt nα nβ) (x : α) : nβ (f x) ≤ nα x := by + obtain ⟨C, hC0, hC⟩ := hf + have hlim : Tendsto (fun n : ℕ => C ^ (1 / (n : ℝ)) * nα x) atTop (𝓝 (nα x)) := by + nth_rewrite 2 [← one_mul (nα x)] + exact ((rpow_zero C ▸ ContinuousAt.tendsto (continuousAt_const_rpow (ne_of_gt hC0))).comp + (tendsto_const_div_atTop_nhds_zero_nat 1)).mul tendsto_const_nhds + apply ge_of_tendsto hlim + simp only [eventually_atTop, ge_iff_le] + use 1 + intro n hn + have h : (C ^ (1 / n : ℝ)) ^ n = C := by + have hn0 : (n : ℝ) ≠ 0 := Nat.cast_ne_zero.mpr (ne_of_gt hn) + rw [← rpow_natCast, ← rpow_mul (le_of_lt hC0), one_div, inv_mul_cancel₀ hn0, rpow_one] + apply le_of_pow_le_pow_left (ne_of_gt hn) + (mul_nonneg (rpow_nonneg (le_of_lt hC0) _) (apply_nonneg _ _)) + · rw [mul_pow, h, ← hβ _ hn, ← RingHom.map_pow] + apply le_trans (hC (x ^ n)) + rw [mul_le_mul_left hC0] + exact map_pow_le_pow _ _ (Nat.one_le_iff_ne_zero.mp hn) + +/-- Given a bounded `f : α →+* β` between seminormed rings, is the seminorm on `β` is + power-multiplicative, then `f` is a contraction. -/ +theorem contraction_of_isPowMul {α β : Type*} [SeminormedRing α] [SeminormedRing β] + (hβ : IsPowMul (norm : β → ℝ)) {f : α →+* β} (hf : f.IsBounded) (x : α) : norm (f x) ≤ norm x := + contraction_of_isPowMul_of_boundedWrt (SeminormedRing.toRingSeminorm α) hβ hf x + +/-- Given two power-multiplicative ring seminorms `f, g` on `α`, if `f` is bounded by a positive + multiple of `g` and vice versa, then `f = g`. -/ +theorem eq_seminorms {F : Type*} {α : outParam (Type*)} [Ring α] [FunLike F α ℝ] + [RingSeminormClass F α ℝ] {f g : F} (hfpm : IsPowMul f) (hgpm : IsPowMul g) + (hfg : ∃ (r : ℝ) (_ : 0 < r), ∀ a : α, f a ≤ r * g a) + (hgf : ∃ (r : ℝ) (_ : 0 < r), ∀ a : α, g a ≤ r * f a) : f = g := by + obtain ⟨r, hr0, hr⟩ := hfg + obtain ⟨s, hs0, hs⟩ := hgf + have hle : RingHom.IsBoundedWrt f g (RingHom.id _) := ⟨s, hs0, hs⟩ + have hge : RingHom.IsBoundedWrt g f (RingHom.id _) := ⟨r, hr0, hr⟩ + rw [← Function.Injective.eq_iff DFunLike.coe_injective'] + ext x + exact le_antisymm (contraction_of_isPowMul_of_boundedWrt g hfpm hge x) + (contraction_of_isPowMul_of_boundedWrt f hgpm hle x) + +variable {R S : Type*} [NormedCommRing R] [CommRing S] [Algebra R S] + +/-- If `R` is a normed commutative ring and `f₁` and `f₂` are two power-multiplicative `R`-algebra + norms on `S`, then if `f₁` and `f₂` are equivalent on every subring `R[y]` for `y : S`, it + follows that `f₁ = f₂` [BGR, Proposition 3.1.5/1][bosch-guntzer-remmert]. -/ +theorem eq_of_powMul_faithful (f₁ : AlgebraNorm R S) (hf₁_pm : IsPowMul f₁) (f₂ : AlgebraNorm R S) + (hf₂_pm : IsPowMul f₂) + (h_eq : ∀ y : S, ∃ (C₁ C₂ : ℝ) (_ : 0 < C₁) (_ : 0 < C₂), + ∀ x : Algebra.adjoin R {y}, f₁ x.val ≤ C₁ * f₂ x.val ∧ f₂ x.val ≤ C₂ * f₁ x.val) : + f₁ = f₂ := by + ext x + set g₁ : AlgebraNorm R (Algebra.adjoin R ({x} : Set S)) := AlgebraNorm.restriction _ f₁ + set g₂ : AlgebraNorm R (Algebra.adjoin R ({x} : Set S)) := AlgebraNorm.restriction _ f₂ + have hg₁_pm : IsPowMul g₁ := IsPowMul.restriction _ hf₁_pm + have hg₂_pm : IsPowMul g₂ := IsPowMul.restriction _ hf₂_pm + let y : Algebra.adjoin R ({x} : Set S) := ⟨x, Algebra.self_mem_adjoin_singleton R x⟩ + have hy : x = y.val := rfl + have h1 : f₁ y.val = g₁ y := rfl + have h2 : f₂ y.val = g₂ y := rfl + obtain ⟨C₁, C₂, hC₁_pos, hC₂_pos, hC⟩ := h_eq x + obtain ⟨hC₁, hC₂⟩ := forall_and.mp hC + rw [hy, h1, h2, eq_seminorms hg₁_pm hg₂_pm ⟨C₁, hC₁_pos, hC₁⟩ ⟨C₂, hC₂_pos, hC₂⟩] diff --git a/Mathlib/Analysis/Normed/Ring/Seminorm.lean b/Mathlib/Analysis/Normed/Ring/Seminorm.lean index 2f18c14fb0172..650ace74daac1 100644 --- a/Mathlib/Analysis/Normed/Ring/Seminorm.lean +++ b/Mathlib/Analysis/Normed/Ring/Seminorm.lean @@ -151,6 +151,26 @@ end Ring end RingSeminorm +/-- If `f` is a ring seminorm on `a`, then `∀ {n : ℕ}, n ≠ 0 → f (a ^ n) ≤ f a ^ n`. -/ +theorem map_pow_le_pow {F α : Type*} [Ring α] [FunLike F α ℝ] [RingSeminormClass F α ℝ] (f : F) + (a : α) : ∀ {n : ℕ}, n ≠ 0 → f (a ^ n) ≤ f a ^ n + | 0, h => absurd rfl h + | 1, _ => by simp only [pow_one, le_refl] + | n + 2, _ => by + simp only [pow_succ _ (n + 1)]; + exact + le_trans (map_mul_le_mul f _ a) + (mul_le_mul_of_nonneg_right (map_pow_le_pow _ _ n.succ_ne_zero) (apply_nonneg f a)) + +/-- If `f` is a ring seminorm on `a` with `f 1 ≤ 1`, then `∀ (n : ℕ), f (a ^ n) ≤ f a ^ n`. -/ +theorem map_pow_le_pow' {F α : Type*} [Ring α] [FunLike F α ℝ] [RingSeminormClass F α ℝ] {f : F} + (hf1 : f 1 ≤ 1) (a : α) : ∀ n : ℕ, f (a ^ n) ≤ f a ^ n + | 0 => by simp only [pow_zero, hf1] + | n + 1 => by + simp only [pow_succ _ n]; + exact le_trans (map_mul_le_mul f _ a) + (mul_le_mul_of_nonneg_right (map_pow_le_pow' hf1 _ n) (apply_nonneg f a)) + /-- The norm of a `NonUnitalSeminormedRing` as a `RingSeminorm`. -/ def normRingSeminorm (R : Type*) [NonUnitalSeminormedRing R] : RingSeminorm R := { normAddGroupSeminorm R with @@ -368,3 +388,36 @@ lemma MulRingNorm.apply_natAbs_eq {R : Type*} [Ring R] (x : ℤ) (f : MulRingNor f x := by obtain ⟨n, rfl | rfl⟩ := eq_nat_or_neg x <;> simp only [natAbs_neg, natAbs_ofNat, cast_neg, cast_natCast, map_neg_eq_map] + +/-- The seminorm on a `SeminormedRing`, as a `RingSeminorm`. -/ +def SeminormedRing.toRingSeminorm (R : Type*) [SeminormedRing R] : RingSeminorm R where + toFun := norm + map_zero' := norm_zero + add_le' := norm_add_le + mul_le' := norm_mul_le + neg' := norm_neg + +/-- The norm on a `NormedRing`, as a `RingNorm`. -/ +@[simps] +def NormedRing.toRingNorm (R : Type*) [NormedRing R] : RingNorm R where + toFun := norm + map_zero' := norm_zero + add_le' := norm_add_le + mul_le' := norm_mul_le + neg' := norm_neg + eq_zero_of_map_eq_zero' x hx := by rw [← norm_eq_zero]; exact hx + +@[simp] +theorem NormedRing.toRingNorm_apply (R : Type*) [NormedRing R] (x : R) : + (NormedRing.toRingNorm R) x = ‖x‖ := + rfl + +/-- The norm on a `NormedField`, as a `MulRingNorm`. -/ +def NormedField.toMulRingNorm (R : Type*) [NormedField R] : MulRingNorm R where + toFun := norm + map_zero' := norm_zero + map_one' := norm_one + add_le' := norm_add_le + map_mul' := norm_mul + neg' := norm_neg + eq_zero_of_map_eq_zero' x hx := by rw [← norm_eq_zero]; exact hx diff --git a/Mathlib/Analysis/Normed/Ring/Ultra.lean b/Mathlib/Analysis/Normed/Ring/Ultra.lean new file mode 100644 index 0000000000000..1e8016ac72edb --- /dev/null +++ b/Mathlib/Analysis/Normed/Ring/Ultra.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2024 Yakov Pechersky. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yakov Pechersky +-/ +import Mathlib.Analysis.Normed.Field.Basic +import Mathlib.Analysis.Normed.Group.Ultra + +/-! +# Ultrametric norms on rings where the norm of one is one + +This file contains results on the behavior of norms in ultrametric normed rings. +The norm must send one to one. + +## Main results + +* `norm_intCast_le_one`: + the norm of the image of an integer in the ring is always less than or equal to one + +## Implementation details + +A `[NormedRing R]` only assumes a submultiplicative norm and does not have `[NormOneClass R]`. +The weakest ring-like structure that has a bundled norm such that `‖1‖ = 1` is +`[NormedDivisionRing K]`. +Since the statements below hold in any context, we can state them +in an unbundled fashion using `[NormOneClass R]`. +In fact one can actually prove all these lemmas only assuming +`{R : Type*} [SeminormedAddGroup R] [One R] [NormOneClass R] [IsUltrametricDist R]`. +But one has to give the typeclass machinery a little help in order to get it to recognise that there +is a coercion from `ℕ` or `ℤ` to `R`. +Instead, we use weakest pre-existing typeclass that implies both +`[SeminormedAddGroup R]` and `[AddGroupWithOne R]`, which is `[SeminormedRing R]`. + +## Tags + +ultrametric, nonarchimedean +-/ +open Metric NNReal + +namespace IsUltrametricDist + +section NormOneClass + +variable {R : Type*} [SeminormedRing R] [NormOneClass R] [IsUltrametricDist R] + +lemma norm_add_one_le_max_norm_one (x : R) : + ‖x + 1‖ ≤ max ‖x‖ 1 := by + simpa only [le_max_iff, norm_one] using norm_add_le_max x 1 + +lemma nnnorm_add_one_le_max_nnnorm_one (x : R) : + ‖x + 1‖₊ ≤ max ‖x‖₊ 1 := + norm_add_one_le_max_norm_one _ + +variable (R) +lemma nnnorm_natCast_le_one (n : ℕ) : + ‖(n : R)‖₊ ≤ 1 := by + induction n with + | zero => simp only [Nat.cast_zero, nnnorm_zero, zero_le] + | succ n hn => simpa only [Nat.cast_add, Nat.cast_one, hn, max_eq_right] using + nnnorm_add_one_le_max_nnnorm_one (n : R) + +lemma norm_natCast_le_one (n : ℕ) : + ‖(n : R)‖ ≤ 1 := + nnnorm_natCast_le_one R n + +lemma nnnorm_intCast_le_one (z : ℤ) : + ‖(z : R)‖₊ ≤ 1 := by + induction z <;> + simpa only [Int.ofNat_eq_coe, Int.cast_natCast, Int.cast_negSucc, Nat.cast_one, nnnorm_neg] + using nnnorm_natCast_le_one _ _ + +lemma norm_intCast_le_one (z : ℤ) : + ‖(z : R)‖ ≤ 1 := + nnnorm_intCast_le_one _ z + +end NormOneClass + +end IsUltrametricDist diff --git a/Mathlib/Analysis/Normed/Ring/Units.lean b/Mathlib/Analysis/Normed/Ring/Units.lean index 6a9faca97ff80..86883d4c5d017 100644 --- a/Mathlib/Analysis/Normed/Ring/Units.lean +++ b/Mathlib/Analysis/Normed/Ring/Units.lean @@ -145,7 +145,7 @@ theorem inverse_one_sub_norm : (fun t : R => inverse (1 - t)) =O[𝓝 0] (fun _t have := tsum_geometric_le_of_norm_lt_one t ht' have : (1 - ‖t‖)⁻¹ ≤ 2 := by rw [← inv_inv (2 : ℝ)] - refine inv_le_inv_of_le (by norm_num) ?_ + refine inv_anti₀ (by norm_num) ?_ have : (2 : ℝ)⁻¹ + (2 : ℝ)⁻¹ = 1 := by ring linarith linarith diff --git a/Mathlib/Analysis/NormedSpace/Connected.lean b/Mathlib/Analysis/NormedSpace/Connected.lean index 64d98223dda5e..e14389a41de74 100644 --- a/Mathlib/Analysis/NormedSpace/Connected.lean +++ b/Mathlib/Analysis/NormedSpace/Connected.lean @@ -52,13 +52,11 @@ theorem Set.Countable.isPathConnected_compl_of_one_lt_rank let c := (2 : ℝ)⁻¹ • (a + b) let x := (2 : ℝ)⁻¹ • (b - a) have Ia : c - x = a := by - simp only [c, x, smul_add, smul_sub] - abel_nf - simp [← Int.cast_smul_eq_zsmul ℝ 2] + simp only [c, x] + module have Ib : c + x = b := by - simp only [c, x, smul_add, smul_sub] - abel_nf - simp [← Int.cast_smul_eq_zsmul ℝ 2] + simp only [c, x] + module have x_ne_zero : x ≠ 0 := by simpa [x] using sub_ne_zero.2 hab.symm obtain ⟨y, hy⟩ : ∃ y, LinearIndependent ℝ ![x, y] := exists_linearIndependent_pair_of_one_lt_rank h x_ne_zero diff --git a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean index ce018727e6c0f..b158eee9c860d 100644 --- a/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean +++ b/Mathlib/Analysis/NormedSpace/HahnBanach/Extension.lean @@ -107,7 +107,7 @@ theorem exists_extension_norm_eq (p : Subspace 𝕜 E) (f : p →L[𝕜] 𝕜) : _ = ‖f‖ := by rw [reCLM_norm, one_mul] · exact f.opNorm_le_bound g.extendTo𝕜.opNorm_nonneg fun x => h x ▸ g.extendTo𝕜.le_opNorm x -open FiniteDimensional +open Module /-- Corollary of the **Hahn-Banach theorem**: if `f : p → F` is a continuous linear map from a submodule of a normed space `E` over `𝕜`, `𝕜 = ℝ` or `𝕜 = ℂ`, @@ -120,7 +120,7 @@ lemma ContinuousLinearMap.exist_extension_of_finiteDimensional_range {p : Submod (f : p →L[𝕜] F) [FiniteDimensional 𝕜 (LinearMap.range f)] : ∃ g : E →L[𝕜] F, f = g.comp p.subtypeL := by letI : RCLike 𝕜 := IsRCLikeNormedField.rclike 𝕜 - set b := finBasis 𝕜 (LinearMap.range f) + set b := Module.finBasis 𝕜 (LinearMap.range f) set e := b.equivFunL set fi := fun i ↦ (LinearMap.toContinuousLinearMap (b.coord i)).comp (f.codRestrict _ <| LinearMap.mem_range_self _) diff --git a/Mathlib/Analysis/NormedSpace/HahnBanach/SeparatingDual.lean b/Mathlib/Analysis/NormedSpace/HahnBanach/SeparatingDual.lean index af94c78f743e0..b63ecf7d25efc 100644 --- a/Mathlib/Analysis/NormedSpace/HahnBanach/SeparatingDual.lean +++ b/Mathlib/Analysis/NormedSpace/HahnBanach/SeparatingDual.lean @@ -26,7 +26,7 @@ equivalences acts transitively on the set of nonzero vectors. registers that continuous linear forms on `E` separate points of `E`. -/ @[mk_iff separatingDual_def] class SeparatingDual (R V : Type*) [Ring R] [AddCommGroup V] [TopologicalSpace V] - [TopologicalSpace R] [Module R V] : Prop := + [TopologicalSpace R] [Module R V] : Prop where /-- Any nonzero vector can be mapped by a continuous linear map to a nonzero scalar. -/ exists_ne_zero' : ∀ (x : V), x ≠ 0 → ∃ f : V →L[R] R, f x ≠ 0 diff --git a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean index 8c50769ed4fbd..4b87da345fe31 100644 --- a/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/Multilinear/Basic.lean @@ -74,19 +74,48 @@ We use the following type variables in this file: universe u v v' wE wE₁ wE' wG wG' -/-- Applying a multilinear map to a vector is continuous in both coordinates. -/ -theorem ContinuousMultilinearMap.continuous_eval {𝕜 ι : Type*} {E : ι → Type*} {F : Type*} +section continuous_eval + +variable {𝕜 ι : Type*} {E : ι → Type*} {F : Type*} [NormedField 𝕜] [Finite ι] [∀ i, SeminormedAddCommGroup (E i)] [∀ i, NormedSpace 𝕜 (E i)] - [TopologicalSpace F] [AddCommGroup F] [TopologicalAddGroup F] [Module 𝕜 F] : + [TopologicalSpace F] [AddCommGroup F] [TopologicalAddGroup F] [Module 𝕜 F] + +/-- Applying a multilinear map to a vector is continuous in both coordinates. -/ +theorem ContinuousMultilinearMap.continuous_eval : Continuous fun p : ContinuousMultilinearMap 𝕜 E F × ∀ i, E i => p.1 p.2 := by cases nonempty_fintype ι let _ := TopologicalAddGroup.toUniformSpace F have := comm_topologicalAddGroup_is_uniform (G := F) refine (UniformOnFun.continuousOn_eval₂ fun m ↦ ?_).comp_continuous - (embedding_toUniformOnFun.continuous.prod_map continuous_id) fun (f, x) ↦ f.cont.continuousAt + (embedding_toUniformOnFun.continuous.prodMap continuous_id) fun (f, x) ↦ f.cont.continuousAt exact ⟨ball m 1, NormedSpace.isVonNBounded_of_isBounded _ isBounded_ball, ball_mem_nhds _ one_pos⟩ +namespace ContinuousLinearMap + +variable {G : Type*} [AddCommGroup G] [TopologicalSpace G] [Module 𝕜 G] [ContinuousConstSMul 𝕜 F] + (f : G →L[𝕜] ContinuousMultilinearMap 𝕜 E F) + +lemma continuous_uncurry_of_multilinear : + Continuous (fun (p : G × (Π i, E i)) ↦ f p.1 p.2) := + ContinuousMultilinearMap.continuous_eval.comp <| .prodMap (map_continuous f) continuous_id + +lemma continuousOn_uncurry_of_multilinear {s} : + ContinuousOn (fun (p : G × (Π i, E i)) ↦ f p.1 p.2) s := + f.continuous_uncurry_of_multilinear.continuousOn + +lemma continuousAt_uncurry_of_multilinear {x} : + ContinuousAt (fun (p : G × (Π i, E i)) ↦ f p.1 p.2) x := + f.continuous_uncurry_of_multilinear.continuousAt + +lemma continuousWithinAt_uncurry_of_multilinear {s x} : + ContinuousWithinAt (fun (p : G × (Π i, E i)) ↦ f p.1 p.2) s x := + f.continuous_uncurry_of_multilinear.continuousWithinAt + +end ContinuousLinearMap + +end continuous_eval + section Seminorm variable {𝕜 : Type u} {ι : Type v} {ι' : Type v'} {E : ι → Type wE} {E₁ : ι → Type wE₁} @@ -339,7 +368,7 @@ theorem isLeast_opNorm : IsLeast {c : ℝ | 0 ≤ c ∧ ∀ m, ‖f m‖ ≤ c * @[deprecated (since := "2024-02-02")] alias isLeast_op_norm := isLeast_opNorm theorem opNorm_nonneg : 0 ≤ ‖f‖ := - Real.sInf_nonneg _ fun _ ⟨hx, _⟩ => hx + Real.sInf_nonneg fun _ ⟨hx, _⟩ => hx @[deprecated (since := "2024-02-02")] alias op_norm_nonneg := opNorm_nonneg @@ -390,7 +419,7 @@ theorem le_of_opNorm_le {C : ℝ} (h : ‖f‖ ≤ C) : ‖f m‖ ≤ C * ∏ i, variable (f) theorem ratio_le_opNorm : (‖f m‖ / ∏ i, ‖m i‖) ≤ ‖f‖ := - div_le_of_nonneg_of_le_mul (by positivity) (opNorm_nonneg _) (f.le_opNorm m) + div_le_of_le_mul₀ (by positivity) (opNorm_nonneg _) (f.le_opNorm m) @[deprecated (since := "2024-02-02")] alias ratio_le_op_norm := ratio_le_opNorm @@ -747,7 +776,7 @@ theorem norm_mkPiAlgebraFin_succ_le : ‖ContinuousMultilinearMap.mkPiAlgebraFin simp only [ContinuousMultilinearMap.mkPiAlgebraFin_apply, one_mul, List.ofFn_eq_map, Fin.prod_univ_def, Multiset.map_coe, Multiset.prod_coe] refine (List.norm_prod_le' ?_).trans_eq ?_ - · rw [Ne, List.map_eq_nil, List.finRange_eq_nil] + · rw [Ne, List.map_eq_nil_iff, List.finRange_eq_nil] exact Nat.succ_ne_zero _ rw [List.map_map, Function.comp_def] diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean index 7c3c4398246cc..5d787cb4490a6 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Basic.lean @@ -174,7 +174,7 @@ theorem opNorm_neg (f : E →SL[σ₁₂] F) : ‖-f‖ = ‖f‖ := by simp onl @[deprecated (since := "2024-02-02")] alias op_norm_neg := opNorm_neg theorem opNorm_nonneg (f : E →SL[σ₁₂] F) : 0 ≤ ‖f‖ := - Real.sInf_nonneg _ fun _ ↦ And.left + Real.sInf_nonneg fun _ ↦ And.left @[deprecated (since := "2024-02-02")] alias op_norm_nonneg := opNorm_nonneg @@ -227,7 +227,7 @@ theorem opNorm_le_iff {f : E →SL[σ₁₂] F} {M : ℝ} (hMp : 0 ≤ M) : @[deprecated (since := "2024-02-02")] alias op_norm_le_iff := opNorm_le_iff theorem ratio_le_opNorm : ‖f x‖ / ‖x‖ ≤ ‖f‖ := - div_le_of_nonneg_of_le_mul (norm_nonneg _) f.opNorm_nonneg (le_opNorm _ _) + div_le_of_le_mul₀ (norm_nonneg _) f.opNorm_nonneg (le_opNorm _ _) @[deprecated (since := "2024-02-02")] alias ratio_le_op_norm := ratio_le_opNorm @@ -264,7 +264,7 @@ theorem opNorm_le_of_shell' {f : E →SL[σ₁₂] F} {ε C : ℝ} (ε_pos : 0 < · refine opNorm_le_of_ball ε_pos hC fun x hx => hf x ?_ ?_ · simp [h0] · rwa [ball_zero_eq] at hx - · rw [← inv_inv c, norm_inv, inv_lt_one_iff_of_pos (norm_pos_iff.2 <| inv_ne_zero h0)] at hc + · rw [← inv_inv c, norm_inv, inv_lt_one₀ (norm_pos_iff.2 <| inv_ne_zero h0)] at hc refine opNorm_le_of_shell ε_pos hC hc ?_ rwa [norm_inv, div_eq_mul_inv, inv_inv] diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean index b4e87ed65eb32..783b55750d8fb 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Completeness.lean @@ -181,7 +181,7 @@ variable [CompleteSpace F] (e : E →L[𝕜] Fₗ) (h_dense : DenseRange e) section -variable (h_e : UniformInducing e) +variable (h_e : IsUniformInducing e) /-- Extension of a continuous linear map `f : E →SL[σ₁₂] F`, with `E` a normed space and `F` a complete normed space, along a uniform and dense embedding `e : E →L[𝕜] Fₗ`. -/ @@ -190,7 +190,7 @@ def extend : Fₗ →SL[σ₁₂] F := have cont := (uniformContinuous_uniformly_extend h_e h_dense f.uniformContinuous).continuous -- extension of `f` agrees with `f` on the domain of the embedding `e` have eq := uniformly_extend_of_ind h_e h_dense f.uniformContinuous - { toFun := (h_e.denseInducing h_dense).extend f + { toFun := (h_e.isDenseInducing h_dense).extend f map_add' := by refine h_dense.induction_on₂ ?_ ?_ · exact isClosed_eq (cont.comp continuous_add) @@ -208,10 +208,10 @@ def extend : Fₗ →SL[σ₁₂] F := exact ContinuousLinearMap.map_smulₛₗ _ _ _ cont } --- Porting note: previously `(h_e.denseInducing h_dense)` was inferred. +-- Porting note: previously `(h_e.isDenseInducing h_dense)` was inferred. @[simp] theorem extend_eq (x : E) : extend f e h_dense h_e (e x) = f x := - DenseInducing.extend_eq (h_e.denseInducing h_dense) f.cont _ + IsDenseInducing.extend_eq (h_e.isDenseInducing h_dense) f.cont _ theorem extend_unique (g : Fₗ →SL[σ₁₂] F) (H : g.comp e = f) : extend f e h_dense h_e = g := ContinuousLinearMap.coeFn_injective <| @@ -230,7 +230,7 @@ variable {N : ℝ≥0} (h_e : ∀ x, ‖x‖ ≤ N * ‖e x‖) [RingHomIsometri /-- If a dense embedding `e : E →L[𝕜] G` expands the norm by a constant factor `N⁻¹`, then the norm of the extension of `f` along `e` is bounded by `N * ‖f‖`. -/ theorem opNorm_extend_le : - ‖f.extend e h_dense (uniformEmbedding_of_bound _ h_e).toUniformInducing‖ ≤ N * ‖f‖ := by + ‖f.extend e h_dense (isUniformEmbedding_of_bound _ h_e).isUniformInducing‖ ≤ N * ‖f‖ := by -- Add `opNorm_le_of_dense`? refine opNorm_le_bound _ ?_ (isClosed_property h_dense (isClosed_le ?_ ?_) fun x ↦ ?_) · cases le_total 0 N with diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean index 9eae72e5fb45b..a42244f918fa7 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/Mul.lean @@ -121,7 +121,7 @@ examples. Any algebra with an approximate identity (e.g., $$L^1$$) is also regul This is a useful class because it gives rise to a nice norm on the unitization; in particular it is a C⋆-norm when the norm on `A` is a C⋆-norm. -/ -class _root_.RegularNormedAlgebra : Prop := +class _root_.RegularNormedAlgebra : Prop where /-- The left regular representation of the algebra on itself is an isometry. -/ isometry_mul' : Isometry (mul 𝕜 𝕜') diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean index 7461f70c18dfc..020de596c8f44 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NNNorm.lean @@ -156,7 +156,7 @@ theorem exists_lt_apply_of_lt_opNNNorm {𝕜 𝕜₂ E F : Type*} [NormedAddComm obtain ⟨k, hk₁, hk₂⟩ := NormedField.exists_lt_nnnorm_lt 𝕜 hy refine ⟨k • y, (nnnorm_smul k y).symm ▸ (NNReal.lt_inv_iff_mul_lt hy').1 hk₂, ?_⟩ have : ‖σ₁₂ k‖₊ = ‖k‖₊ := Subtype.ext RingHomIsometric.is_iso - rwa [map_smulₛₗ f, nnnorm_smul, ← NNReal.div_lt_iff hfy, div_eq_mul_inv, this] + rwa [map_smulₛₗ f, nnnorm_smul, ← div_lt_iff₀ hfy.bot_lt, div_eq_mul_inv, this] @[deprecated (since := "2024-02-02")] alias exists_lt_apply_of_lt_op_nnnorm := exists_lt_apply_of_lt_opNNNorm diff --git a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean index 85edc3f7a843e..253805834044d 100644 --- a/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean +++ b/Mathlib/Analysis/NormedSpace/OperatorNorm/NormedSpace.lean @@ -165,6 +165,15 @@ theorem norm_toContinuousLinearMap_comp [RingHomIsometric σ₁₂] (f : F → opNorm_ext (f.toContinuousLinearMap.comp g) g fun x => by simp only [norm_map, coe_toContinuousLinearMap, coe_comp', Function.comp_apply] +/-- Composing on the left with a linear isometry gives a linear isometry between spaces of +continuous linear maps. -/ +def postcomp [RingHomIsometric σ₁₂] [RingHomIsometric σ₁₃] (a : F →ₛₗᵢ[σ₂₃] G) : + (E →SL[σ₁₂] F) →ₛₗᵢ[σ₂₃] (E →SL[σ₁₃] G) where + toFun f := a.toContinuousLinearMap.comp f + map_add' f g := by simp + map_smul' c f := by simp + norm_map' f := by simp [a.norm_toContinuousLinearMap_comp] + end LinearIsometry end diff --git a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean index 1ddd022c490b2..299585582989c 100644 --- a/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean +++ b/Mathlib/Analysis/NormedSpace/PiTensorProduct/InjectiveSeminorm.lean @@ -211,8 +211,7 @@ theorem injectiveSeminorm_le_projectiveSeminorm : existsi PUnit, inferInstance, inferInstance ext x simp only [Seminorm.zero_apply, Seminorm.comp_apply, coe_normSeminorm] - have heq : toDualContinuousMultilinearMap PUnit x = 0 := by ext _ - rw [heq, norm_zero] + rw [Subsingleton.elim (toDualContinuousMultilinearMap PUnit x) 0, norm_zero] · intro p hp simp only [Set.mem_setOf_eq] at hp obtain ⟨G, _, _, h⟩ := hp diff --git a/Mathlib/Analysis/NormedSpace/Pointwise.lean b/Mathlib/Analysis/NormedSpace/Pointwise.lean index bb061dfe9e186..866ca33561073 100644 --- a/Mathlib/Analysis/NormedSpace/Pointwise.lean +++ b/Mathlib/Analysis/NormedSpace/Pointwise.lean @@ -78,7 +78,7 @@ theorem smul_ball {c : 𝕜} (hc : c ≠ 0) (x : E) (r : ℝ) : c • ball x r = ext y rw [mem_smul_set_iff_inv_smul_mem₀ hc] conv_lhs => rw [← inv_smul_smul₀ hc x] - simp [← div_eq_inv_mul, div_lt_iff (norm_pos_iff.2 hc), mul_comm _ r, dist_smul₀] + simp [← div_eq_inv_mul, div_lt_iff₀ (norm_pos_iff.2 hc), mul_comm _ r, dist_smul₀] theorem smul_unitBall {c : 𝕜} (hc : c ≠ 0) : c • ball (0 : E) (1 : ℝ) = ball (0 : E) ‖c‖ := by rw [_root_.smul_ball hc, smul_zero, mul_one] diff --git a/Mathlib/Analysis/NormedSpace/RieszLemma.lean b/Mathlib/Analysis/NormedSpace/RieszLemma.lean index 415a55f95a3f4..553d89feaaa42 100644 --- a/Mathlib/Analysis/NormedSpace/RieszLemma.lean +++ b/Mathlib/Analysis/NormedSpace/RieszLemma.lean @@ -50,7 +50,7 @@ theorem riesz_lemma {F : Subspace 𝕜 E} (hFc : IsClosed (F : Set E)) (hF : ∃ simp only [r', max_lt_iff, hr, true_and] norm_num have hlt : 0 < r' := lt_of_lt_of_le (by norm_num) (le_max_right r 2⁻¹) - have hdlt : d < d / r' := (lt_div_iff hlt).mpr ((mul_lt_iff_lt_one_right hdp).2 hr') + have hdlt : d < d / r' := (lt_div_iff₀ hlt).mpr ((mul_lt_iff_lt_one_right hdp).2 hr') obtain ⟨y₀, hy₀F, hxy₀⟩ : ∃ y ∈ F, dist x y < d / r' := (Metric.infDist_lt_iff hFn).mp hdlt have x_ne_y₀ : x - y₀ ∉ F := by by_contra h @@ -63,7 +63,7 @@ theorem riesz_lemma {F : Subspace 𝕜 E} (hFc : IsClosed (F : Set E)) (hF : ∃ r * ‖x - y₀‖ ≤ r' * ‖x - y₀‖ := by gcongr; apply le_max_left _ < d := by rw [← dist_eq_norm] - exact (lt_div_iff' hlt).1 hxy₀ + exact (lt_div_iff₀' hlt).1 hxy₀ _ ≤ dist x (y₀ + y) := Metric.infDist_le_dist_of_mem hy₀y _ = ‖x - y₀ - y‖ := by rw [sub_sub, dist_eq_norm] @@ -82,7 +82,7 @@ theorem riesz_lemma_of_norm_lt {c : 𝕜} (hc : 1 < ‖c‖) {R : ℝ} (hR : ‖ ∃ x₀ : E, ‖x₀‖ ≤ R ∧ ∀ y ∈ F, 1 ≤ ‖x₀ - y‖ := by have Rpos : 0 < R := (norm_nonneg _).trans_lt hR have : ‖c‖ / R < 1 := by - rw [div_lt_iff Rpos] + rw [div_lt_iff₀ Rpos] simpa using hR rcases riesz_lemma hFc hF this with ⟨x, xF, hx⟩ have x0 : x ≠ 0 := fun H => by simp [H] at xF diff --git a/Mathlib/Analysis/ODE/PicardLindelof.lean b/Mathlib/Analysis/ODE/PicardLindelof.lean index a1db140c6f1f2..9c46abf777613 100644 --- a/Mathlib/Analysis/ODE/PicardLindelof.lean +++ b/Mathlib/Analysis/ODE/PicardLindelof.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Winston Yin -/ import Mathlib.Analysis.SpecialFunctions.Integrals +import Mathlib.Topology.Algebra.Order.Floor import Mathlib.Topology.MetricSpace.Contracting /-! @@ -169,9 +170,12 @@ def toContinuousMap : v.FunSpace ↪ C(Icc v.tMin v.tMax, E) := instance : MetricSpace v.FunSpace := MetricSpace.induced toContinuousMap toContinuousMap.injective inferInstance -theorem uniformInducing_toContinuousMap : UniformInducing (@toContinuousMap _ _ _ v) := +theorem isUniformInducing_toContinuousMap : IsUniformInducing (@toContinuousMap _ _ _ v) := ⟨rfl⟩ +@[deprecated (since := "2024-10-05")] +alias uniformInducing_toContinuousMap := isUniformInducing_toContinuousMap + theorem range_toContinuousMap : range toContinuousMap = {f : C(Icc v.tMin v.tMax, E) | f v.t₀ = v.x₀ ∧ LipschitzWith v.C f} := by @@ -216,7 +220,7 @@ theorem dist_le_of_forall {f₁ f₂ : FunSpace v} {d : ℝ} (h : ∀ t, dist (f v.nonempty_Icc.to_subtype).2 h instance [CompleteSpace E] : CompleteSpace v.FunSpace := by - refine (completeSpace_iff_isComplete_range uniformInducing_toContinuousMap).2 + refine (completeSpace_iff_isComplete_range isUniformInducing_toContinuousMap).2 (IsClosed.isComplete ?_) rw [range_toContinuousMap, setOf_and] refine (isClosed_eq (ContinuousMap.continuous_eval_const _) continuous_const).inter ?_ @@ -301,7 +305,7 @@ section theorem exists_contracting_iterate : ∃ (N : ℕ) (K : _), ContractingWith K (FunSpace.next : v.FunSpace → v.FunSpace)^[N] := by - rcases ((Real.tendsto_pow_div_factorial_atTop (v.L * v.tDist)).eventually + rcases ((FloorSemiring.tendsto_pow_div_factorial_atTop (v.L * v.tDist)).eventually (gt_mem_nhds zero_lt_one)).exists with ⟨N, hN⟩ have : (0 : ℝ) ≤ (v.L * v.tDist) ^ N / N ! := div_nonneg (pow_nonneg (mul_nonneg v.L.2 v.tDist_nonneg) _) (Nat.cast_nonneg _) diff --git a/Mathlib/Analysis/Oscillation.lean b/Mathlib/Analysis/Oscillation.lean index 16bc8089b08b1..c6327e3b9a059 100644 --- a/Mathlib/Analysis/Oscillation.lean +++ b/Mathlib/Analysis/Oscillation.lean @@ -3,8 +3,9 @@ Copyright (c) 2024 James Sundstrom. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: James Sundstrom -/ -import Mathlib.Topology.EMetricSpace.Diam +import Mathlib.Data.ENNReal.Real import Mathlib.Order.WellFoundedSet +import Mathlib.Topology.EMetricSpace.Diam /-! # Oscillation diff --git a/Mathlib/Analysis/PSeries.lean b/Mathlib/Analysis/PSeries.lean index 29941c56c0472..a0365a83cfc7b 100644 --- a/Mathlib/Analysis/PSeries.lean +++ b/Mathlib/Analysis/PSeries.lean @@ -63,7 +63,7 @@ theorem le_sum_schlomilch' (hf : ∀ ⦃m n⦄, 0 < m → m ≤ n → f n ≤ f theorem le_sum_condensed' (hf : ∀ ⦃m n⦄, 0 < m → m ≤ n → f n ≤ f m) (n : ℕ) : (∑ k ∈ Ico 1 (2 ^ n), f k) ≤ ∑ k ∈ range n, 2 ^ k • f (2 ^ k) := by convert le_sum_schlomilch' hf (fun n => pow_pos zero_lt_two n) - (fun m n hm => pow_le_pow_right one_le_two hm) n using 2 + (fun m n hm => pow_right_mono₀ one_le_two hm) n using 2 simp [pow_succ, mul_two, two_mul] theorem le_sum_schlomilch (hf : ∀ ⦃m n⦄, 0 < m → m ≤ n → f n ≤ f m) (h_pos : ∀ n, 0 < u n) @@ -98,7 +98,7 @@ theorem sum_schlomilch_le' (hf : ∀ ⦃m n⦄, 1 < m → m ≤ n → f n ≤ f theorem sum_condensed_le' (hf : ∀ ⦃m n⦄, 1 < m → m ≤ n → f n ≤ f m) (n : ℕ) : (∑ k ∈ range n, 2 ^ k • f (2 ^ (k + 1))) ≤ ∑ k ∈ Ico 2 (2 ^ n + 1), f k := by convert sum_schlomilch_le' hf (fun n => pow_pos zero_lt_two n) - (fun m n hm => pow_le_pow_right one_le_two hm) n using 2 + (fun m n hm => pow_right_mono₀ one_le_two hm) n using 2 simp [pow_succ, mul_two, two_mul] theorem sum_schlomilch_le {C : ℕ} (hf : ∀ ⦃m n⦄, 1 < m → m ≤ n → f n ≤ f m) (h_pos : ∀ n, 0 < u n) @@ -162,8 +162,8 @@ theorem tsum_schlomilch_le {C : ℕ} (hf : ∀ ⦃m n⦄, 1 < m → m ≤ n → le_trans ?_ (add_le_add_left (mul_le_mul_of_nonneg_left (ENNReal.sum_le_tsum <| Finset.Ico (u 0 + 1) (u n + 1)) ?_) _) - simpa using Finset.sum_schlomilch_le hf h_pos h_nonneg hu h_succ_diff n - exact zero_le _ + · simpa using Finset.sum_schlomilch_le hf h_pos h_nonneg hu h_succ_diff n + · exact zero_le _ theorem tsum_condensed_le (hf : ∀ ⦃m n⦄, 1 < m → m ≤ n → f n ≤ f m) : (∑' k : ℕ, 2 ^ k * f (2 ^ k)) ≤ f 1 + 2 * ∑' k, f k := by @@ -283,7 +283,7 @@ theorem summable_nat_rpow_inv {p : ℝ} : (eventually_cofinite_ne 0)).exists apply hk₀ rw [← pos_iff_ne_zero, ← @Nat.cast_pos ℝ] at hk₀ - simpa [inv_lt_one_iff_of_pos (rpow_pos_of_pos hk₀ _), one_lt_rpow_iff_of_pos hk₀, hp, + simpa [inv_lt_one₀ (rpow_pos_of_pos hk₀ _), one_lt_rpow_iff_of_pos hk₀, hp, hp.not_lt, hk₀] using hk₁ @[simp] @@ -416,7 +416,7 @@ theorem sum_Ioo_inv_sq_le (k n : ℕ) : (∑ i ∈ Ioo k n, (i ^ 2 : α)⁻¹) have A : (1 : α) ≤ k + 1 := by simp only [le_add_iff_nonneg_left, Nat.cast_nonneg] simp_rw [← one_div] gcongr - simpa using pow_le_pow_right A one_le_two + simpa using pow_right_mono₀ A one_le_two _ = 2 / (k + 1) := by ring end diff --git a/Mathlib/Analysis/Quaternion.lean b/Mathlib/Analysis/Quaternion.lean index 0991d3a5949c9..3466df2251849 100644 --- a/Mathlib/Analysis/Quaternion.lean +++ b/Mathlib/Analysis/Quaternion.lean @@ -195,9 +195,9 @@ theorem continuous_im : Continuous fun q : ℍ => q.im := by simpa only [← sub_self_re] using continuous_id.sub (continuous_coe.comp continuous_re) instance : CompleteSpace ℍ := - haveI : UniformEmbedding linearIsometryEquivTuple.toLinearEquiv.toEquiv.symm := - linearIsometryEquivTuple.toContinuousLinearEquiv.symm.uniformEmbedding - (completeSpace_congr this).1 (by infer_instance) + haveI : IsUniformEmbedding linearIsometryEquivTuple.toLinearEquiv.toEquiv.symm := + linearIsometryEquivTuple.toContinuousLinearEquiv.symm.isUniformEmbedding + (completeSpace_congr this).1 inferInstance section infinite_sum diff --git a/Mathlib/Analysis/RCLike/Basic.lean b/Mathlib/Analysis/RCLike/Basic.lean index 869aa9fe0a463..69097ee6513a0 100644 --- a/Mathlib/Analysis/RCLike/Basic.lean +++ b/Mathlib/Analysis/RCLike/Basic.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Frédéric Dupuis -/ import Mathlib.Algebra.Algebra.Field +import Mathlib.Algebra.BigOperators.Balance +import Mathlib.Algebra.Order.BigOperators.Expect import Mathlib.Algebra.Order.Star.Basic import Mathlib.Analysis.CStarAlgebra.Basic import Mathlib.Analysis.Normed.Operator.ContinuousLinearMap @@ -39,7 +41,8 @@ their counterparts in `Mathlib/Analysis/Complex/Basic.lean` (which causes linter A few lemmas requiring heavier imports are in `Mathlib/Data/RCLike/Lemmas.lean`. -/ -open scoped ComplexConjugate +open Fintype +open scoped BigOperators ComplexConjugate section @@ -234,6 +237,17 @@ theorem norm_ofReal (r : ℝ) : ‖(r : K)‖ = |r| := instance (priority := 100) charZero_rclike : CharZero K := (RingHom.charZero_iff (algebraMap ℝ K).injective).1 inferInstance +@[rclike_simps, norm_cast] +lemma ofReal_expect {α : Type*} (s : Finset α) (f : α → ℝ) : 𝔼 i ∈ s, f i = 𝔼 i ∈ s, (f i : K) := + map_expect (algebraMap ..) .. + +@[norm_cast] +lemma ofReal_balance {ι : Type*} [Fintype ι] (f : ι → ℝ) (i : ι) : + ((balance f i : ℝ) : K) = balance ((↑) ∘ f) i := map_balance (algebraMap ..) .. + +@[simp] lemma ofReal_comp_balance {ι : Type*} [Fintype ι] (f : ι → ℝ) : + ofReal ∘ balance f = balance (ofReal ∘ f : ι → K) := funext <| ofReal_balance _ + /-! ### The imaginary unit, `I` -/ /-- The imaginary unit. -/ @@ -605,13 +619,23 @@ variable (K) in lemma nnnorm_nsmul [NormedAddCommGroup E] [NormedSpace K E] (n : ℕ) (x : E) : ‖n • x‖₊ = n • ‖x‖₊ := by simpa [Nat.cast_smul_eq_nsmul] using nnnorm_smul (n : K) x +section NormedField +variable [NormedField E] [CharZero E] [NormedSpace K E] +include K + variable (K) in -lemma norm_nnqsmul [NormedField E] [CharZero E] [NormedSpace K E] (q : ℚ≥0) (x : E) : - ‖q • x‖ = q • ‖x‖ := by simpa [NNRat.cast_smul_eq_nnqsmul] using norm_smul (q : K) x +lemma norm_nnqsmul (q : ℚ≥0) (x : E) : ‖q • x‖ = q • ‖x‖ := by + simpa [NNRat.cast_smul_eq_nnqsmul] using norm_smul (q : K) x variable (K) in -lemma nnnorm_nnqsmul [NormedField E] [CharZero E] [NormedSpace K E] (q : ℚ≥0) (x : E) : - ‖q • x‖₊ = q • ‖x‖₊ := by simpa [NNRat.cast_smul_eq_nnqsmul] using nnnorm_smul (q : K) x +lemma nnnorm_nnqsmul (q : ℚ≥0) (x : E) : ‖q • x‖₊ = q • ‖x‖₊ := by + simpa [NNRat.cast_smul_eq_nnqsmul] using nnnorm_smul (q : K) x + +@[bound] +lemma norm_expect_le {ι : Type*} {s : Finset ι} {f : ι → E} : ‖𝔼 i ∈ s, f i‖ ≤ 𝔼 i ∈ s, ‖f i‖ := + Finset.le_expect_of_subadditive norm_zero norm_add_le fun _ _ ↦ by rw [norm_nnqsmul K] + +end NormedField theorem mul_self_norm (z : K) : ‖z‖ * ‖z‖ = normSq z := by rw [normSq_eq_def', sq] @@ -648,11 +672,11 @@ open IsAbsoluteValue theorem abs_re_div_norm_le_one (z : K) : |re z / ‖z‖| ≤ 1 := by rw [abs_div, abs_norm] - exact div_le_one_of_le (abs_re_le_norm _) (norm_nonneg _) + exact div_le_one_of_le₀ (abs_re_le_norm _) (norm_nonneg _) theorem abs_im_div_norm_le_one (z : K) : |im z / ‖z‖| ≤ 1 := by rw [abs_div, abs_norm] - exact div_le_one_of_le (abs_im_le_norm _) (norm_nonneg _) + exact div_le_one_of_le₀ (abs_im_le_norm _) (norm_nonneg _) theorem norm_I_of_ne_zero (hI : (I : K) ≠ 0) : ‖(I : K)‖ = 1 := by rw [← mul_self_inj_of_nonneg (norm_nonneg I) zero_le_one, one_mul, ← norm_mul, @@ -1062,7 +1086,7 @@ section /-- A mixin over a normed field, saying that the norm field structure is the same as `ℝ` or `ℂ`. To endow such a field with a compatible `RCLike` structure in a proof, use `letI := IsRCLikeNormedField.rclike 𝕜`.-/ -class IsRCLikeNormedField (𝕜 : Type*) [hk : NormedField 𝕜] : Prop := +class IsRCLikeNormedField (𝕜 : Type*) [hk : NormedField 𝕜] : Prop where out : ∃ h : RCLike 𝕜, hk = h.toNormedField instance (priority := 100) (𝕜 : Type*) [h : RCLike 𝕜] : IsRCLikeNormedField 𝕜 := ⟨⟨h, rfl⟩⟩ diff --git a/Mathlib/Analysis/RCLike/Inner.lean b/Mathlib/Analysis/RCLike/Inner.lean new file mode 100644 index 0000000000000..4136cd8069e82 --- /dev/null +++ b/Mathlib/Analysis/RCLike/Inner.lean @@ -0,0 +1,163 @@ +/- +Copyright (c) 2023 Yaël Dilies. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yaël Dilies +-/ +import Mathlib.Analysis.InnerProductSpace.PiL2 + +/-! +# L2 inner product of finite sequences + +This file defines the weighted L2 inner product of functions `f g : ι → R` where `ι` is a fintype as +`∑ i, conj (f i) * g i`. This convention (conjugation on the left) matches the inner product coming +from `RCLike.innerProductSpace`. + +## TODO + +* Build a non-instance `InnerProductSpace` from `wInner`. +* `cWeight` is a poor name. Can we find better? It doesn't hugely matter for typing, since it's + hidden behind the `⟪f, g⟫ₙ_[𝕝] `notation, but it does show up in lemma names + `⟪f, g⟫_[𝕝, cWeight]` is called `wInner_cWeight`. Maybe we should introduce some naming + convention, similarly to `MeasureTheory.average`? +-/ + +open Finset Function Real +open scoped BigOperators ComplexConjugate ComplexOrder ENNReal NNReal NNRat + +variable {ι κ 𝕜 : Type*} {E : ι → Type*} [Fintype ι] + +namespace RCLike +variable [RCLike 𝕜] + +section Pi +variable [∀ i, SeminormedAddCommGroup (E i)] [∀ i, InnerProductSpace 𝕜 (E i)] {w : ι → ℝ} + +/-- Weighted inner product giving rise to the L2 norm. -/ +def wInner (w : ι → ℝ) (f g : ∀ i, E i) : 𝕜 := ∑ i, w i • inner (f i) (g i) + +/-- The weight function making `wInner` into the compact inner product. -/ +noncomputable abbrev cWeight : ι → ℝ := Function.const _ (Fintype.card ι)⁻¹ + +@[inherit_doc] notation "⟪" f ", " g "⟫_[" 𝕝 ", " w "]" => wInner (𝕜 := 𝕝) w f g + +/-- Discrete inner product giving rise to the discrete L2 norm. -/ +notation "⟪" f ", " g "⟫_[" 𝕝 "]" => ⟪f, g⟫_[𝕝, 1] + +/-- Compact inner product giving rise to the compact L2 norm. -/ +notation "⟪" f ", " g "⟫ₙ_[" 𝕝 "]" => ⟪f, g⟫_[𝕝, cWeight] + +lemma wInner_cWeight_eq_smul_wInner_one (f g : ∀ i, E i) : + ⟪f, g⟫ₙ_[𝕜] = (Fintype.card ι : ℚ≥0)⁻¹ • ⟪f, g⟫_[𝕜] := by + simp [wInner, smul_sum, ← NNRat.cast_smul_eq_nnqsmul ℝ] + +@[simp] lemma conj_wInner_symm (w : ι → ℝ) (f g : ∀ i, E i) : + conj ⟪f, g⟫_[𝕜, w] = ⟪g, f⟫_[𝕜, w] := by + simp [wInner, map_sum, inner_conj_symm, rclike_simps] + +@[simp] lemma wInner_zero_left (w : ι → ℝ) (g : ∀ i, E i) : ⟪0, g⟫_[𝕜, w] = 0 := by simp [wInner] +@[simp] lemma wInner_zero_right (w : ι → ℝ) (f : ∀ i, E i) : ⟪f, 0⟫_[𝕜, w] = 0 := by simp [wInner] + +lemma wInner_add_left (w : ι → ℝ) (f₁ f₂ g : ∀ i, E i) : + ⟪f₁ + f₂, g⟫_[𝕜, w] = ⟪f₁, g⟫_[𝕜, w] + ⟪f₂, g⟫_[𝕜, w] := by + simp [wInner, inner_add_left, smul_add, sum_add_distrib] + +lemma wInner_add_right (w : ι → ℝ) (f g₁ g₂ : ∀ i, E i) : + ⟪f, g₁ + g₂⟫_[𝕜, w] = ⟪f, g₁⟫_[𝕜, w] + ⟪f, g₂⟫_[𝕜, w] := by + simp [wInner, inner_add_right, smul_add, sum_add_distrib] + +@[simp] lemma wInner_neg_left (w : ι → ℝ) (f g : ∀ i, E i) : ⟪-f, g⟫_[𝕜, w] = -⟪f, g⟫_[𝕜, w] := by + simp [wInner] + +@[simp] lemma wInner_neg_right (w : ι → ℝ) (f g : ∀ i, E i) : ⟪f, -g⟫_[𝕜, w] = -⟪f, g⟫_[𝕜, w] := by + simp [wInner] + +lemma wInner_sub_left (w : ι → ℝ) (f₁ f₂ g : ∀ i, E i) : + ⟪f₁ - f₂, g⟫_[𝕜, w] = ⟪f₁, g⟫_[𝕜, w] - ⟪f₂, g⟫_[𝕜, w] := by + simp_rw [sub_eq_add_neg, wInner_add_left, wInner_neg_left] + +lemma wInner_sub_right (w : ι → ℝ) (f g₁ g₂ : ∀ i, E i) : + ⟪f, g₁ - g₂⟫_[𝕜, w] = ⟪f, g₁⟫_[𝕜, w] - ⟪f, g₂⟫_[𝕜, w] := by + simp_rw [sub_eq_add_neg, wInner_add_right, wInner_neg_right] + +@[simp] lemma wInner_of_isEmpty [IsEmpty ι] (w : ι → ℝ) (f g : ∀ i, E i) : ⟪f, g⟫_[𝕜, w] = 0 := by + simp [Subsingleton.elim f 0] + +lemma wInner_smul_left {𝕝 : Type*} [CommSemiring 𝕝] [StarRing 𝕝] [Algebra 𝕝 𝕜] [StarModule 𝕝 𝕜] + [SMulCommClass ℝ 𝕝 𝕜] [∀ i, Module 𝕝 (E i)] [∀ i, IsScalarTower 𝕝 𝕜 (E i)] (c : 𝕝) + (w : ι → ℝ) (f g : ∀ i, E i) : ⟪c • f, g⟫_[𝕜, w] = star c • ⟪f, g⟫_[𝕜, w] := by + simp_rw [wInner, Pi.smul_apply, inner_smul_left_eq_star_smul, starRingEnd_apply, smul_sum, + smul_comm (w _)] + +lemma wInner_smul_right {𝕝 : Type*} [CommSemiring 𝕝] [StarRing 𝕝] [Algebra 𝕝 𝕜] [StarModule 𝕝 𝕜] + [SMulCommClass ℝ 𝕝 𝕜] [∀ i, Module 𝕝 (E i)] [∀ i, IsScalarTower 𝕝 𝕜 (E i)] (c : 𝕝) + (w : ι → ℝ) (f g : ∀ i, E i) : ⟪f, c • g⟫_[𝕜, w] = c • ⟪f, g⟫_[𝕜, w] := by + simp_rw [wInner, Pi.smul_apply, inner_smul_right_eq_smul, smul_sum, smul_comm] + +lemma mul_wInner_left (c : 𝕜) (w : ι → ℝ) (f g : ∀ i, E i) : + c * ⟪f, g⟫_[𝕜, w] = ⟪star c • f, g⟫_[𝕜, w] := by rw [wInner_smul_left, star_star, smul_eq_mul] + +lemma wInner_one_eq_sum (f g : ∀ i, E i) : ⟪f, g⟫_[𝕜] = ∑ i, inner (f i) (g i) := by simp [wInner] +lemma wInner_cWeight_eq_expect (f g : ∀ i, E i) : ⟪f, g⟫ₙ_[𝕜] = 𝔼 i, inner (f i) (g i) := by + simp [wInner, expect, smul_sum, ← NNRat.cast_smul_eq_nnqsmul ℝ] + +end Pi + +section Function +variable {w : ι → ℝ} {f g : ι → 𝕜} + +lemma wInner_const_left (a : 𝕜) (f : ι → 𝕜) : + ⟪const _ a, f⟫_[𝕜, w] = conj a * ∑ i, w i • f i := by simp [wInner, const_apply, mul_sum] + +lemma wInner_const_right (f : ι → 𝕜) (a : 𝕜) : + ⟪f, const _ a⟫_[𝕜, w] = (∑ i, w i • conj (f i)) * a := by simp [wInner, const_apply, sum_mul] + +@[simp] lemma wInner_one_const_left (a : 𝕜) (f : ι → 𝕜) : + ⟪const _ a, f⟫_[𝕜] = conj a * ∑ i, f i := by simp [wInner_one_eq_sum, mul_sum] + +@[simp] lemma wInner_one_const_right (f : ι → 𝕜) (a : 𝕜) : + ⟪f, const _ a⟫_[𝕜] = (∑ i, conj (f i)) * a := by simp [wInner_one_eq_sum, sum_mul] + +@[simp] lemma wInner_cWeight_const_left (a : 𝕜) (f : ι → 𝕜) : + ⟪const _ a, f⟫ₙ_[𝕜] = conj a * 𝔼 i, f i := by simp [wInner_cWeight_eq_expect, mul_expect] + +@[simp] lemma wInner_cWeight_const_right (f : ι → 𝕜) (a : 𝕜) : + ⟪f, const _ a⟫ₙ_[𝕜] = (𝔼 i, conj (f i)) * a := by simp [wInner_cWeight_eq_expect, expect_mul] + +lemma wInner_one_eq_inner (f g : ι → 𝕜) : + ⟪f, g⟫_[𝕜, 1] = inner ((WithLp.equiv 2 _).symm f) ((WithLp.equiv 2 _).symm g) := by + simp [wInner] + +lemma inner_eq_wInner_one (f g : PiLp 2 fun _i : ι ↦ 𝕜) : + inner f g = ⟪WithLp.equiv 2 _ f, WithLp.equiv 2 _ g⟫_[𝕜, 1] := by simp [wInner] + +lemma linearIndependent_of_ne_zero_of_wInner_one_eq_zero {f : κ → ι → 𝕜} (hf : ∀ k, f k ≠ 0) + (hinner : Pairwise fun k₁ k₂ ↦ ⟪f k₁, f k₂⟫_[𝕜] = 0) : LinearIndependent 𝕜 f := by + simp_rw [wInner_one_eq_inner] at hinner + have := linearIndependent_of_ne_zero_of_inner_eq_zero ?_ hinner + exacts [this, hf] + +lemma linearIndependent_of_ne_zero_of_wInner_cWeight_eq_zero {f : κ → ι → 𝕜} (hf : ∀ k, f k ≠ 0) + (hinner : Pairwise fun k₁ k₂ ↦ ⟪f k₁, f k₂⟫ₙ_[𝕜] = 0) : LinearIndependent 𝕜 f := by + cases isEmpty_or_nonempty ι + · have : IsEmpty κ := ⟨fun k ↦ hf k <| Subsingleton.elim ..⟩ + exact linearIndependent_empty_type + · exact linearIndependent_of_ne_zero_of_wInner_one_eq_zero hf <| by + simpa [wInner_cWeight_eq_smul_wInner_one, ← NNRat.cast_smul_eq_nnqsmul 𝕜] using hinner + +lemma wInner_nonneg (hw : 0 ≤ w) (hf : 0 ≤ f) (hg : 0 ≤ g) : 0 ≤ ⟪f, g⟫_[𝕜, w] := + sum_nonneg fun _ _ ↦ smul_nonneg (hw _) <| mul_nonneg (star_nonneg_iff.2 (hf _)) (hg _) + +lemma norm_wInner_le (hw : 0 ≤ w) : ‖⟪f, g⟫_[𝕜, w]‖ ≤ ⟪fun i ↦ ‖f i‖, fun i ↦ ‖g i‖⟫_[ℝ, w] := + (norm_sum_le ..).trans_eq <| sum_congr rfl fun i _ ↦ by + simp [Algebra.smul_def, norm_mul, abs_of_nonneg (hw i)] + +end Function + +section Real +variable {w f g : ι → ℝ} + +lemma abs_wInner_le (hw : 0 ≤ w) : |⟪f, g⟫_[ℝ, w]| ≤ ⟪|f|, |g|⟫_[ℝ, w] := by + simpa using norm_wInner_le (𝕜 := ℝ) hw + +end Real +end RCLike diff --git a/Mathlib/Analysis/Seminorm.lean b/Mathlib/Analysis/Seminorm.lean index 6ca315beb04f3..a448a13eadcc8 100644 --- a/Mathlib/Analysis/Seminorm.lean +++ b/Mathlib/Analysis/Seminorm.lean @@ -495,7 +495,7 @@ noncomputable instance instSupSet : SupSet (Seminorm 𝕜 E) where if h : BddAbove ((↑) '' s : Set (E → ℝ)) then { toFun := ⨆ p : s, ((p : Seminorm 𝕜 E) : E → ℝ) map_zero' := by - rw [iSup_apply, ← @Real.ciSup_const_zero s] + rw [iSup_apply, ← @Real.iSup_const_zero s] congr! rename_i _ _ _ i exact map_zero i.1 @@ -658,7 +658,7 @@ theorem ball_smul (p : Seminorm 𝕜 E) {c : NNReal} (hc : 0 < c) (r : ℝ) (x : (c • p).ball x r = p.ball x (r / c) := by ext rw [mem_ball, mem_ball, smul_apply, NNReal.smul_def, smul_eq_mul, mul_comm, - lt_div_iff (NNReal.coe_pos.mpr hc)] + lt_div_iff₀ (NNReal.coe_pos.mpr hc)] theorem closedBall_smul (p : Seminorm 𝕜 E) {c : NNReal} (hc : 0 < c) (r : ℝ) (x : E) : (c • p).closedBall x r = p.closedBall x (r / c) := by @@ -899,7 +899,7 @@ theorem smul_ball_zero {p : Seminorm 𝕜 E} {k : 𝕜} {r : ℝ} (hk : k ≠ 0) k • p.ball 0 r = p.ball 0 (‖k‖ * r) := by ext rw [mem_smul_set_iff_inv_smul_mem₀ hk, p.mem_ball_zero, p.mem_ball_zero, map_smul_eq_mul, - norm_inv, ← div_eq_inv_mul, div_lt_iff (norm_pos_iff.2 hk), mul_comm] + norm_inv, ← div_eq_inv_mul, div_lt_iff₀ (norm_pos_iff.2 hk), mul_comm] theorem smul_closedBall_subset {p : Seminorm 𝕜 E} {k : 𝕜} {r : ℝ} : k • p.closedBall 0 r ⊆ p.closedBall 0 (‖k‖ * r) := by @@ -952,7 +952,7 @@ protected theorem absorbent_closedBall (hpr : p x < r) : Absorbent 𝕜 (closedB theorem smul_ball_preimage (p : Seminorm 𝕜 E) (y : E) (r : ℝ) (a : 𝕜) (ha : a ≠ 0) : (a • ·) ⁻¹' p.ball y r = p.ball (a⁻¹ • y) (r / ‖a‖) := Set.ext fun _ => by - rw [mem_preimage, mem_ball, mem_ball, lt_div_iff (norm_pos_iff.mpr ha), mul_comm, ← + rw [mem_preimage, mem_ball, mem_ball, lt_div_iff₀ (norm_pos_iff.mpr ha), mul_comm, ← map_smul_eq_mul p, smul_sub, smul_inv_smul₀ ha] end NormedField @@ -1047,7 +1047,7 @@ theorem continuousAt_zero' [TopologicalSpace E] [ContinuousConstSMul 𝕜 E] {p obtain ⟨k, hk₀, hk⟩ : ∃ k : 𝕜, 0 < ‖k‖ ∧ ‖k‖ * r < ε := by rcases le_or_lt r 0 with hr | hr · use 1; simpa using hr.trans_lt hε - · simpa [lt_div_iff hr] using exists_norm_lt 𝕜 (div_pos hε hr) + · simpa [lt_div_iff₀ hr] using exists_norm_lt 𝕜 (div_pos hε hr) rw [← set_smul_mem_nhds_zero_iff (norm_pos_iff.1 hk₀), smul_closedBall_zero hk₀] at hp exact mem_of_superset hp <| p.closedBall_mono hk.le @@ -1184,13 +1184,13 @@ lemma rescale_to_shell_zpow (p : Seminorm 𝕜 E) {c : 𝕜} (hc : 1 < ‖c‖) refine ⟨-(n+1), ?_, ?_, ?_, ?_⟩ · show c ^ (-(n + 1)) ≠ 0; exact zpow_ne_zero _ (norm_pos_iff.1 cpos) · show p ((c ^ (-(n + 1))) • x) < ε - rw [map_smul_eq_mul, zpow_neg, norm_inv, ← div_eq_inv_mul, div_lt_iff cnpos, mul_comm, + rw [map_smul_eq_mul, zpow_neg, norm_inv, ← div_eq_inv_mul, div_lt_iff₀ cnpos, mul_comm, norm_zpow] - exact (div_lt_iff εpos).1 (hn.2) + exact (div_lt_iff₀ εpos).1 (hn.2) · show ε / ‖c‖ ≤ p (c ^ (-(n + 1)) • x) rw [zpow_neg, div_le_iff₀ cpos, map_smul_eq_mul, norm_inv, norm_zpow, zpow_add₀ (ne_of_gt cpos), zpow_one, mul_inv_rev, mul_comm, ← mul_assoc, ← mul_assoc, mul_inv_cancel₀ (ne_of_gt cpos), - one_mul, ← div_eq_inv_mul, le_div_iff₀ (zpow_pos_of_pos cpos _), mul_comm] + one_mul, ← div_eq_inv_mul, le_div_iff₀ (zpow_pos cpos _), mul_comm] exact (le_div_iff₀ εpos).1 hn.1 · show ‖(c ^ (-(n + 1)))‖⁻¹ ≤ ε⁻¹ * ‖c‖ * p x have : ε⁻¹ * ‖c‖ * p x = ε⁻¹ * p x * ‖c‖ := by ring diff --git a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean index 71515ffc2fc55..a38081bf15582 100644 --- a/Mathlib/Analysis/SpecialFunctions/Bernstein.lean +++ b/Mathlib/Analysis/SpecialFunctions/Bernstein.lean @@ -3,10 +3,11 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ +import Mathlib.Algebra.Order.Field.Power import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.RingTheory.Polynomial.Bernstein -import Mathlib.Topology.ContinuousFunction.Polynomial -import Mathlib.Topology.ContinuousFunction.Compact +import Mathlib.Topology.ContinuousMap.Polynomial +import Mathlib.Topology.ContinuousMap.Compact /-! # Bernstein approximations and Weierstrass' theorem diff --git a/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean b/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean index 402c63a136cb7..c74cbff25c9e5 100644 --- a/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean +++ b/Mathlib/Analysis/SpecialFunctions/BinaryEntropy.lean @@ -80,8 +80,8 @@ lemma binEntropy_two_inv_add (p : ℝ) : binEntropy (2⁻¹ + p) = binEntropy (2 lemma binEntropy_pos (hp₀ : 0 < p) (hp₁ : p < 1) : 0 < binEntropy p := by unfold binEntropy have : 0 < 1 - p := sub_pos.2 hp₁ - have : 0 < log p⁻¹ := log_pos <| one_lt_inv hp₀ hp₁ - have : 0 < log (1 - p)⁻¹ := log_pos <| one_lt_inv ‹_› (sub_lt_self _ hp₀) + have : 0 < log p⁻¹ := log_pos <| (one_lt_inv₀ hp₀).2 hp₁ + have : 0 < log (1 - p)⁻¹ := log_pos <| (one_lt_inv₀ ‹_›).2 (sub_lt_self _ hp₀) positivity lemma binEntropy_nonneg (hp₀ : 0 ≤ p) (hp₁ : p ≤ 1) : 0 ≤ binEntropy p := by @@ -397,7 +397,7 @@ lemma qaryEntropy_strictAntiOn (qLe2 : 2 ≤ q) : · exact qaryEntropy_continuous.continuousOn · intro p hp have : 2 ≤ (q : ℝ) := Nat.ofNat_le_cast.mpr qLe2 - have qinv_lt_1 : (q : ℝ)⁻¹ < 1 := inv_lt_one (by linarith) + have qinv_lt_1 : (q : ℝ)⁻¹ < 1 := inv_lt_one_of_one_lt₀ (by linarith) have zero_lt_1_sub_p : 0 < 1 - p := by simp_all only [sub_pos, hp.2, interior_Icc, mem_Ioo] simp only [one_div, interior_Icc, mem_Ioo] at hp rw [deriv_qaryEntropy (by linarith)] diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean index 18ea3db3671d5..d717114a27b82 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Analytic.lean @@ -11,7 +11,7 @@ import Mathlib.Analysis.SpecialFunctions.Complex.LogDeriv /-! # Various complex special functions are analytic -`exp`, `log`, and `cpow` are analytic, since they are differentiable. +`log`, and `cpow` are analytic, since they are differentiable. -/ open Complex Set @@ -20,22 +20,6 @@ open scoped Topology variable {E : Type} [NormedAddCommGroup E] [NormedSpace ℂ E] variable {f g : E → ℂ} {z : ℂ} {x : E} {s : Set E} -/-- `exp` is entire -/ -theorem analyticOn_cexp : AnalyticOn ℂ exp univ := by - rw [analyticOn_univ_iff_differentiable]; exact differentiable_exp - -/-- `exp` is analytic at any point -/ -theorem analyticAt_cexp : AnalyticAt ℂ exp z := - analyticOn_cexp z (mem_univ _) - -/-- `exp ∘ f` is analytic -/ -theorem AnalyticAt.cexp (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (fun z ↦ exp (f z)) x := - analyticAt_cexp.comp fa - -/-- `exp ∘ f` is analytic -/ -theorem AnalyticOn.cexp (fs : AnalyticOn ℂ f s) : AnalyticOn ℂ (fun z ↦ exp (f z)) s := - fun z n ↦ analyticAt_cexp.comp (fs z n) - /-- `log` is analytic away from nonpositive reals -/ theorem analyticAt_clog (m : z ∈ slitPlane) : AnalyticAt ℂ log z := by rw [analyticAt_iff_eventually_differentiableAt] @@ -48,21 +32,40 @@ theorem AnalyticAt.clog (fa : AnalyticAt ℂ f x) (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ log (f z)) x := (analyticAt_clog m).comp fa +theorem AnalyticWithinAt.clog (fa : AnalyticWithinAt ℂ f s x) (m : f x ∈ slitPlane) : + AnalyticWithinAt ℂ (fun z ↦ log (f z)) s x := + (analyticAt_clog m).comp_analyticWithinAt fa + /-- `log` is analytic away from nonpositive reals -/ +theorem AnalyticOnNhd.clog (fs : AnalyticOnNhd ℂ f s) (m : ∀ z ∈ s, f z ∈ slitPlane) : + AnalyticOnNhd ℂ (fun z ↦ log (f z)) s := + fun z n ↦ (analyticAt_clog (m z n)).comp (fs z n) + theorem AnalyticOn.clog (fs : AnalyticOn ℂ f s) (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOn ℂ (fun z ↦ log (f z)) s := - fun z n ↦ (analyticAt_clog (m z n)).comp (fs z n) + fun z n ↦ (analyticAt_clog (m z n)).analyticWithinAt.comp (fs z n) m /-- `f z ^ g z` is analytic if `f z` is not a nonpositive real -/ -theorem AnalyticAt.cpow (fa : AnalyticAt ℂ f x) (ga : AnalyticAt ℂ g x) - (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ f z ^ g z) x := by - have e : (fun z ↦ f z ^ g z) =ᶠ[𝓝 x] fun z ↦ exp (log (f z) * g z) := by - filter_upwards [(fa.continuousAt.eventually_ne (slitPlane_ne_zero m))] +theorem AnalyticWithinAt.cpow (fa : AnalyticWithinAt ℂ f s x) (ga : AnalyticWithinAt ℂ g s x) + (m : f x ∈ slitPlane) : AnalyticWithinAt ℂ (fun z ↦ f z ^ g z) s x := by + have e : (fun z ↦ f z ^ g z) =ᶠ[𝓝[insert x s] x] fun z ↦ exp (log (f z) * g z) := by + filter_upwards [(fa.continuousWithinAt_insert.eventually_ne (slitPlane_ne_zero m))] intro z fz simp only [fz, cpow_def, if_false] - rw [analyticAt_congr e] + apply AnalyticWithinAt.congr_of_eventuallyEq_insert _ e exact ((fa.clog m).mul ga).cexp +/-- `f z ^ g z` is analytic if `f z` is not a nonpositive real -/ +theorem AnalyticAt.cpow (fa : AnalyticAt ℂ f x) (ga : AnalyticAt ℂ g x) + (m : f x ∈ slitPlane) : AnalyticAt ℂ (fun z ↦ f z ^ g z) x := by + rw [← analyticWithinAt_univ] at fa ga ⊢ + exact fa.cpow ga m + +/-- `f z ^ g z` is analytic if `f z` avoids nonpositive reals -/ +theorem AnalyticOnNhd.cpow (fs : AnalyticOnNhd ℂ f s) (gs : AnalyticOnNhd ℂ g s) + (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOnNhd ℂ (fun z ↦ f z ^ g z) s := + fun z n ↦ (fs z n).cpow (gs z n) (m z n) + /-- `f z ^ g z` is analytic if `f z` avoids nonpositive reals -/ theorem AnalyticOn.cpow (fs : AnalyticOn ℂ f s) (gs : AnalyticOn ℂ g s) (m : ∀ z ∈ s, f z ∈ slitPlane) : AnalyticOn ℂ (fun z ↦ f z ^ g z) s := diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean b/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean index d9d625ead931a..d5bc0c1f1b5ba 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/Arctan.lean @@ -73,7 +73,7 @@ theorem arctan_tan {z : ℂ} (h₀ : z ≠ π / 2) (h₁ : -(π / 2) < z.re) (h rw [← exp_mul_I, ← exp_mul_I, ← exp_sub, show z * I - -z * I = 2 * (I * z) by ring, log_exp, show -I / 2 * (2 * (I * z)) = -(I * I) * z by ring, I_mul_I, neg_neg, one_mul] all_goals norm_num - · rwa [← div_lt_iff' two_pos, neg_div] + · rwa [← div_lt_iff₀' two_pos, neg_div] · rwa [← le_div_iff₀' two_pos] @[simp, norm_cast] diff --git a/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean index 7d994e5d897af..f5e05a1e202df 100644 --- a/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean +++ b/Mathlib/Analysis/SpecialFunctions/Complex/LogBounds.lean @@ -110,7 +110,7 @@ lemma norm_one_add_mul_inv_le {t : ℝ} (ht : t ∈ Set.Icc 0 1) {z : ℂ} (hz : ‖(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) ?_ + refine inv_anti₀ (by linarith) ?_ calc 1 - ‖z‖ _ ≤ 1 - t * ‖z‖ := by nlinarith [norm_nonneg z] diff --git a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean index 2986597856fcc..8c7bd3f605070 100644 --- a/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean +++ b/Mathlib/Analysis/SpecialFunctions/ContinuousFunctionalCalculus/ExpLog.lean @@ -7,7 +7,7 @@ Authors: Frédéric Dupuis import Mathlib.Analysis.Normed.Algebra.Spectrum import Mathlib.Analysis.SpecialFunctions.Exponential import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unital -import Mathlib.Topology.ContinuousFunction.StarOrdered +import Mathlib.Topology.ContinuousMap.StarOrdered /-! # The exponential and logarithm based on the continuous functional calculus diff --git a/Mathlib/Analysis/SpecialFunctions/Exp.lean b/Mathlib/Analysis/SpecialFunctions/Exp.lean index d9317023529a2..8d018a967ecb0 100644 --- a/Mathlib/Analysis/SpecialFunctions/Exp.lean +++ b/Mathlib/Analysis/SpecialFunctions/Exp.lean @@ -263,7 +263,7 @@ theorem tendsto_exp_div_pow_atTop (n : ℕ) : Tendsto (fun x => exp x / x ^ n) a eventually_atTop.1 ((tendsto_pow_const_div_const_pow_of_one_lt n (one_lt_exp_iff.2 zero_lt_one)).eventually (gt_mem_nhds this)) - simp only [← exp_nat_mul, mul_one, div_lt_iff, exp_pos, ← div_eq_inv_mul] at hN + simp only [← exp_nat_mul, mul_one, div_lt_iff₀, exp_pos, ← div_eq_inv_mul] at hN refine ⟨N, trivial, fun x hx => ?_⟩ rw [Set.mem_Ioi] at hx have hx₀ : 0 < x := (Nat.cast_nonneg N).trans_lt hx diff --git a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean index 31ff5558fe80a..8506d9e055ab1 100644 --- a/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/ExpDeriv.lean @@ -6,6 +6,7 @@ Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne import Mathlib.Analysis.Complex.RealDeriv import Mathlib.Analysis.Calculus.ContDiff.RCLike import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas +import Mathlib.Analysis.SpecialFunctions.Exponential /-! # Complex and real exponential @@ -24,6 +25,41 @@ open scoped Topology /-! ## `Complex.exp` -/ +section + +open Complex + +variable {E : Type} [NormedAddCommGroup E] [NormedSpace ℂ E] +variable {f g : E → ℂ} {z : ℂ} {x : E} {s : Set E} + +/-- `exp` is entire -/ +theorem analyticOnNhd_cexp : AnalyticOnNhd ℂ exp univ := by + rw [Complex.exp_eq_exp_ℂ] + exact fun x _ ↦ NormedSpace.exp_analytic x + +theorem analyticOn_cexp : AnalyticOn ℂ exp univ := analyticOnNhd_cexp.analyticOn + +/-- `exp` is analytic at any point -/ +theorem analyticAt_cexp : AnalyticAt ℂ exp z := + analyticOnNhd_cexp z (mem_univ _) + +/-- `exp ∘ f` is analytic -/ +theorem AnalyticAt.cexp (fa : AnalyticAt ℂ f x) : AnalyticAt ℂ (fun z ↦ exp (f z)) x := + analyticAt_cexp.comp fa + +theorem AnalyticWithinAt.cexp (fa : AnalyticWithinAt ℂ f s x) : + AnalyticWithinAt ℂ (fun z ↦ exp (f z)) s x := + analyticAt_cexp.comp_analyticWithinAt fa + +/-- `exp ∘ f` is analytic -/ +theorem AnalyticOnNhd.cexp (fs : AnalyticOnNhd ℂ f s) : AnalyticOnNhd ℂ (fun z ↦ exp (f z)) s := + fun z n ↦ analyticAt_cexp.comp (fs z n) + +theorem AnalyticOn.cexp (fs : AnalyticOn ℂ f s) : AnalyticOn ℂ (fun z ↦ exp (f z)) s := + analyticOnNhd_cexp.comp_analyticOn fs (mapsTo_univ _ _) + +end + namespace Complex variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] [NormedAlgebra 𝕜 ℂ] @@ -52,17 +88,8 @@ theorem iter_deriv_exp : ∀ n : ℕ, deriv^[n] exp = exp | 0 => rfl | n + 1 => by rw [iterate_succ_apply, deriv_exp, iter_deriv_exp n] -theorem contDiff_exp : ∀ {n}, ContDiff 𝕜 n exp := by - -- Porting note: added `@` due to `∀ {n}` weirdness above - refine @(contDiff_all_iff_nat.2 fun n => ?_) - have : ContDiff ℂ (↑n) exp := by - induction n with - | zero => exact contDiff_zero.2 continuous_exp - | succ n ihn => - rw [contDiff_succ_iff_deriv] - use differentiable_exp - rwa [deriv_exp] - exact this.restrict_scalars 𝕜 +theorem contDiff_exp {n : ℕ∞} : ContDiff 𝕜 n exp := + analyticOnNhd_cexp.restrictScalars.contDiff theorem hasStrictDerivAt_exp (x : ℂ) : HasStrictDerivAt exp (exp x) x := contDiff_exp.contDiffAt.hasStrictDerivAt' (hasDerivAt_exp x) le_rfl @@ -156,12 +183,44 @@ theorem iteratedDeriv_cexp_const_mul (n : ℕ) (c : ℂ) : (iteratedDeriv n fun s : ℂ => exp (c * s)) = fun s => c ^ n * exp (c * s) := by rw [iteratedDeriv_const_mul contDiff_exp, iteratedDeriv_eq_iterate, iter_deriv_exp] - /-! ## `Real.exp` -/ -namespace Real +section + +open Real + +variable {x : ℝ} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {f : E → ℝ} {s : Set E} + +/-- `exp` is entire -/ +theorem analyticOnNhd_rexp : AnalyticOnNhd ℝ exp univ := by + rw [Real.exp_eq_exp_ℝ] + exact fun x _ ↦ NormedSpace.exp_analytic x + +theorem analyticOn_rexp : AnalyticOn ℝ exp univ := analyticOnNhd_rexp.analyticOn + +/-- `exp` is analytic at any point -/ +theorem analyticAt_rexp : AnalyticAt ℝ exp x := + analyticOnNhd_rexp x (mem_univ _) -variable {x y z : ℝ} +/-- `exp ∘ f` is analytic -/ +theorem AnalyticAt.rexp {x : E} (fa : AnalyticAt ℝ f x) : AnalyticAt ℝ (fun z ↦ exp (f z)) x := + analyticAt_rexp.comp fa + +theorem AnalyticWithinAt.rexp {x : E} (fa : AnalyticWithinAt ℝ f s x) : + AnalyticWithinAt ℝ (fun z ↦ exp (f z)) s x := + analyticAt_rexp.comp_analyticWithinAt fa + +/-- `exp ∘ f` is analytic -/ +theorem AnalyticOnNhd.rexp {s : Set E} (fs : AnalyticOnNhd ℝ f s) : + AnalyticOnNhd ℝ (fun z ↦ exp (f z)) s := + fun z n ↦ analyticAt_rexp.comp (fs z n) + +theorem AnalyticOn.rexp (fs : AnalyticOn ℝ f s) : AnalyticOn ℝ (fun z ↦ exp (f z)) s := + analyticOnNhd_rexp.comp_analyticOn fs (mapsTo_univ _ _) + +end + +namespace Real theorem hasStrictDerivAt_exp (x : ℝ) : HasStrictDerivAt exp (exp x) x := (Complex.hasStrictDerivAt_exp x).real_of_complex @@ -169,12 +228,12 @@ theorem hasStrictDerivAt_exp (x : ℝ) : HasStrictDerivAt exp (exp x) x := theorem hasDerivAt_exp (x : ℝ) : HasDerivAt exp (exp x) x := (Complex.hasDerivAt_exp x).real_of_complex -theorem contDiff_exp {n} : ContDiff ℝ n exp := +theorem contDiff_exp {n : ℕ∞} : ContDiff ℝ n exp := Complex.contDiff_exp.real_of_complex theorem differentiable_exp : Differentiable ℝ exp := fun x => (hasDerivAt_exp x).differentiableAt -theorem differentiableAt_exp : DifferentiableAt ℝ exp x := +theorem differentiableAt_exp {x : ℝ} : DifferentiableAt ℝ exp x := differentiable_exp x @[simp] diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean index c12393d6b86df..ac24c2337c490 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Basic.lean @@ -115,7 +115,7 @@ def GammaIntegral (s : ℂ) : ℂ := theorem GammaIntegral_conj (s : ℂ) : GammaIntegral (conj s) = conj (GammaIntegral s) := by rw [GammaIntegral, GammaIntegral, ← integral_conj] - refine setIntegral_congr measurableSet_Ioi fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun x hx => ?_ dsimp only rw [RingHom.map_mul, conj_ofReal, cpow_def_of_ne_zero (ofReal_ne_zero.mpr (ne_of_gt hx)), cpow_def_of_ne_zero (ofReal_ne_zero.mpr (ne_of_gt hx)), ← exp_conj, RingHom.map_mul, ← @@ -126,7 +126,7 @@ theorem GammaIntegral_ofReal (s : ℝ) : have : ∀ r : ℝ, Complex.ofReal' r = @RCLike.ofReal ℂ _ r := fun r => rfl rw [GammaIntegral] conv_rhs => rw [this, ← _root_.integral_ofReal] - refine setIntegral_congr measurableSet_Ioi ?_ + refine setIntegral_congr_fun measurableSet_Ioi ?_ intro x hx; dsimp only conv_rhs => rw [← this] rw [ofReal_mul, ofReal_cpow (mem_Ioi.mp hx).le] @@ -377,7 +377,7 @@ 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] calc _ = ∫ (t : ℝ) in Ioi 0, (1 / r) ^ (a - 1) * (r * t) ^ (a - 1) * exp (-(r * t)) := by - refine MeasureTheory.setIntegral_congr measurableSet_Ioi (fun x hx ↦ ?_) + refine MeasureTheory.setIntegral_congr_fun 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⁻¹, @@ -487,7 +487,7 @@ theorem Gamma_eq_integral {s : ℝ} (hs : 0 < s) : have cc : ∀ r : ℝ, Complex.ofReal' r = @RCLike.ofReal ℂ _ r := fun r => rfl conv_lhs => rw [this]; enter [1, 2, x]; rw [cc] rw [_root_.integral_ofReal, ← cc, Complex.ofReal_re] - refine setIntegral_congr measurableSet_Ioi fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun x hx => ?_ push_cast rw [Complex.ofReal_cpow (le_of_lt hx)] push_cast; rfl @@ -551,10 +551,9 @@ lemma integral_rpow_mul_exp_neg_mul_Ioi {a r : ℝ} (ha : 0 < a) (hr : 0 < r) : ∫ t : ℝ in Ioi 0, t ^ (a - 1) * exp (-(r * t)) = (1 / r) ^ a * Gamma a := by rw [← ofReal_inj, ofReal_mul, ← Gamma_ofReal, ofReal_cpow (by positivity), ofReal_div] convert integral_cpow_mul_exp_neg_mul_Ioi (by rwa [ofReal_re] : 0 < (a : ℂ).re) hr - refine _root_.integral_ofReal.symm.trans <| setIntegral_congr measurableSet_Ioi (fun t ht ↦ ?_) + refine integral_ofReal.symm.trans <| setIntegral_congr_fun measurableSet_Ioi (fun t ht ↦ ?_) norm_cast - rw [← ofReal_cpow (le_of_lt ht), RCLike.ofReal_mul] - rfl + simp_rw [← ofReal_cpow ht.le, RCLike.ofReal_mul, coe_algebraMap] open Lean.Meta Qq Mathlib.Meta.Positivity in /-- The `positivity` extension which identifies expressions of the form `Gamma a`. -/ diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean index 8f72e2ec290e0..feeba0621e3e6 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/Beta.lean @@ -114,7 +114,7 @@ theorem betaIntegral_scaled (s t : ℂ) {a : ℝ} (ha : 0 < a) : rw [A, mul_assoc, ← intervalIntegral.integral_const_mul, ← real_smul, ← zero_div a, ← div_self ha.ne', ← intervalIntegral.integral_comp_div _ ha.ne', zero_div] simp_rw [intervalIntegral.integral_of_le ha.le] - refine setIntegral_congr measurableSet_Ioc fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioc fun x hx => ?_ rw [mul_mul_mul_comm] congr 1 · rw [← mul_cpow_ofReal_nonneg ha.le (div_pos hx.1 ha).le, ofReal_div, mul_div_cancel₀ _ ha'] @@ -134,7 +134,7 @@ theorem Gamma_mul_Gamma_eq_betaIntegral {s t : ℂ} (hs : 0 < re s) (ht : 0 < re have hst : 0 < re (s + t) := by rw [add_re]; exact add_pos hs ht rw [Gamma_eq_integral hs, Gamma_eq_integral ht, Gamma_eq_integral hst, GammaIntegral, GammaIntegral, GammaIntegral, ← conv_int, ← integral_mul_right (betaIntegral _ _)] - refine setIntegral_congr measurableSet_Ioi fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun x hx => ?_ rw [mul_assoc, ← betaIntegral_scaled s t hx, ← intervalIntegral.integral_const_mul] congr 1 with y : 1 push_cast @@ -259,7 +259,7 @@ theorem GammaSeq_eq_approx_Gamma_integral {s : ℂ} (hs : 0 < re s) {n : ℕ} (h ← intervalIntegral.integral_const_mul, ← intervalIntegral.integral_const_mul] swap; · exact Nat.cast_ne_zero.mpr hn simp_rw [intervalIntegral.integral_of_le zero_le_one] - refine setIntegral_congr measurableSet_Ioc fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioc fun x hx => ?_ push_cast have hn' : (n : ℂ) ≠ 0 := Nat.cast_ne_zero.mpr hn have A : (n : ℂ) ^ s = (n : ℂ) ^ (s - 1) * n := by @@ -328,7 +328,7 @@ theorem approx_Gamma_integral_tendsto_Gamma_integral {s : ℂ} (hs : 0 < re s) : 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) _), + (pow_nonneg (sub_nonneg.mpr <| div_le_one_of_le₀ hxn <| by positivity) _), Complex.norm_eq_abs, abs_cpow_eq_rpow_re_of_pos hx, sub_re, one_re, mul_le_mul_right (rpow_pos_of_pos hx _)] exact one_sub_div_pow_le_exp_neg hxn @@ -547,13 +547,13 @@ theorem Gamma_mul_Gamma_add_half (s : ℂ) : convert congr_arg Inv.inv (congr_fun this s) using 1 · rw [mul_inv, inv_inv, inv_inv] · rw [div_eq_mul_inv, mul_inv, mul_inv, inv_inv, inv_inv, ← cpow_neg, neg_sub] - have h1 : AnalyticOn ℂ (fun z : ℂ => (Gamma z)⁻¹ * (Gamma (z + 1 / 2))⁻¹) univ := by - refine DifferentiableOn.analyticOn ?_ isOpen_univ + have h1 : AnalyticOnNhd ℂ (fun z : ℂ => (Gamma z)⁻¹ * (Gamma (z + 1 / 2))⁻¹) univ := by + refine DifferentiableOn.analyticOnNhd ?_ isOpen_univ refine (differentiable_one_div_Gamma.mul ?_).differentiableOn exact differentiable_one_div_Gamma.comp (differentiable_id.add (differentiable_const _)) - have h2 : AnalyticOn ℂ + have h2 : AnalyticOnNhd ℂ (fun z => (Gamma (2 * z))⁻¹ * (2 : ℂ) ^ (2 * z - 1) / ↑(√π)) univ := by - refine DifferentiableOn.analyticOn ?_ isOpen_univ + refine DifferentiableOn.analyticOnNhd ?_ isOpen_univ refine (Differentiable.mul ?_ (differentiable_const _)).differentiableOn apply Differentiable.mul · exact differentiable_one_div_Gamma.comp (differentiable_id'.const_mul _) @@ -563,7 +563,7 @@ theorem Gamma_mul_Gamma_add_half (s : ℂ) : rw [tendsto_nhdsWithin_iff]; constructor · exact tendsto_nhdsWithin_of_tendsto_nhds continuous_ofReal.continuousAt · exact eventually_nhdsWithin_iff.mpr (Eventually.of_forall fun t ht => ofReal_ne_one.mpr ht) - refine AnalyticOn.eq_of_frequently_eq h1 h2 (h3.frequently ?_) + refine AnalyticOnNhd.eq_of_frequently_eq h1 h2 (h3.frequently ?_) refine ((Eventually.filter_mono nhdsWithin_le_nhds) ?_).frequently refine (eventually_gt_nhds zero_lt_one).mp (Eventually.of_forall fun t ht => ?_) rw [← mul_inv, Gamma_ofReal, (by norm_num : (t : ℂ) + 1 / 2 = ↑(t + 1 / 2)), Gamma_ofReal, ← diff --git a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean index f3bd9a9a2e9a4..c9f1f89b0bd5a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gamma/BohrMollerup.lean @@ -94,7 +94,7 @@ theorem Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma {s t a b : ℝ} (hs : 0 < MeasureTheory.integral_mul_le_Lp_mul_Lq_of_nonneg e (posf' a s) (posf' b t) (f_mem_Lp ha hs) (f_mem_Lp hb ht) using 1 - · refine setIntegral_congr measurableSet_Ioi fun x hx => ?_ + · refine setIntegral_congr_fun measurableSet_Ioi fun x hx => ?_ dsimp only have A : exp (-x) = exp (-a * x) * exp (-b * x) := by rw [← exp_add, ← add_mul, ← neg_add, hab, neg_one_mul] @@ -103,7 +103,7 @@ theorem Gamma_mul_add_mul_le_rpow_Gamma_mul_rpow_Gamma {s t a b : ℝ} (hs : 0 < rw [A, B] ring · rw [one_div_one_div, one_div_one_div] - congr 2 <;> exact setIntegral_congr measurableSet_Ioi fun x hx => fpow (by assumption) _ hx + congr 2 <;> exact setIntegral_congr_fun measurableSet_Ioi fun x hx => fpow (by assumption) _ hx theorem convexOn_log_Gamma : ConvexOn ℝ (Ioi 0) (log ∘ Gamma) := by refine convexOn_iff_forall_pos.mpr ⟨convex_Ioi _, fun x hx y hy a b ha hb hab => ?_⟩ diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean index ea572b4ce3c4e..89db8290e3687 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/FourierTransform.lean @@ -332,18 +332,18 @@ theorem integral_cexp_neg_mul_sq_norm_add_of_euclideanSpace theorem integral_cexp_neg_mul_sq_norm_add (hb : 0 < b.re) (c : ℂ) (w : V) : ∫ v : V, cexp (- b * ‖v‖^2 + c * ⟪w, v⟫) = - (π / b) ^ (FiniteDimensional.finrank ℝ V / 2 : ℂ) * cexp (c ^ 2 * ‖w‖^2 / (4 * b)) := by + (π / b) ^ (Module.finrank ℝ V / 2 : ℂ) * cexp (c ^ 2 * ‖w‖^2 / (4 * b)) := by let e := (stdOrthonormalBasis ℝ V).repr.symm rw [← e.measurePreserving.integral_comp e.toHomeomorph.measurableEmbedding] convert integral_cexp_neg_mul_sq_norm_add_of_euclideanSpace hb c (e.symm w) <;> simp [LinearIsometryEquiv.inner_map_eq_flip] theorem integral_cexp_neg_mul_sq_norm (hb : 0 < b.re) : - ∫ v : V, cexp (- b * ‖v‖^2) = (π / b) ^ (FiniteDimensional.finrank ℝ V / 2 : ℂ) := by + ∫ v : V, cexp (- b * ‖v‖^2) = (π / b) ^ (Module.finrank ℝ V / 2 : ℂ) := by simpa using integral_cexp_neg_mul_sq_norm_add hb 0 (0 : V) theorem integral_rexp_neg_mul_sq_norm {b : ℝ} (hb : 0 < b) : - ∫ v : V, rexp (- b * ‖v‖^2) = (π / b) ^ (FiniteDimensional.finrank ℝ V / 2 : ℝ) := by + ∫ v : V, rexp (- b * ‖v‖^2) = (π / b) ^ (Module.finrank ℝ V / 2 : ℝ) := by rw [← ofReal_inj] convert integral_cexp_neg_mul_sq_norm (show 0 < (b : ℂ).re from hb) (V := V) · change ofRealLI (∫ (v : V), rexp (-b * ‖v‖ ^ 2)) = ∫ (v : V), cexp (-↑b * ↑‖v‖ ^ 2) @@ -354,7 +354,7 @@ theorem integral_rexp_neg_mul_sq_norm {b : ℝ} (hb : 0 < b) : theorem _root_.fourierIntegral_gaussian_innerProductSpace' (hb : 0 < b.re) (x w : V) : 𝓕 (fun v ↦ cexp (- b * ‖v‖^2 + 2 * π * Complex.I * ⟪x, v⟫)) w = - (π / b) ^ (FiniteDimensional.finrank ℝ V / 2 : ℂ) * cexp (-π ^ 2 * ‖x - w‖ ^ 2 / b) := by + (π / b) ^ (Module.finrank ℝ V / 2 : ℂ) * cexp (-π ^ 2 * ‖x - w‖ ^ 2 / b) := by simp only [neg_mul, fourierIntegral_eq', ofReal_neg, ofReal_mul, ofReal_ofNat, smul_eq_mul, ← Complex.exp_add, real_inner_comm w] convert integral_cexp_neg_mul_sq_norm_add hb (2 * π * Complex.I) (x - w) using 3 with v @@ -367,7 +367,7 @@ theorem _root_.fourierIntegral_gaussian_innerProductSpace' (hb : 0 < b.re) (x w theorem _root_.fourierIntegral_gaussian_innerProductSpace (hb : 0 < b.re) (w : V) : 𝓕 (fun v ↦ cexp (- b * ‖v‖^2)) w = - (π / b) ^ (FiniteDimensional.finrank ℝ V / 2 : ℂ) * cexp (-π ^ 2 * ‖w‖^2 / b) := by + (π / b) ^ (Module.finrank ℝ V / 2 : ℂ) * cexp (-π ^ 2 * ‖w‖^2 / b) := by simpa using fourierIntegral_gaussian_innerProductSpace' hb 0 w end InnerProductSpace diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean index 163d700eb16bb..1c044bfc8ba0e 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/GaussianIntegral.lean @@ -335,7 +335,7 @@ theorem Real.Gamma_one_half_eq : Real.Gamma (1 / 2) = √π := by rw [Gamma_eq_integral one_half_pos, ← integral_comp_rpow_Ioi_of_pos zero_lt_two] convert congr_arg (fun x : ℝ => 2 * x) (integral_gaussian_Ioi 1) using 1 · rw [← integral_mul_left] - refine setIntegral_congr measurableSet_Ioi fun x hx => ?_ + refine setIntegral_congr_fun measurableSet_Ioi fun x hx => ?_ dsimp only have : (x ^ (2 : ℝ)) ^ (1 / (2 : ℝ) - 1) = x⁻¹ := by rw [← rpow_mul (le_of_lt hx)] diff --git a/Mathlib/Analysis/SpecialFunctions/Gaussian/PoissonSummation.lean b/Mathlib/Analysis/SpecialFunctions/Gaussian/PoissonSummation.lean index 8347a8e9d6908..d543c9e1d418b 100644 --- a/Mathlib/Analysis/SpecialFunctions/Gaussian/PoissonSummation.lean +++ b/Mathlib/Analysis/SpecialFunctions/Gaussian/PoissonSummation.lean @@ -29,8 +29,6 @@ noncomputable section section GaussianPoisson -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 : ℝ) : diff --git a/Mathlib/Analysis/SpecialFunctions/Integrals.lean b/Mathlib/Analysis/SpecialFunctions/Integrals.lean index 506735693822c..31f51791cdb31 100644 --- a/Mathlib/Analysis/SpecialFunctions/Integrals.lean +++ b/Mathlib/Analysis/SpecialFunctions/Integrals.lean @@ -33,7 +33,7 @@ integrate, integration, integrable, integrability -/ -open Real Nat Set Finset +open Real Set Finset open scoped Real Interval @@ -580,8 +580,9 @@ theorem integral_mul_rpow_one_add_sq {t : ℝ} (ht : t ≠ -1) : end RpowCpow -/-! ### Integral of `sin x ^ n` -/ +open Nat +/-! ### Integral of `sin x ^ n` -/ theorem integral_sin_pow_aux : (∫ x in a..b, sin x ^ (n + 2)) = diff --git a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean index 79be49beb847d..5b9cbab201ab2 100644 --- a/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean +++ b/Mathlib/Analysis/SpecialFunctions/JapaneseBracket.lean @@ -27,7 +27,7 @@ noncomputable section open scoped NNReal Filter Topology ENNReal -open Asymptotics Filter Set Real MeasureTheory FiniteDimensional +open Asymptotics Filter Set Real MeasureTheory Module variable {E : Type*} [NormedAddCommGroup E] @@ -85,7 +85,7 @@ theorem finite_integral_rpow_sub_one_pow_aux {r : ℝ} (n : ℕ) (hnr : (n : ℝ refine IntegrableOn.setLIntegral_lt_top ?_ rw [← intervalIntegrable_iff_integrableOn_Ioc_of_le zero_le_one] apply intervalIntegral.intervalIntegrable_rpow' - rwa [neg_lt_neg_iff, inv_mul_lt_iff' hr, one_mul] + rwa [neg_lt_neg_iff, inv_mul_lt_iff₀' hr, one_mul] variable [MeasurableSpace E] [BorelSpace E] {μ : Measure E} [μ.IsAddHaarMeasure] diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Base.lean b/Mathlib/Analysis/SpecialFunctions/Log/Base.lean index 23dedfcd33066..f7fafb38f92f6 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Base.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Base.lean @@ -423,7 +423,7 @@ lemma Real.induction_Ico_mul {P : ℝ → Prop} (x₀ r : ℝ) (hr : 1 < r) (hx intro x hx have hx' : 0 < x / x₀ := div_pos (hx₀.trans_le hx) hx₀ refine this ⌊logb r (x / x₀)⌋₊ x ?_ - rw [mem_Ico, ← div_lt_iff hx₀, ← rpow_natCast, ← logb_lt_iff_lt_rpow hr hx', Nat.cast_add, + rw [mem_Ico, ← div_lt_iff₀ hx₀, ← rpow_natCast, ← logb_lt_iff_lt_rpow hr hx', Nat.cast_add, Nat.cast_one] exact ⟨hx, Nat.lt_floor_add_one _⟩ intro n diff --git a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean index 4698f6d30f954..ccc7141a90155 100644 --- a/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Log/Basic.lean @@ -281,17 +281,27 @@ theorem log_le_sub_one_of_pos {x : ℝ} (hx : 0 < x) : log x ≤ x - 1 := by lemma one_sub_inv_le_log_of_pos (hx : 0 < x) : 1 - x⁻¹ ≤ log x := by simpa [add_comm] using log_le_sub_one_of_pos (inv_pos.2 hx) +/-- See `Real.log_le_sub_one_of_pos` for the stronger version when `x ≠ 0`. -/ +lemma log_le_self (hx : 0 ≤ x) : log x ≤ x := by + obtain rfl | hx := hx.eq_or_lt + · simp + · exact (log_le_sub_one_of_pos hx).trans (by linarith) + +/-- See `Real.one_sub_inv_le_log_of_pos` for the stronger version when `x ≠ 0`. -/ +lemma neg_inv_le_log (hx : 0 ≤ x) : -x⁻¹ ≤ log x := by + rw [neg_le, ← log_inv]; exact log_le_self <| inv_nonneg.2 hx + /-- Bound for `|log x * x|` in the interval `(0, 1]`. -/ theorem abs_log_mul_self_lt (x : ℝ) (h1 : 0 < x) (h2 : x ≤ 1) : |log x * x| < 1 := by have : 0 < 1 / x := by simpa only [one_div, inv_pos] using h1 replace := log_le_sub_one_of_pos this replace : log (1 / x) < 1 / x := by linarith - rw [log_div one_ne_zero h1.ne', log_one, zero_sub, lt_div_iff h1] at this + rw [log_div one_ne_zero h1.ne', log_one, zero_sub, lt_div_iff₀ h1] at this have aux : 0 ≤ -log x * x := by refine mul_nonneg ?_ h1.le rw [← log_inv] apply log_nonneg - rw [← le_inv h1 zero_lt_one, inv_one] + rw [← le_inv_comm₀ h1 zero_lt_one, inv_one] exact h2 rw [← abs_of_nonneg aux, neg_mul, abs_neg] at this exact this diff --git a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean index 62dafde2c1433..46513cef6be86 100644 --- a/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean +++ b/Mathlib/Analysis/SpecialFunctions/PolarCoord.lean @@ -135,13 +135,13 @@ theorem integral_comp_polarCoord_symm {E : Type*} [NormedAddCommGroup E] [Normed symm calc ∫ p, f p = ∫ p in polarCoord.source, f p := by - rw [← integral_univ] - apply setIntegral_congr_set_ae + rw [← setIntegral_univ] + apply setIntegral_congr_set exact polarCoord_source_ae_eq_univ.symm _ = ∫ p in polarCoord.target, abs (B p).det • f (polarCoord.symm p) := by apply integral_target_eq_integral_abs_det_fderiv_smul volume A _ = ∫ p in polarCoord.target, p.1 • f (polarCoord.symm p) := by - apply setIntegral_congr polarCoord.open_target.measurableSet fun x hx => ?_ + apply setIntegral_congr_fun polarCoord.open_target.measurableSet fun x hx => ?_ rw [B_det, abs_of_pos] exact hx.1 diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean index 95944cd30ee97..58b6a5277c22c 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Asymptotics.lean @@ -190,7 +190,7 @@ theorem isTheta_exp_arg_mul_im (hl : IsBoundedUnder (· ≤ ·) l fun x => |(g x refine Real.isTheta_exp_comp_one.2 ⟨π * b, ?_⟩ rw [eventually_map] at hb ⊢ refine hb.mono fun x hx => ?_ - erw [abs_mul] + rw [abs_mul] exact mul_le_mul (abs_arg_le_pi _) hx (abs_nonneg _) Real.pi_pos.le theorem isBigO_cpow_rpow (hl : IsBoundedUnder (· ≤ ·) l fun x => |(g x).im|) : diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean index 9a2469906a661..c9a10865fd507 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Complex.lean @@ -175,7 +175,7 @@ lemma cpow_ofNat_mul' {x : ℂ} {n : ℕ} [n.AtLeastTwo] (hlt : -π < OfNat.ofNa lemma pow_cpow_nat_inv {x : ℂ} {n : ℕ} (h₀ : n ≠ 0) (hlt : -(π / n) < x.arg) (hle : x.arg ≤ π / n) : (x ^ n) ^ (n⁻¹ : ℂ) = x := by rw [← cpow_nat_mul', mul_inv_cancel₀ (Nat.cast_ne_zero.2 h₀), cpow_one] - · rwa [← div_lt_iff' (Nat.cast_pos.2 h₀.bot_lt), neg_div] + · rwa [← div_lt_iff₀' (Nat.cast_pos.2 h₀.bot_lt), neg_div] · rwa [← le_div_iff₀' (Nat.cast_pos.2 h₀.bot_lt)] lemma pow_cpow_ofNat_inv {x : ℂ} {n : ℕ} [n.AtLeastTwo] (hlt : -(π / OfNat.ofNat n) < x.arg) diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean index 529dea6298d19..841d4fc4de757 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Continuity.lean @@ -332,8 +332,7 @@ theorem continuousAt_ofReal_cpow (x : ℝ) (y : ℂ) (h : 0 < y.re ∨ x ≠ 0) ContinuousAt (fun p => (p.1 : ℂ) ^ p.2 : ℝ × ℂ → ℂ) (x, y) := by rcases lt_trichotomy (0 : ℝ) x with (hx | rfl | hx) · -- x > 0 : easy case - have : ContinuousAt (fun p => ⟨↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) (x, y) := - continuous_ofReal.continuousAt.prod_map continuousAt_id + have : ContinuousAt (fun p => ⟨↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) (x, y) := by fun_prop refine (continuousAt_cpow (Or.inl ?_)).comp this rwa [ofReal_re] · -- x = 0 : reduce to continuousAt_cpow_zero_of_re_pos @@ -341,15 +340,13 @@ theorem continuousAt_ofReal_cpow (x : ℝ) (y : ℂ) (h : 0 < y.re ∨ x ≠ 0) rw [ofReal_zero] apply continuousAt_cpow_zero_of_re_pos tauto - have B : ContinuousAt (fun p => ⟨↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) ⟨0, y⟩ := - continuous_ofReal.continuousAt.prod_map continuousAt_id + have B : ContinuousAt (fun p => ⟨↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) ⟨0, y⟩ := by fun_prop 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) ?_) exact fun p hp => (ofReal_cpow_of_nonpos (le_of_lt hp.1) p.2).symm - have A : ContinuousAt (fun p => ⟨-↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) (x, y) := - ContinuousAt.prod_map continuous_ofReal.continuousAt.neg continuousAt_id + have A : ContinuousAt (fun p => ⟨-↑p.1, p.2⟩ : ℝ × ℂ → ℂ × ℂ) (x, y) := by fun_prop apply ContinuousAt.mul · refine (continuousAt_cpow (Or.inl ?_)).comp A rwa [neg_re, ofReal_re, neg_pos] @@ -394,7 +391,7 @@ theorem eventually_pow_one_div_le (x : ℝ≥0) {y : ℝ≥0} (hy : 1 < y) : refine eventually_atTop.2 ⟨m + 1, fun n hn => ?_⟩ simp only [one_div] simpa only [NNReal.rpow_inv_le_iff (Nat.cast_pos.2 <| m.succ_pos.trans_le hn), - NNReal.rpow_natCast] using hm.le.trans (pow_le_pow_right hy.le (m.le_succ.trans hn)) + NNReal.rpow_natCast] using hm.le.trans (pow_right_mono₀ hy.le (m.le_succ.trans hn)) end NNReal diff --git a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean index 6a7ea43f88beb..b712f2e3cd568 100644 --- a/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean +++ b/Mathlib/Analysis/SpecialFunctions/Pow/Real.lean @@ -166,6 +166,22 @@ theorem abs_rpow_le_exp_log_mul (x y : ℝ) : |x ^ y| ≤ exp (log x * y) := by · by_cases hy : y = 0 <;> simp [hx, hy, zero_le_one] · rw [rpow_def_of_pos (abs_pos.2 hx), log_abs] +lemma rpow_inv_log (hx₀ : 0 < x) (hx₁ : x ≠ 1) : x ^ (log x)⁻¹ = exp 1 := by + rw [rpow_def_of_pos hx₀, mul_inv_cancel₀] + exact log_ne_zero.2 ⟨hx₀.ne', hx₁, (hx₀.trans' <| by norm_num).ne'⟩ + +/-- See `Real.rpow_inv_log` for the equality when `x ≠ 1` is strictly positive. -/ +lemma rpow_inv_log_le_exp_one : x ^ (log x)⁻¹ ≤ exp 1 := by + calc + _ ≤ |x ^ (log x)⁻¹| := le_abs_self _ + _ ≤ |x| ^ (log x)⁻¹ := abs_rpow_le_abs_rpow .. + rw [← log_abs] + obtain hx | hx := (abs_nonneg x).eq_or_gt + · simp [hx] + · rw [rpow_def_of_pos hx] + gcongr + exact mul_inv_le_one + theorem norm_rpow_of_nonneg {x y : ℝ} (hx_nonneg : 0 ≤ x) : ‖x ^ y‖ = ‖x‖ ^ y := by simp_rw [Real.norm_eq_abs] exact abs_rpow_of_nonneg hx_nonneg @@ -512,13 +528,13 @@ theorem monotoneOn_rpow_Ici_of_exponent_nonneg {r : ℝ} (hr : 0 ≤ r) : lemma rpow_lt_rpow_of_neg (hx : 0 < x) (hxy : x < y) (hz : z < 0) : y ^ z < x ^ z := by have := hx.trans hxy - rw [← inv_lt_inv, ← rpow_neg, ← rpow_neg] + rw [← inv_lt_inv₀, ← rpow_neg, ← rpow_neg] on_goal 1 => refine rpow_lt_rpow ?_ hxy (neg_pos.2 hz) all_goals positivity lemma rpow_le_rpow_of_nonpos (hx : 0 < x) (hxy : x ≤ y) (hz : z ≤ 0) : y ^ z ≤ x ^ z := by have := hx.trans_le hxy - rw [← inv_le_inv, ← rpow_neg, ← rpow_neg] + rw [← inv_le_inv₀, ← rpow_neg, ← rpow_neg] on_goal 1 => refine rpow_le_rpow ?_ hxy (neg_nonneg.2 hz) all_goals positivity @@ -576,7 +592,7 @@ theorem rpow_lt_rpow_of_exponent_neg {x y z : ℝ} (hy : 0 < y) (hxy : y < x) (h x ^ z < y ^ z := by have hx : 0 < x := hy.trans hxy rw [← neg_neg z, Real.rpow_neg (le_of_lt hx) (-z), Real.rpow_neg (le_of_lt hy) (-z), - inv_lt_inv (rpow_pos_of_pos hx _) (rpow_pos_of_pos hy _)] + inv_lt_inv₀ (rpow_pos_of_pos hx _) (rpow_pos_of_pos hy _)] exact Real.rpow_lt_rpow (by positivity) hxy <| neg_pos_of_neg hz theorem strictAntiOn_rpow_Ioi_of_exponent_neg {r : ℝ} (hr : r < 0) : @@ -807,7 +823,7 @@ theorem rpow_le_one_iff_of_pos (hx : 0 < x) : x ^ y ≤ 1 ↔ 1 ≤ x ∧ y ≤ /-- Bound for `|log x * x ^ t|` in the interval `(0, 1]`, for positive real `t`. -/ theorem abs_log_mul_self_rpow_lt (x t : ℝ) (h1 : 0 < x) (h2 : x ≤ 1) (ht : 0 < t) : |log x * x ^ t| < 1 / t := by - rw [lt_div_iff ht] + rw [lt_div_iff₀ ht] have := abs_log_mul_self_lt (x ^ t) (rpow_pos_of_pos h1 t) (rpow_le_one h1.le h2 ht.le) rwa [log_rpow h1, mul_assoc, abs_mul, abs_of_pos ht, mul_comm] at this diff --git a/Mathlib/Analysis/SpecialFunctions/Stirling.lean b/Mathlib/Analysis/SpecialFunctions/Stirling.lean index 0ff3d40698098..35d9ac4c47d5b 100644 --- a/Mathlib/Analysis/SpecialFunctions/Stirling.lean +++ b/Mathlib/Analysis/SpecialFunctions/Stirling.lean @@ -102,12 +102,12 @@ theorem log_stirlingSeq_diff_le_geo_sum (n : ℕ) : · simp_rw [← _root_.pow_succ'] at this exact this rw [one_div, inv_pow] - exact inv_lt_one (one_lt_pow ((lt_add_iff_pos_left 1).mpr <| by positivity) two_ne_zero) + exact inv_lt_one_of_one_lt₀ (one_lt_pow₀ (lt_add_of_pos_left _ <| by positivity) two_ne_zero) have hab (k : ℕ) : (1 : ℝ) / (2 * ↑(k + 1) + 1) * ((1 / (2 * ↑(n + 1) + 1)) ^ 2) ^ ↑(k + 1) ≤ (((1 : ℝ) / (2 * ↑(n + 1) + 1)) ^ 2) ^ ↑(k + 1) := by refine mul_le_of_le_one_left (pow_nonneg h_nonneg ↑(k + 1)) ?_ rw [one_div] - exact inv_le_one (le_add_of_nonneg_left <| by positivity) + exact inv_le_one_of_one_le₀ (le_add_of_nonneg_left <| by positivity) exact hasSum_le hab (log_stirlingSeq_diff_hasSum n) g /-- We have the bound `log (stirlingSeq n) - log (stirlingSeq (n+1))` ≤ 1/(4 n^2) diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean index 364f5e72076c6..c5ed691712471 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Angle.lean @@ -554,7 +554,7 @@ theorem nsmul_toReal_eq_mul {n : ℕ} (h : n ≠ 0) {θ : Angle} : (n • θ).toReal = n * θ.toReal ↔ θ.toReal ∈ Set.Ioc (-π / n) (π / n) := by nth_rw 1 [← coe_toReal θ] have h' : 0 < (n : ℝ) := mod_cast Nat.pos_of_ne_zero h - rw [← coe_nsmul, nsmul_eq_mul, toReal_coe_eq_self_iff, Set.mem_Ioc, div_lt_iff' h', + rw [← coe_nsmul, nsmul_eq_mul, toReal_coe_eq_self_iff, Set.mem_Ioc, div_lt_iff₀' h', le_div_iff₀' h'] theorem two_nsmul_toReal_eq_two_mul {θ : Angle} : @@ -585,7 +585,7 @@ theorem two_nsmul_toReal_eq_two_mul_sub_two_pi {θ : Angle} : rw [← coe_nsmul, two_nsmul, ← two_mul, toReal_coe_eq_self_sub_two_pi_iff, Set.mem_Ioc] exact ⟨fun h => by linarith, fun h => - ⟨(div_lt_iff' (zero_lt_two' ℝ)).1 h, by linarith [pi_pos, toReal_le_pi θ]⟩⟩ + ⟨(div_lt_iff₀' (zero_lt_two' ℝ)).1 h, by linarith [pi_pos, toReal_le_pi θ]⟩⟩ theorem two_zsmul_toReal_eq_two_mul_sub_two_pi {θ : Angle} : ((2 : ℤ) • θ).toReal = 2 * θ.toReal - 2 * π ↔ π / 2 < θ.toReal := by diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean index 2ea81c6afbe95..6919f9dcbb728 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Arctan.lean @@ -208,7 +208,7 @@ lemma arctan_add_arctan_lt_pi_div_two {x y : ℝ} (h : x * y < 1) : arctan x + a cases' le_or_lt y 0 with hy hy · rw [← add_zero (π / 2), ← arctan_zero] exact add_lt_add_of_lt_of_le (arctan_lt_pi_div_two _) (tanOrderIso.symm.monotone hy) - · rw [← lt_div_iff hy, ← inv_eq_one_div] at h + · rw [← lt_div_iff₀ hy, ← inv_eq_one_div] at h replace h : arctan x < arctan y⁻¹ := tanOrderIso.symm.strictMono h rwa [arctan_inv_of_pos hy, lt_tsub_iff_right] at h @@ -228,7 +228,7 @@ theorem arctan_add_eq_add_pi {x y : ℝ} (h : 1 < x * y) (hx : 0 < x) : have hy : 0 < y := by have := mul_pos_iff.mp (zero_lt_one.trans h) simpa [hx, hx.asymm] - have k := arctan_add (mul_inv x y ▸ inv_lt_one h) + have k := arctan_add (mul_inv x y ▸ inv_lt_one_of_one_lt₀ h) rw [arctan_inv_of_pos hx, arctan_inv_of_pos hy, show _ + _ = π - (arctan x + arctan y) by ring, sub_eq_iff_eq_add, ← sub_eq_iff_eq_add', sub_eq_add_neg, ← arctan_neg, add_comm] at k convert k.symm using 3 diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean index c31a03b44e31f..ff16ee4d5471a 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Basic.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Benjamin Davidson -/ +import Mathlib.Algebra.QuadraticDiscriminant import Mathlib.Analysis.SpecialFunctions.Exp import Mathlib.Tactic.Positivity.Core import Mathlib.Algebra.Ring.NegOnePow @@ -517,7 +518,7 @@ theorem cos_eq_one_iff (x : ℝ) : cos x = 1 ↔ ∃ n : ℤ, (n : ℝ) * (2 * (Int.emod_two_eq_zero_or_one n).elim (fun hn0 => by rwa [← mul_assoc, ← @Int.cast_two ℝ, ← Int.cast_mul, - Int.ediv_mul_cancel ((Int.dvd_iff_emod_eq_zero _ _).2 hn0)]) + Int.ediv_mul_cancel (Int.dvd_iff_emod_eq_zero.2 hn0)]) fun hn1 => by rw [← Int.emod_add_ediv n 2, hn1, Int.cast_add, Int.cast_one, add_mul, one_mul, add_comm, mul_comm (2 : ℤ), Int.cast_mul, mul_assoc, Int.cast_two] at hn @@ -661,7 +662,7 @@ theorem sqrtTwoAddSeries_monotone_left {x y : ℝ} (h : x ≤ y) : theorem cos_pi_over_two_pow : ∀ n : ℕ, cos (π / 2 ^ (n + 1)) = sqrtTwoAddSeries 0 n / 2 | 0 => by simp | n + 1 => by - have A : (1 : ℝ) < 2 ^ (n + 1) := one_lt_pow one_lt_two n.succ_ne_zero + have A : (1 : ℝ) < 2 ^ (n + 1) := one_lt_pow₀ one_lt_two n.succ_ne_zero have B : π / 2 ^ (n + 1) < π := div_lt_self pi_pos A have C : 0 < π / 2 ^ (n + 1) := by positivity rw [pow_succ, div_mul_eq_div_div, cos_half, cos_pi_over_two_pow n, sqrtTwoAddSeries, @@ -690,7 +691,7 @@ theorem sin_pi_over_two_pow_succ (n : ℕ) : exact (sqrtTwoAddSeries_lt_two _).le refine mul_nonneg (sin_nonneg_of_nonneg_of_le_pi ?_ ?_) zero_le_two · positivity - · exact div_le_self pi_pos.le <| one_le_pow_of_one_le one_le_two _ + · exact div_le_self pi_pos.le <| one_le_pow₀ one_le_two @[simp] theorem cos_pi_div_four : cos (π / 4) = √2 / 2 := by @@ -795,6 +796,49 @@ theorem sin_pi_div_three : sin (π / 3) = √3 / 2 := by congr ring +theorem quadratic_root_cos_pi_div_five : + letI c := cos (π / 5) + 4 * c ^ 2 - 2 * c - 1 = 0 := by + set θ := π / 5 with hθ + set c := cos θ + set s := sin θ + suffices 2 * c = 4 * c ^ 2 - 1 by simp [this] + have hs : s ≠ 0 := by + rw [ne_eq, sin_eq_zero_iff, hθ] + push_neg + intro n hn + replace hn : n * 5 = 1 := by field_simp [mul_comm _ π, mul_assoc] at hn; norm_cast at hn + rcases Int.mul_eq_one_iff_eq_one_or_neg_one.mp hn with ⟨_, h⟩ | ⟨_, h⟩ <;> norm_num at h + suffices s * (2 * c) = s * (4 * c ^ 2 - 1) from mul_left_cancel₀ hs this + calc s * (2 * c) = 2 * s * c := by rw [← mul_assoc, mul_comm 2] + _ = sin (2 * θ) := by rw [sin_two_mul] + _ = sin (π - 2 * θ) := by rw [sin_pi_sub] + _ = sin (2 * θ + θ) := by congr; field_simp [hθ]; linarith + _ = sin (2 * θ) * c + cos (2 * θ) * s := sin_add (2 * θ) θ + _ = 2 * s * c * c + cos (2 * θ) * s := by rw [sin_two_mul] + _ = 2 * s * c * c + (2 * c ^ 2 - 1) * s := by rw [cos_two_mul] + _ = s * (2 * c * c) + s * (2 * c ^ 2 - 1) := by linarith + _ = s * (4 * c ^ 2 - 1) := by linarith + +open Polynomial in +theorem Polynomial.isRoot_cos_pi_div_five : + (4 • X ^ 2 - 2 • X - C 1 : ℝ[X]).IsRoot (cos (π / 5)) := by + simpa using quadratic_root_cos_pi_div_five + +/-- The cosine of `π / 5` is `(1 + √5) / 4`. -/ +@[simp] +theorem cos_pi_div_five : cos (π / 5) = (1 + √5) / 4 := by + set c := cos (π / 5) + have : 4 * (c * c) + (-2) * c + (-1) = 0 := by + rw [← sq, neg_mul, ← sub_eq_add_neg, ← sub_eq_add_neg] + exact quadratic_root_cos_pi_div_five + have hd : discrim 4 (-2) (-1) = (2 * √5) * (2 * √5) := by norm_num [discrim, mul_mul_mul_comm] + rcases (quadratic_eq_zero_iff (by norm_num) hd c).mp this with h | h + · field_simp [h]; linarith + · absurd (show 0 ≤ c from cos_nonneg_of_mem_Icc <| by constructor <;> linarith [pi_pos.le]) + rw [not_le, h] + exact div_neg_of_neg_of_pos (by norm_num [lt_sqrt]) (by positivity) + end CosDivSq /-- `Real.sin` as an `OrderIso` between `[-(π / 2), π / 2]` and `[-1, 1]`. -/ diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean index e0595d589e11d..f3a9858bddf37 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Bounds.lean @@ -173,11 +173,9 @@ theorem lt_tan {x : ℝ} (h1 : 0 < x) (h2 : x < π / 2) : x < tan x := by let U := Ico 0 (π / 2) have intU : interior U = Ioo 0 (π / 2) := interior_Ico have half_pi_pos : 0 < π / 2 := div_pos pi_pos two_pos - have cos_pos : ∀ {y : ℝ}, y ∈ U → 0 < cos y := by - intro y hy + have cos_pos {y : ℝ} (hy : y ∈ U) : 0 < cos y := by exact cos_pos_of_mem_Ioo (Ico_subset_Ioo_left (neg_lt_zero.mpr half_pi_pos) hy) - have sin_pos : ∀ {y : ℝ}, y ∈ interior U → 0 < sin y := by - intro y hy + have sin_pos {y : ℝ} (hy : y ∈ interior U) : 0 < sin y := by rw [intU] at hy exact sin_pos_of_mem_Ioo (Ioo_subset_Ioo_right (div_le_self pi_pos.le one_le_two) hy) have tan_cts_U : ContinuousOn tan U := by @@ -186,8 +184,7 @@ theorem lt_tan {x : ℝ} (h1 : 0 < x) (h2 : x < π / 2) : x < tan x := by simp only [mem_setOf_eq] exact (cos_pos hz).ne' have tan_minus_id_cts : ContinuousOn (fun y : ℝ => tan y - y) U := tan_cts_U.sub continuousOn_id - have deriv_pos : ∀ y : ℝ, y ∈ interior U → 0 < deriv (fun y' : ℝ => tan y' - y') y := by - intro y hy + have deriv_pos (y : ℝ) (hy : y ∈ interior U) : 0 < deriv (fun y' : ℝ => tan y' - y') y := by have := cos_pos (interior_subset hy) simp only [deriv_tan_sub_id y this.ne', one_div, gt_iff_lt, sub_pos] norm_cast @@ -195,7 +192,7 @@ theorem lt_tan {x : ℝ} (h1 : 0 < x) (h2 : x < π / 2) : x < tan x := by apply lt_of_le_of_ne y.cos_sq_le_one rw [cos_sq'] simpa only [Ne, sub_eq_self, sq_eq_zero_iff] using (sin_pos hy).ne' - rwa [lt_inv, inv_one] + rwa [lt_inv_comm₀, inv_one] · exact zero_lt_one simpa only [sq, mul_self_pos] using this.ne' have mono := strictMonoOn_of_deriv_pos (convex_Ico 0 (π / 2)) tan_minus_id_cts deriv_pos diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean index ece140bac4b05..34180b091bfb1 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Complex.lean @@ -172,7 +172,7 @@ theorem cos_eq_iff_quadratic {z w : ℂ} : theorem cos_surjective : Function.Surjective cos := by intro x - obtain ⟨w, w₀, hw⟩ : ∃ w ≠ 0, 1 * w * w + -2 * x * w + 1 = 0 := by + obtain ⟨w, w₀, hw⟩ : ∃ w ≠ 0, 1 * (w * w) + -2 * x * w + 1 = 0 := by rcases exists_quadratic_eq_zero one_ne_zero ⟨_, (cpow_nat_inv_pow _ two_ne_zero).symm.trans <| pow_two _⟩ with ⟨w, hw⟩ diff --git a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Deriv.lean b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Deriv.lean index e11d7973f3b2c..862ffd739dff4 100644 --- a/Mathlib/Analysis/SpecialFunctions/Trigonometric/Deriv.lean +++ b/Mathlib/Analysis/SpecialFunctions/Trigonometric/Deriv.lean @@ -45,8 +45,10 @@ theorem contDiff_sin {n} : ContDiff ℂ n sin := (((contDiff_neg.mul contDiff_const).cexp.sub (contDiff_id.mul contDiff_const).cexp).mul contDiff_const).div_const _ +@[fun_prop] theorem differentiable_sin : Differentiable ℂ sin := fun x => (hasDerivAt_sin x).differentiableAt +@[fun_prop] theorem differentiableAt_sin {x : ℂ} : DifferentiableAt ℂ sin x := differentiable_sin x @@ -70,8 +72,10 @@ theorem hasDerivAt_cos (x : ℂ) : HasDerivAt cos (-sin x) x := theorem contDiff_cos {n} : ContDiff ℂ n cos := ((contDiff_id.mul contDiff_const).cexp.add (contDiff_neg.mul contDiff_const).cexp).div_const _ +@[fun_prop] theorem differentiable_cos : Differentiable ℂ cos := fun x => (hasDerivAt_cos x).differentiableAt +@[fun_prop] theorem differentiableAt_cos {x : ℂ} : DifferentiableAt ℂ cos x := differentiable_cos x @@ -98,8 +102,10 @@ theorem hasDerivAt_sinh (x : ℂ) : HasDerivAt sinh (cosh x) x := theorem contDiff_sinh {n} : ContDiff ℂ n sinh := (contDiff_exp.sub contDiff_neg.cexp).div_const _ +@[fun_prop] theorem differentiable_sinh : Differentiable ℂ sinh := fun x => (hasDerivAt_sinh x).differentiableAt +@[fun_prop] theorem differentiableAt_sinh {x : ℂ} : DifferentiableAt ℂ sinh x := differentiable_sinh x @@ -123,8 +129,10 @@ theorem hasDerivAt_cosh (x : ℂ) : HasDerivAt cosh (sinh x) x := theorem contDiff_cosh {n} : ContDiff ℂ n cosh := (contDiff_exp.add contDiff_neg.cexp).div_const _ +@[fun_prop] theorem differentiable_cosh : Differentiable ℂ cosh := fun x => (hasDerivAt_cosh x).differentiableAt +@[fun_prop] theorem differentiableAt_cosh {x : ℂ} : DifferentiableAt ℂ cosh x := differentiable_cosh x @@ -482,8 +490,10 @@ theorem hasDerivAt_sin (x : ℝ) : HasDerivAt sin (cos x) x := theorem contDiff_sin {n} : ContDiff ℝ n sin := Complex.contDiff_sin.real_of_complex +@[fun_prop] theorem differentiable_sin : Differentiable ℝ sin := fun x => (hasDerivAt_sin x).differentiableAt +@[fun_prop] theorem differentiableAt_sin : DifferentiableAt ℝ sin x := differentiable_sin x @@ -500,8 +510,10 @@ theorem hasDerivAt_cos (x : ℝ) : HasDerivAt cos (-sin x) x := theorem contDiff_cos {n} : ContDiff ℝ n cos := Complex.contDiff_cos.real_of_complex +@[fun_prop] theorem differentiable_cos : Differentiable ℝ cos := fun x => (hasDerivAt_cos x).differentiableAt +@[fun_prop] theorem differentiableAt_cos : DifferentiableAt ℝ cos x := differentiable_cos x @@ -521,8 +533,10 @@ theorem hasDerivAt_sinh (x : ℝ) : HasDerivAt sinh (cosh x) x := theorem contDiff_sinh {n} : ContDiff ℝ n sinh := Complex.contDiff_sinh.real_of_complex +@[fun_prop] theorem differentiable_sinh : Differentiable ℝ sinh := fun x => (hasDerivAt_sinh x).differentiableAt +@[fun_prop] theorem differentiableAt_sinh : DifferentiableAt ℝ sinh x := differentiable_sinh x @@ -539,8 +553,10 @@ theorem hasDerivAt_cosh (x : ℝ) : HasDerivAt cosh (sinh x) x := theorem contDiff_cosh {n} : ContDiff ℝ n cosh := Complex.contDiff_cosh.real_of_complex +@[fun_prop] theorem differentiable_cosh : Differentiable ℝ cosh := fun x => (hasDerivAt_cosh x).differentiableAt +@[fun_prop] theorem differentiableAt_cosh : DifferentiableAt ℝ cosh x := differentiable_cosh x diff --git a/Mathlib/Analysis/SpecificLimits/Basic.lean b/Mathlib/Analysis/SpecificLimits/Basic.lean index 661e426e3784c..c0a2df7d23e61 100644 --- a/Mathlib/Analysis/SpecificLimits/Basic.lean +++ b/Mathlib/Analysis/SpecificLimits/Basic.lean @@ -119,7 +119,7 @@ theorem tendsto_natCast_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' (pow_right_mono₀ <| le_add_of_nonneg_left h.le) <| not_bddAbove_iff.2 fun _ ↦ Set.exists_range_iff.2 <| add_one_pow_unbounded_of_pos _ h theorem tendsto_pow_atTop_atTop_of_one_lt [LinearOrderedRing α] [Archimedean α] {r : α} @@ -137,7 +137,7 @@ theorem tendsto_pow_atTop_nhds_zero_of_lt_one {𝕜 : Type*} [LinearOrderedField (fun hr ↦ (tendsto_add_atTop_iff_nat 1).mp <| by simp [_root_.pow_succ, ← hr, tendsto_const_nhds]) (fun hr ↦ - have := one_lt_inv hr h₂ |> tendsto_pow_atTop_atTop_of_one_lt + have := (one_lt_inv₀ hr).2 h₂ |> tendsto_pow_atTop_atTop_of_one_lt (tendsto_inv_atTop_zero.comp this).congr fun n ↦ by simp) @[deprecated (since := "2024-01-31")] alias tendsto_pow_atTop_nhds_0_of_lt_1 := tendsto_pow_atTop_nhds_zero_of_lt_one @@ -252,7 +252,7 @@ protected theorem ENNReal.tendsto_pow_atTop_nhds_top_iff {r : ℝ≥0∞} : specialize h_tends (Ioi_mem_nhds one_lt_top) simp only [Filter.mem_map, mem_atTop_sets, ge_iff_le, Set.mem_preimage, Set.mem_Ioi] at h_tends obtain ⟨n, hn⟩ := h_tends - exact lt_irrefl _ <| lt_of_lt_of_le (hn n le_rfl) <| pow_le_one n (zero_le _) r_le_one + exact lt_irrefl _ <| lt_of_lt_of_le (hn n le_rfl) <| pow_le_one₀ (zero_le _) r_le_one · intro r_gt_one have obs := @Tendsto.inv ℝ≥0∞ ℕ _ _ _ (fun n ↦ (r⁻¹)^n) atTop 0 simp only [ENNReal.tendsto_pow_atTop_nhds_zero_iff, inv_zero] at obs @@ -360,7 +360,7 @@ theorem ENNReal.tsum_geometric (r : ℝ≥0∞) : ∑' n : ℕ, r ^ n = (1 - r) (ENNReal.exists_nat_gt (lt_top_iff_ne_top.1 ha)).imp fun n hn ↦ lt_of_lt_of_le hn ?_ calc (n : ℝ≥0∞) = ∑ i ∈ range n, 1 := by rw [sum_const, nsmul_one, card_range] - _ ≤ ∑ i ∈ range n, r ^ i := by gcongr; apply one_le_pow_of_one_le' hr + _ ≤ ∑ i ∈ range n, r ^ i := by gcongr; apply one_le_pow₀ hr theorem ENNReal.tsum_geometric_add_one (r : ℝ≥0∞) : ∑' n : ℕ, r ^ (n + 1) = r * (1 - r)⁻¹ := by simp only [_root_.pow_succ', ENNReal.tsum_mul_left, ENNReal.tsum_geometric] @@ -513,7 +513,7 @@ theorem summable_one_div_pow_of_le {m : ℝ} {f : ℕ → ℕ} (hm : 1 < m) (fi (summable_geometric_of_lt_one (one_div_nonneg.mpr (zero_le_one.trans hm.le)) ((one_div_lt (zero_lt_one.trans hm) zero_lt_one).mpr (one_div_one.le.trans_lt hm))) rw [div_pow, one_pow] - refine (one_div_le_one_div ?_ ?_).mpr (pow_le_pow_right hm.le (fi a)) <;> + refine (one_div_le_one_div ?_ ?_).mpr (pow_right_mono₀ hm.le (fi a)) <;> exact pow_pos (zero_lt_one.trans hm) _ /-! ### Positive sequences with small sums on countable types -/ diff --git a/Mathlib/Analysis/SpecificLimits/FloorPow.lean b/Mathlib/Analysis/SpecificLimits/FloorPow.lean index fe6f17c4e3162..0d410a3b11645 100644 --- a/Mathlib/Analysis/SpecificLimits/FloorPow.lean +++ b/Mathlib/Analysis/SpecificLimits/FloorPow.lean @@ -195,8 +195,7 @@ theorem tendsto_div_of_monotone_of_tendsto_div_floor_pow (u : ℕ → ℝ) (l : have H : ∀ n : ℕ, (0 : ℝ) < ⌊c k ^ n⌋₊ := by intro n refine zero_lt_one.trans_le ?_ - simp only [Real.rpow_natCast, Nat.one_le_cast, Nat.one_le_floor_iff, - one_le_pow_of_one_le (cone k).le n] + simp only [Real.rpow_natCast, Nat.one_le_cast, Nat.one_le_floor_iff, one_le_pow₀ (cone k).le] have A : Tendsto (fun n : ℕ => (⌊c k ^ (n + 1)⌋₊ : ℝ) / c k ^ (n + 1) * c k / (⌊c k ^ n⌋₊ / c k ^ n)) atTop (𝓝 (1 * c k / 1)) := by @@ -223,12 +222,12 @@ theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc have B : c ^ 2 * ((1 : ℝ) - c⁻¹ ^ 2)⁻¹ ≤ c ^ 3 * (c - 1)⁻¹ := by rw [← div_eq_mul_inv, ← div_eq_mul_inv, div_le_div_iff _ (sub_pos.2 hc)] swap - · exact sub_pos.2 (pow_lt_one (inv_nonneg.2 cpos.le) (inv_lt_one hc) two_ne_zero) + · exact sub_pos.2 (pow_lt_one₀ (inv_nonneg.2 cpos.le) (inv_lt_one_of_one_lt₀ hc) two_ne_zero) have : c ^ 3 = c ^ 2 * c := by ring 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 + simpa using pow_right_mono₀ hc.le one_le_two + have C : c⁻¹ ^ 2 < 1 := pow_lt_one₀ (inv_nonneg.2 cpos.le) (inv_lt_one_of_one_lt₀ hc) two_ne_zero calc (∑ i ∈ (range N).filter (j < c ^ ·), (1 : ℝ) / (c ^ i) ^ 2) ≤ ∑ i ∈ Ico ⌊Real.log j / Real.log c⌋₊ N, (1 : ℝ) / (c ^ i) ^ 2 := by @@ -237,7 +236,7 @@ theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc simp only [hi.1, mem_Ico, and_true] apply Nat.floor_le_of_le apply le_of_lt - rw [div_lt_iff (Real.log_pos hc), ← Real.log_pow] + rw [div_lt_iff₀ (Real.log_pos hc), ← Real.log_pow] exact Real.log_lt_log hj hi.2 _ = ∑ i ∈ Ico ⌊Real.log j / Real.log c⌋₊ N, (c⁻¹ ^ 2) ^ i := by congr 1 with i @@ -258,7 +257,7 @@ theorem sum_div_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : ℝ} (hc 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' + 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 gcongr @@ -271,7 +270,7 @@ theorem mul_pow_le_nat_floor_pow {c : ℝ} (hc : 1 < c) (i : ℕ) : (1 - c⁻¹) (1 - c⁻¹) * c ^ i = c ^ i - c ^ i * c⁻¹ := by ring _ ≤ c ^ i - 1 := by gcongr - simpa only [← div_eq_mul_inv, one_le_div cpos, pow_one] using le_self_pow hc.le hi + 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 /-- The sum of `1/⌊c^i⌋₊^2` above a threshold `j` is comparable to `1/j^2`, up to a multiplicative @@ -280,7 +279,7 @@ theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : (∑ i ∈ (range N).filter (j < ⌊c ^ ·⌋₊), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2) ≤ c ^ 5 * (c - 1)⁻¹ ^ 3 / j ^ 2 := by have cpos : 0 < c := zero_lt_one.trans hc - have A : 0 < 1 - c⁻¹ := sub_pos.2 (inv_lt_one hc) + have A : 0 < 1 - c⁻¹ := sub_pos.2 (inv_lt_one_of_one_lt₀ hc) calc (∑ i ∈ (range N).filter (j < ⌊c ^ ·⌋₊), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2) ≤ ∑ i ∈ (range N).filter (j < c ^ ·), (1 : ℝ) / (⌊c ^ i⌋₊ : ℝ) ^ 2 := by @@ -292,7 +291,7 @@ theorem sum_div_nat_floor_pow_sq_le_div_sq (N : ℕ) {j : ℝ} (hj : 0 < j) {c : rw [mul_div_assoc', mul_one, div_le_div_iff]; rotate_left · apply sq_pos_of_pos refine zero_lt_one.trans_le ?_ - simp only [Nat.le_floor, one_le_pow_of_one_le, hc.le, Nat.one_le_cast, Nat.cast_one] + simp only [Nat.le_floor, one_le_pow₀, hc.le, Nat.one_le_cast, Nat.cast_one] · exact sq_pos_of_pos (pow_pos cpos _) rw [one_mul, ← mul_pow] gcongr diff --git a/Mathlib/Analysis/SpecificLimits/Normed.lean b/Mathlib/Analysis/SpecificLimits/Normed.lean index a84b941a538ea..ba7281ba264e2 100644 --- a/Mathlib/Analysis/SpecificLimits/Normed.lean +++ b/Mathlib/Analysis/SpecificLimits/Normed.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker, Sébastien Gouëzel, Yury Kudryashov, Dylan MacKenzie, Patrick Massot -/ import Mathlib.Algebra.BigOperators.Module -import Mathlib.Algebra.Order.Field.Basic +import Mathlib.Algebra.Order.Field.Power import Mathlib.Analysis.Asymptotics.Asymptotics import Mathlib.Analysis.Normed.Field.InfiniteSum import Mathlib.Analysis.Normed.Module.Basic @@ -210,7 +210,7 @@ theorem tendsto_pow_const_mul_const_pow_of_abs_lt_one (k : ℕ) {r : ℝ} (hr : by_cases h0 : r = 0 · exact tendsto_const_nhds.congr' (mem_atTop_sets.2 ⟨1, fun n hn ↦ by simp [zero_lt_one.trans_le hn |>.ne', h0]⟩) - have hr' : 1 < |r|⁻¹ := one_lt_inv (abs_pos.2 h0) hr + have hr' : 1 < |r|⁻¹ := (one_lt_inv₀ (abs_pos.2 h0)).2 hr rw [tendsto_zero_iff_norm_tendsto_zero] simpa [div_eq_mul_inv] using tendsto_pow_const_div_const_pow_of_one_lt k hr' @@ -252,7 +252,7 @@ alias tendsto_pow_atTop_nhds_0_of_abs_lt_1 := tendsto_pow_atTop_nhds_zero_of_abs /-- A normed ring has summable geometric series if, for all `ξ` of norm `< 1`, the geometric series `∑ ξ ^ n` converges. This holds both in complete normed rings and in normed fields, providing a convenient abstraction of these two classes to avoid repeating the same proofs. -/ -class HasSummableGeomSeries (K : Type*) [NormedRing K] : Prop := +class HasSummableGeomSeries (K : Type*) [NormedRing K] : Prop where summable_geometric_of_norm_lt_one : ∀ (ξ : K), ‖ξ‖ < 1 → Summable (fun n ↦ ξ ^ n) lemma summable_geometric_of_norm_lt_one {K : Type*} [NormedRing K] [HasSummableGeomSeries K] @@ -908,6 +908,8 @@ theorem Real.summable_pow_div_factorial (x : ℝ) : Summable (fun n ↦ x ^ n / norm_div, Real.norm_natCast, Nat.cast_succ] _ ≤ ‖x‖ / (⌊‖x‖⌋₊ + 1) * ‖x ^ n / (n !)‖ := by gcongr +@[deprecated "`Real.tendsto_pow_div_factorial_atTop` has been deprecated, use +`FloorSemiring.tendsto_pow_div_factorial_atTop` instead" (since := "2024-10-05")] theorem Real.tendsto_pow_div_factorial_atTop (x : ℝ) : Tendsto (fun n ↦ x ^ n / n ! : ℕ → ℝ) atTop (𝓝 0) := (Real.summable_pow_div_factorial x).tendsto_atTop_zero diff --git a/Mathlib/CategoryTheory/Abelian/Opposite.lean b/Mathlib/CategoryTheory/Abelian/Opposite.lean index e862e8a81c331..d0af389e041d3 100644 --- a/Mathlib/CategoryTheory/Abelian/Opposite.lean +++ b/Mathlib/CategoryTheory/Abelian/Opposite.lean @@ -151,7 +151,7 @@ theorem image_ι_op_comp_imageUnopOp_hom : Quiver.Hom.op_unop, cokernelIsoOfEq_hom_comp_desc_assoc, cokernel.π_desc_assoc, cokernel.π_desc] simp only [eqToHom_refl] - erw [IsIso.inv_id, Category.id_comp] + rw [IsIso.inv_id, Category.id_comp] theorem imageUnopOp_hom_comp_image_ι : (imageUnopOp g).hom ≫ image.ι g = (factorThruImage g.unop).op := by diff --git a/Mathlib/CategoryTheory/Adhesive.lean b/Mathlib/CategoryTheory/Adhesive.lean index 159adb085741e..51235c1937b60 100644 --- a/Mathlib/CategoryTheory/Adhesive.lean +++ b/Mathlib/CategoryTheory/Adhesive.lean @@ -133,7 +133,7 @@ theorem is_coprod_iff_isPushout {X E Y YE : C} (c : BinaryCofan X E) (hc : IsCol · intro s m e₁ e₂ apply PushoutCocone.IsColimit.hom_ext H.isColimit · symm; exact (H.isColimit.fac _ WalkingSpan.left).trans e₂.symm - · erw [H.isColimit.fac _ WalkingSpan.right] + · rw [H.isColimit.fac _ WalkingSpan.right] apply BinaryCofan.IsColimit.hom_ext hc · erw [hc.fac, ← H.w_assoc, e₂]; rfl · refine ((Category.assoc _ _ _).symm.trans e₁).trans ?_; symm; exact hc.fac _ _ diff --git a/Mathlib/CategoryTheory/Adjunction/Basic.lean b/Mathlib/CategoryTheory/Adjunction/Basic.lean index f0a274f9be2a4..3d9c1506b6275 100644 --- a/Mathlib/CategoryTheory/Adjunction/Basic.lean +++ b/Mathlib/CategoryTheory/Adjunction/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Reid Barton, Johan Commelin, Bhavik Mehta -/ import Mathlib.CategoryTheory.Equivalence +import Mathlib.CategoryTheory.Yoneda /-! # Adjunctions between functors @@ -13,7 +14,9 @@ import Mathlib.CategoryTheory.Equivalence We provide various useful constructors: * `mkOfHomEquiv` -* `mkOfUnitCounit` +* `mk'`: construct an adjunction from the data of a hom set equivalence, unit and counit natural + transformations together with proofs of the equalities `homEquiv_unit` and `homEquiv_counit` + relating them to each other. * `leftAdjointOfEquiv` / `rightAdjointOfEquiv` construct a left/right adjoint of a given functor given the action on objects and the relevant equivalence of morphism spaces. @@ -29,6 +32,44 @@ adjoint can be obtained as `F.rightAdjoint`. `toEquivalence` upgrades an adjunction to an equivalence, given witnesses that the unit and counit are pointwise isomorphisms. Conversely `Equivalence.toAdjunction` recovers the underlying adjunction from an equivalence. + +## Overview of the directory `CategoryTheory.Adjunction` + +* Adjoint lifting theorems are in the directory `Lifting`. +* The file `AdjointFunctorTheorems` proves the adjoint functor theorems. +* The file `Comma` shows that for a functor `G : D ⥤ C` the data of an initial object in each + `StructuredArrow` category on `G` is equivalent to a left adjoint to `G`, as well as the dual. +* The file `Evaluation` shows that products and coproducts are adjoint to evaluation of functors. +* The file `FullyFaithful` characterizes when adjoints are full or faithful in terms of the unit + and counit. +* The file `Limits` proves that left adjoints preserve colimits and right adjoints preserve limits. +* The file `Mates` establishes the bijection between the 2-cells + ``` + L₁ R₁ + C --→ D C ←-- D + G ↓ ↗ ↓ H G ↓ ↘ ↓ H + E --→ F E ←-- F + L₂ R₂ + ``` + where `L₁ ⊣ R₁` and `L₂ ⊣ R₂`. Specializing to a pair of adjoints `L₁ L₂ : C ⥤ D`, + `R₁ R₂ : D ⥤ C`, it provides equivalences `(L₂ ⟶ L₁) ≃ (R₁ ⟶ R₂)` and `(L₂ ≅ L₁) ≃ (R₁ ≅ R₂)`. +* The file `Opposites` contains constructions to relate adjunctions of functors to adjunctions of + their opposites. +* The file `Reflective` defines reflective functors, i.e. fully faithful right adjoints. Note that + many facts about reflective functors are proved in the earlier file `FullyFaithful`. +* The file `Restrict` defines the restriction of an adjunction along fully faithful functors. +* The file `Triple` proves that in an adjoint triple, the left adjoint is fully faithful if and + only if the right adjoint is. +* The file `Unique` proves uniqueness of adjoints. +* The file `Whiskering` proves that functors `F : D ⥤ E` and `G : E ⥤ D` with an adjunction + `F ⊣ G`, induce adjunctions between the functor categories `C ⥤ D` and `C ⥤ E`, + and the functor categories `E ⥤ C` and `D ⥤ C`. + +## Other files related to adjunctions + +* The file `CategoryTheory.Monad.Adjunction` develops the basic relationship between adjunctions + and (co)monads. There it is also shown that given an adjunction `L ⊣ R` and an isomorphism + `L ⋙ R ≅ 𝟭 C`, the unit is an isomorphism, and similarly for the counit. -/ @@ -58,8 +99,6 @@ hom set equivalence. To construct adjoints to a given functor, there are constructors `leftAdjointOfEquiv` and `adjunctionOfEquivLeft` (as well as their duals). -Uniqueness of adjoints is shown in `CategoryTheory.Adjunction.Unique`. - See . -/ structure Adjunction (F : C ⥤ D) (G : D ⥤ C) where @@ -419,6 +458,22 @@ def ofNatIsoRight {F : C ⥤ D} {G H : D ⥤ C} (adj : F ⊣ G) (iso : G ≅ H) Adjunction.mkOfHomEquiv { homEquiv := fun X Y => (adj.homEquiv X Y).trans (equivHomsetRightOfNatIso iso) } +/-- The isomorpism which an adjunction `F ⊣ G` induces on `G ⋙ yoneda`. This states that +`Adjunction.homEquiv` is natural in both arguments. -/ +@[simps!] +def compYonedaIso {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₁} D] + {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) : + G ⋙ yoneda ≅ yoneda ⋙ (whiskeringLeft _ _ _).obj F.op := + NatIso.ofComponents fun X => NatIso.ofComponents fun Y => (adj.homEquiv Y.unop X).toIso.symm + +/-- The isomorpism which an adjunction `F ⊣ G` induces on `F.op ⋙ coyoneda`. This states that +`Adjunction.homEquiv` is natural in both arguments. -/ +@[simps!] +def compCoyonedaIso {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₁} D] + {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) : + F.op ⋙ coyoneda ≅ coyoneda ⋙ (whiskeringLeft _ _ _).obj G := + NatIso.ofComponents fun X => NatIso.ofComponents fun Y => (adj.homEquiv X.unop Y).toIso + section variable {E : Type u₃} [ℰ : Category.{v₃} E] {H : D ⥤ E} {I : E ⥤ D} diff --git a/Mathlib/CategoryTheory/Adjunction/Mates.lean b/Mathlib/CategoryTheory/Adjunction/Mates.lean index 1353ea9022b78..ca344b3aa3796 100644 --- a/Mathlib/CategoryTheory/Adjunction/Mates.lean +++ b/Mathlib/CategoryTheory/Adjunction/Mates.lean @@ -13,11 +13,13 @@ import Mathlib.Tactic.ApplyFun This file establishes the bijection between the 2-cells +``` L₁ R₁ C --→ D C ←-- D G ↓ ↗ ↓ H G ↓ ↘ ↓ H E --→ F E ←-- F L₂ R₂ +``` where `L₁ ⊣ R₁` and `L₂ ⊣ R₂`. The corresponding natural transformations are called mates. @@ -328,6 +330,7 @@ Furthermore, this bijection preserves (and reflects) isomorphisms, i.e. a transf iff its image under the bijection is an iso, see eg `CategoryTheory.conjugateIsoEquiv`. This is in contrast to the general case `mateEquiv` which does not in general have this property. -/ +@[simps!] def conjugateEquiv : (L₂ ⟶ L₁) ≃ (R₁ ⟶ R₂) := calc (L₂ ⟶ L₁) ≃ _ := (Iso.homCongr L₂.leftUnitor L₁.rightUnitor).symm @@ -401,6 +404,7 @@ variable [Category.{v₁} C] [Category.{v₂} D] variable {L₁ L₂ L₃ : C ⥤ D} {R₁ R₂ R₃ : D ⥤ C} variable (adj₁ : L₁ ⊣ R₁) (adj₂ : L₂ ⊣ R₂) (adj₃ : L₃ ⊣ R₃) +@[simp] theorem conjugateEquiv_comp (α : L₂ ⟶ L₁) (β : L₃ ⟶ L₂) : conjugateEquiv adj₁ adj₂ α ≫ conjugateEquiv adj₂ adj₃ β = conjugateEquiv adj₁ adj₃ (β ≫ α) := by @@ -414,6 +418,7 @@ theorem conjugateEquiv_comp (α : L₂ ⟶ L₁) (β : L₃ ⟶ L₂) : simp only [comp_id, id_comp, assoc, map_comp] at vcompd ⊢ rw [vcompd] +@[simp] theorem conjugateEquiv_symm_comp (α : R₁ ⟶ R₂) (β : R₂ ⟶ R₃) : (conjugateEquiv adj₂ adj₃).symm β ≫ (conjugateEquiv adj₁ adj₂).symm α = (conjugateEquiv adj₁ adj₃).symm (α ≫ β) := by @@ -473,9 +478,16 @@ theorem conjugateEquiv_symm_of_iso (α : R₁ ⟶ R₂) infer_instance /-- Thus conjugation defines an equivalence between natural isomorphisms. -/ -noncomputable def conjugateIsoEquiv : (L₂ ≅ L₁) ≃ (R₁ ≅ R₂) where - toFun α := asIso (conjugateEquiv adj₁ adj₂ α.hom) - invFun β := asIso ((conjugateEquiv adj₁ adj₂).symm β.hom) +@[simps] +def conjugateIsoEquiv : (L₂ ≅ L₁) ≃ (R₁ ≅ R₂) where + toFun α := { + hom := conjugateEquiv adj₁ adj₂ α.hom + inv := conjugateEquiv adj₂ adj₁ α.inv + } + invFun β := { + hom := (conjugateEquiv adj₁ adj₂).symm β.hom + inv := (conjugateEquiv adj₂ adj₁).symm β.inv + } left_inv := by aesop_cat right_inv := by aesop_cat diff --git a/Mathlib/CategoryTheory/Adjunction/Unique.lean b/Mathlib/CategoryTheory/Adjunction/Unique.lean index e911b3e4dcb59..9c4b07886fc7d 100644 --- a/Mathlib/CategoryTheory/Adjunction/Unique.lean +++ b/Mathlib/CategoryTheory/Adjunction/Unique.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bhavik Mehta, Thomas Read, Andrew Yang, Dagur Asgeirsson, Joël Riou -/ -import Mathlib.CategoryTheory.Adjunction.Basic +import Mathlib.CategoryTheory.Adjunction.Mates /-! # Uniqueness of adjoints @@ -11,9 +11,6 @@ import Mathlib.CategoryTheory.Adjunction.Basic This file shows that adjoints are unique up to natural isomorphism. ## Main results -* `Adjunction.natTransEquiv` and `Adjunction.natIsoEquiv` If `F ⊣ G` and `F' ⊣ G'` are adjunctions, - then there are equivalences `(G ⟶ G') ≃ (F' ⟶ F)` and `(G ≅ G') ≃ (F' ≅ F)`. -Everything else is deduced from this: * `Adjunction.leftAdjointUniq` : If `F` and `F'` are both left adjoint to `G`, then they are naturally isomorphic. @@ -21,12 +18,6 @@ Everything else is deduced from this: * `Adjunction.rightAdjointUniq` : If `G` and `G'` are both right adjoint to `F`, then they are naturally isomorphic. -## TODO - -There some overlap with the file `Adjunction.Mates`. In particular, `natTransEquiv` is just a -special case of `mateEquiv`. However, before removing `natTransEquiv`, in favour of `mateEquiv`, -the latter needs some more API lemmas such as `natTransEquiv_apply_app`, `natTransEquiv_id`, etc. -in order to make automation work better in the rest of this file. -/ open CategoryTheory @@ -35,89 +26,9 @@ variable {C D : Type*} [Category C] [Category D] namespace CategoryTheory.Adjunction -/-- -If `F ⊣ G` and `F' ⊣ G'` are adjunctions, then giving a natural transformation `G ⟶ G'` is the -same as giving a natural transformation `F' ⟶ F`. --/ -@[simps] -def natTransEquiv {F F' : C ⥤ D} {G G' : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F' ⊣ G') : - (G ⟶ G') ≃ (F' ⟶ F) where - toFun f := { - app := fun X ↦ F'.map ((adj1.unit ≫ whiskerLeft F f).app X) ≫ adj2.counit.app _ - naturality := by - intro X Y g - simp only [← Category.assoc, ← Functor.map_comp] - erw [(adj1.unit ≫ (whiskerLeft F f)).naturality] - simp - } - invFun f := { - app := fun X ↦ adj2.unit.app (G.obj X) ≫ G'.map (f.app (G.obj X) ≫ adj1.counit.app X) - naturality := by - intro X Y g - erw [← adj2.unit_naturality_assoc] - simp only [← Functor.map_comp] - simp - } - left_inv f := by - ext X - simp only [Functor.comp_obj, NatTrans.comp_app, Functor.id_obj, whiskerLeft_app, - Functor.map_comp, Category.assoc, unit_naturality_assoc, right_triangle_components_assoc] - erw [← f.naturality (adj1.counit.app X), ← Category.assoc] - simp - right_inv f := by - ext - simp - -@[simp] -lemma natTransEquiv_id {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) : - natTransEquiv adj adj (𝟙 _) = 𝟙 _ := by ext; simp - -@[simp] -lemma natTransEquiv_id_symm {F : C ⥤ D} {G : D ⥤ C} (adj : F ⊣ G) : - (natTransEquiv adj adj).symm (𝟙 _) = 𝟙 _ := by ext; simp - -@[simp] -lemma natTransEquiv_comp {F F' F'' : C ⥤ D} {G G' G'' : D ⥤ C} - (adj1 : F ⊣ G) (adj2 : F' ⊣ G') (adj3 : F'' ⊣ G'') (f : G ⟶ G') (g : G' ⟶ G'') : - natTransEquiv adj2 adj3 g ≫ natTransEquiv adj1 adj2 f = natTransEquiv adj1 adj3 (f ≫ g) := by - apply (natTransEquiv adj1 adj3).symm.injective - ext X - simp only [natTransEquiv_symm_apply_app, Functor.comp_obj, NatTrans.comp_app, - natTransEquiv_apply_app, Functor.id_obj, whiskerLeft_app, Functor.map_comp, Category.assoc, - unit_naturality_assoc, right_triangle_components_assoc, Equiv.symm_apply_apply, - ← g.naturality_assoc, ← g.naturality] - simp only [← Category.assoc, unit_naturality, Functor.comp_obj, right_triangle_components, - Category.comp_id, ← f.naturality, Category.id_comp] - -@[simp] -lemma natTransEquiv_comp_symm {F F' F'' : C ⥤ D} {G G' G'' : D ⥤ C} - (adj1 : F ⊣ G) (adj2 : F' ⊣ G') (adj3 : F'' ⊣ G'') (f : F' ⟶ F) (g : F'' ⟶ F') : - (natTransEquiv adj1 adj2).symm f ≫ (natTransEquiv adj2 adj3).symm g = - (natTransEquiv adj1 adj3).symm (g ≫ f) := by - apply (natTransEquiv adj1 adj3).injective - ext - simp - -/-- -If `F ⊣ G` and `F' ⊣ G'` are adjunctions, then giving a natural isomorphism `G ≅ G'` is the -same as giving a natural transformation `F' ≅ F`. --/ -@[simps] -def natIsoEquiv {F F' : C ⥤ D} {G G' : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F' ⊣ G') : - (G ≅ G') ≃ (F' ≅ F) where - toFun i := { - hom := natTransEquiv adj1 adj2 i.hom - inv := natTransEquiv adj2 adj1 i.inv - } - invFun i := { - hom := (natTransEquiv adj1 adj2).symm i.hom - inv := (natTransEquiv adj2 adj1).symm i.inv } - left_inv i := by simp - right_inv i := by simp - /-- If `F` and `F'` are both left adjoint to `G`, then they are naturally isomorphic. -/ def leftAdjointUniq {F F' : C ⥤ D} {G : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F' ⊣ G) : F ≅ F' := - (natIsoEquiv adj1 adj2 (Iso.refl _)).symm + ((conjugateIsoEquiv adj1 adj2).symm (Iso.refl G)).symm -- Porting note (#10618): removed simp as simp can prove this theorem homEquiv_leftAdjointUniq_hom_app {F F' : C ⥤ D} {G : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F' ⊣ G) @@ -141,9 +52,10 @@ theorem unit_leftAdjointUniq_hom_app theorem leftAdjointUniq_hom_counit {F F' : C ⥤ D} {G : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F' ⊣ G) : whiskerLeft G (leftAdjointUniq adj1 adj2).hom ≫ adj2.counit = adj1.counit := by ext x - simp only [Functor.comp_obj, Functor.id_obj, leftAdjointUniq, Iso.symm_hom, natIsoEquiv_apply_inv, - Iso.refl_inv, NatTrans.comp_app, whiskerLeft_app, natTransEquiv_apply_app, whiskerLeft_id', - Category.comp_id, Category.assoc] + simp only [Functor.comp_obj, Functor.id_obj, leftAdjointUniq, Iso.symm_hom, + conjugateIsoEquiv_symm_apply_inv, Iso.refl_inv, NatTrans.comp_app, whiskerLeft_app, + conjugateEquiv_symm_apply_app, NatTrans.id_app, Functor.map_id, Category.id_comp, + Category.assoc] rw [← adj1.counit_naturality, ← Category.assoc, ← F.map_comp] simp @@ -180,7 +92,7 @@ theorem leftAdjointUniq_refl {F : C ⥤ D} {G : D ⥤ C} (adj1 : F ⊣ G) : /-- If `G` and `G'` are both right adjoint to `F`, then they are naturally isomorphic. -/ def rightAdjointUniq {F : C ⥤ D} {G G' : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F ⊣ G') : G ≅ G' := - (natIsoEquiv adj1 adj2).symm (Iso.refl _) + conjugateIsoEquiv adj1 adj2 (Iso.refl _) -- Porting note (#10618): simp can prove this theorem homEquiv_symm_rightAdjointUniq_hom_app {F : C ⥤ D} {G G' : D ⥤ C} (adj1 : F ⊣ G) @@ -192,8 +104,8 @@ theorem homEquiv_symm_rightAdjointUniq_hom_app {F : C ⥤ D} {G G' : D ⥤ C} (a theorem unit_rightAdjointUniq_hom_app {F : C ⥤ D} {G G' : D ⥤ C} (adj1 : F ⊣ G) (adj2 : F ⊣ G') (x : C) : adj1.unit.app x ≫ (rightAdjointUniq adj1 adj2).hom.app (F.obj x) = adj2.unit.app x := by - simp only [Functor.id_obj, Functor.comp_obj, rightAdjointUniq, natIsoEquiv_symm_apply_hom, - Iso.refl_hom, natTransEquiv_symm_apply_app, NatTrans.id_app, Category.id_comp] + simp only [Functor.id_obj, Functor.comp_obj, rightAdjointUniq, conjugateIsoEquiv_apply_hom, + Iso.refl_hom, conjugateEquiv_apply_app, NatTrans.id_app, Functor.map_id, Category.id_comp] rw [← adj2.unit_naturality_assoc, ← G'.map_comp] simp @@ -243,4 +155,7 @@ theorem rightAdjointUniq_refl {F : C ⥤ D} {G : D ⥤ C} (adj1 : F ⊣ G) : end Adjunction +@[deprecated (since := "2024-10-07")] alias Adjunction.natTransEquiv := conjugateEquiv +@[deprecated (since := "2024-10-07")] alias Adjunction.natIsoEquiv := conjugateIsoEquiv + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Bicategory/Functor/Prelax.lean b/Mathlib/CategoryTheory/Bicategory/Functor/Prelax.lean index 5cace28c07436..f7bb524702e5c 100644 --- a/Mathlib/CategoryTheory/Bicategory/Functor/Prelax.lean +++ b/Mathlib/CategoryTheory/Bicategory/Functor/Prelax.lean @@ -76,8 +76,6 @@ def mkOfHomPrefunctors (F : B → C) (F' : (a : B) → (b : B) → Prefunctor (a map {a b} := (F' a b).obj map₂ {a b} := (F' a b).map -variable (F : PrelaxFunctorStruct B C) - -- Porting note: deleted syntactic tautologies `toPrefunctor_eq_coe : F.toPrefunctor = F` -- and `to_prefunctor_obj : (F : Prefunctor B C).obj = F.obj` -- and `to_prefunctor_map` diff --git a/Mathlib/CategoryTheory/Category/Bipointed.lean b/Mathlib/CategoryTheory/Category/Bipointed.lean index d6bd45ad2304f..e85c5549e371d 100644 --- a/Mathlib/CategoryTheory/Category/Bipointed.lean +++ b/Mathlib/CategoryTheory/Category/Bipointed.lean @@ -20,9 +20,6 @@ open CategoryTheory universe u -variable {α β : Type*} - - /-- The category of bipointed types. -/ structure Bipointed : Type (u + 1) where /-- The underlying type of a bipointed type. -/ diff --git a/Mathlib/CategoryTheory/Category/Cat.lean b/Mathlib/CategoryTheory/Category/Cat.lean index 3d4788b016f0d..9838804baf16f 100644 --- a/Mathlib/CategoryTheory/Category/Cat.lean +++ b/Mathlib/CategoryTheory/Category/Cat.lean @@ -133,6 +133,14 @@ lemma associator_inv_app {B C D E : Cat} (F : B ⟶ C) (G : C ⟶ D) (H : D ⟶ (α_ F G H).inv.app X = eqToHom (by simp) := rfl +/-- The identity in the category of categories equals the identity functor.-/ +theorem id_eq_id (X : Cat) : 𝟙 X = 𝟭 X := rfl + +/-- Composition in the category of categories equals functor composition.-/ +theorem comp_eq_comp {X Y Z : Cat} (F : X ⟶ Y) (G : Y ⟶ Z) : F ≫ G = F ⋙ G := rfl + +@[simp] theorem of_α (C) [Category C] : (of C).α = C := rfl + /-- Functor that gets the set of objects of a category. It is not called `forget`, because it is not a faithful functor. -/ def objects : Cat.{v, u} ⥤ Type u where diff --git a/Mathlib/CategoryTheory/Category/PartialFun.lean b/Mathlib/CategoryTheory/Category/PartialFun.lean index 0ed2b108fb523..b448e2cf2a62f 100644 --- a/Mathlib/CategoryTheory/Category/PartialFun.lean +++ b/Mathlib/CategoryTheory/Category/PartialFun.lean @@ -30,8 +30,6 @@ open CategoryTheory Option universe u -variable {α β : Type*} - /-- The category of types equipped with partial functions. -/ def PartialFun : Type _ := Type* diff --git a/Mathlib/CategoryTheory/Category/Pointed.lean b/Mathlib/CategoryTheory/Category/Pointed.lean index a1f720281f992..8e963c0fc6da9 100644 --- a/Mathlib/CategoryTheory/Category/Pointed.lean +++ b/Mathlib/CategoryTheory/Category/Pointed.lean @@ -22,8 +22,6 @@ open CategoryTheory universe u -variable {α β : Type*} - /-- The category of pointed types. -/ structure Pointed : Type (u + 1) where /-- the underlying type -/ diff --git a/Mathlib/CategoryTheory/Category/Quiv.lean b/Mathlib/CategoryTheory/Category/Quiv.lean index bdb427995bad6..be83ad9b038c2 100644 --- a/Mathlib/CategoryTheory/Category/Quiv.lean +++ b/Mathlib/CategoryTheory/Category/Quiv.lean @@ -11,10 +11,8 @@ import Mathlib.CategoryTheory.PathCategory # The category of quivers The category of (bundled) quivers, and the free/forgetful adjunction between `Cat` and `Quiv`. - -/ - universe v u namespace CategoryTheory @@ -51,6 +49,12 @@ def forget : Cat.{v, u} ⥤ Quiv.{v, u} where obj C := Quiv.of C map F := F.toPrefunctor +/-- The identity in the category of quivers equals the identity prefunctor.-/ +theorem id_eq_id (X : Quiv) : 𝟙 X = 𝟭q X := rfl + +/-- Composition in the category of quivers equals prefunctor composition.-/ +theorem comp_eq_comp {X Y Z : Quiv} (F : X ⟶ Y) (G : Y ⟶ Z) : F ≫ G = F ⋙q G := rfl + end Quiv namespace Cat @@ -65,14 +69,14 @@ def free : Quiv.{v, u} ⥤ Cat.{max u v, u} where map_comp := fun f g => F.mapPath_comp f g } map_id V := by change (show Paths V ⥤ _ from _) = _ - ext; swap - · apply eq_conj_eqToHom + ext · rfl + · exact eq_conj_eqToHom _ map_comp {U _ _} F G := by change (show Paths U ⥤ _ from _) = _ - ext; swap - · apply eq_conj_eqToHom + ext · rfl + · exact eq_conj_eqToHom _ end Cat @@ -105,9 +109,9 @@ def adj : Cat.free ⊣ Quiv.forget := exact Category.id_comp _ } homEquiv_naturality_left_symm := fun {V _ _} f g => by change (show Paths V ⥤ _ from _) = _ - ext; swap - · apply eq_conj_eqToHom - · rfl } + ext + · rfl + · apply eq_conj_eqToHom } end Quiv diff --git a/Mathlib/CategoryTheory/Category/ReflQuiv.lean b/Mathlib/CategoryTheory/Category/ReflQuiv.lean new file mode 100644 index 0000000000000..f26afec53930b --- /dev/null +++ b/Mathlib/CategoryTheory/Category/ReflQuiv.lean @@ -0,0 +1,251 @@ +/- +Copyright (c) 2024 Mario Carneiro and Emily Riehl. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Emily Riehl +-/ +import Mathlib.Combinatorics.Quiver.ReflQuiver +import Mathlib.CategoryTheory.Category.Cat +import Mathlib.CategoryTheory.Category.Quiv + +/-! +# The category of refl quivers + +The category `ReflQuiv` of (bundled) reflexive quivers, and the free/forgetful adjunction between +`Cat` and `ReflQuiv`. +-/ + +namespace CategoryTheory +universe v u + +/-- Category of refl quivers. -/ +@[nolint checkUnivs] +def ReflQuiv := + Bundled ReflQuiver.{v + 1, u} + +namespace ReflQuiv + +instance : CoeSort ReflQuiv (Type u) where coe := Bundled.α + +instance (C : ReflQuiv.{v, u}) : ReflQuiver.{v + 1, u} C := C.str + +/-- The underlying quiver of a reflexive quiver.-/ +def toQuiv (C : ReflQuiv.{v, u}) : Quiv.{v, u} := Quiv.of C.α + +/-- Construct a bundled `ReflQuiv` from the underlying type and the typeclass. -/ +def of (C : Type u) [ReflQuiver.{v + 1} C] : ReflQuiv.{v, u} := Bundled.of C + +instance : Inhabited ReflQuiv := ⟨ReflQuiv.of (Discrete default)⟩ + +@[simp] theorem of_val (C : Type u) [ReflQuiver C] : (ReflQuiv.of C) = C := rfl + +/-- Category structure on `ReflQuiv` -/ +instance category : LargeCategory.{max v u} ReflQuiv.{v, u} where + Hom C D := ReflPrefunctor C D + id C := ReflPrefunctor.id C + comp F G := ReflPrefunctor.comp F G + +theorem id_eq_id (X : ReflQuiv) : 𝟙 X = 𝟭rq X := rfl +theorem comp_eq_comp {X Y Z : ReflQuiv} (F : X ⟶ Y) (G : Y ⟶ Z) : F ≫ G = F ⋙rq G := rfl + +/-- The forgetful functor from categories to quivers. -/ +@[simps] +def forget : Cat.{v, u} ⥤ ReflQuiv.{v, u} where + obj C := ReflQuiv.of C + map F := F.toReflPrefunctor + +theorem forget_faithful {C D : Cat.{v, u}} (F G : C ⥤ D) + (hyp : forget.map F = forget.map G) : F = G := by + cases F; cases G; cases hyp; rfl + +theorem forget.Faithful : Functor.Faithful (forget) where + map_injective := fun hyp ↦ forget_faithful _ _ hyp + +/-- The forgetful functor from categories to quivers. -/ +@[simps] +def forgetToQuiv : ReflQuiv.{v, u} ⥤ Quiv.{v, u} where + obj V := Quiv.of V + map F := F.toPrefunctor + +theorem forgetToQuiv_faithful {V W : ReflQuiv} (F G : V ⥤rq W) + (hyp : forgetToQuiv.map F = forgetToQuiv.map G) : F = G := by + cases F; cases G; cases hyp; rfl + +theorem forgetToQuiv.Faithful : Functor.Faithful (forgetToQuiv) where + map_injective := fun hyp ↦ forgetToQuiv_faithful _ _ hyp + +theorem forget_forgetToQuiv : forget ⋙ forgetToQuiv = Quiv.forget := rfl + +end ReflQuiv + +namespace ReflPrefunctor + +/-- A refl prefunctor can be promoted to a functor if it respects composition.-/ +def toFunctor {C D : Cat} (F : (ReflQuiv.of C) ⟶ (ReflQuiv.of D)) + (hyp : ∀ {X Y Z : ↑C} (f : X ⟶ Y) (g : Y ⟶ Z), + F.map (CategoryStruct.comp (obj := C) f g) = + CategoryStruct.comp (obj := D) (F.map f) (F.map g)) : C ⥤ D where + obj := F.obj + map := F.map + map_id := F.map_id + map_comp := hyp + +end ReflPrefunctor + +namespace Cat + +/-- The hom relation that identifies the specified reflexivity arrows with the nil paths.-/ +inductive FreeReflRel {V} [ReflQuiver V] : (X Y : Paths V) → (f g : X ⟶ Y) → Prop + | mk {X : V} : FreeReflRel X X (Quiver.Hom.toPath (𝟙rq X)) .nil + +/-- A reflexive quiver generates a free category, defined as as quotient of the free category +on its underlying quiver (called the "path category") by the hom relation that uses the specified +reflexivity arrows as the identity arrows. -/ +def FreeRefl (V) [ReflQuiver V] := + Quotient (C := Cat.free.obj (Quiv.of V)) (FreeReflRel (V := V)) + +instance (V) [ReflQuiver V] : Category (FreeRefl V) := + inferInstanceAs (Category (Quotient _)) + +/-- The quotient functor associated to a quotient category defines a natural map from the free +category on the underlying quiver of a refl quiver to the free category on the reflexive quiver.-/ +def FreeRefl.quotientFunctor (V) [ReflQuiver V] : Cat.free.obj (Quiv.of V) ⥤ FreeRefl V := + Quotient.functor (C := Cat.free.obj (Quiv.of V)) (FreeReflRel (V := V)) + +/-- This is a specialization of `Quotient.lift_unique'` rather than `Quotient.lift_unique`, hence +the prime in the name.-/ +theorem FreeRefl.lift_unique' {V} [ReflQuiver V] {D} [Category D] (F₁ F₂ : FreeRefl V ⥤ D) + (h : quotientFunctor V ⋙ F₁ = quotientFunctor V ⋙ F₂) : + F₁ = F₂ := + Quotient.lift_unique' (C := Cat.free.obj (Quiv.of V)) (FreeReflRel (V := V)) _ _ h + +/-- The functor sending a reflexive quiver to the free category it generates, a quotient of +its path category.-/ +@[simps!] +def freeRefl : ReflQuiv.{v, u} ⥤ Cat.{max u v, u} where + obj V := Cat.of (FreeRefl V) + map f := Quotient.lift _ ((by exact Cat.free.map f.toPrefunctor) ⋙ FreeRefl.quotientFunctor _) + (fun X Y f g hfg => by + apply Quotient.sound + cases hfg + simp [ReflPrefunctor.map_id] + constructor) + map_id X := by + dsimp + refine (Quotient.lift_unique _ _ _ _ ((Functor.comp_id _).trans <| + (Functor.id_comp _).symm.trans ?_)).symm + congr 1 + exact (free.map_id X.toQuiv).symm + map_comp {X Y Z} f g := by + dsimp + apply (Quotient.lift_unique _ _ _ _ _).symm + have : free.map (f ≫ g).toPrefunctor = + free.map (X := X.toQuiv) (Y := Y.toQuiv) f.toPrefunctor ⋙ + free.map (X := Y.toQuiv) (Y := Z.toQuiv) g.toPrefunctor := by + show _ = _ ≫ _ + rw [← Functor.map_comp]; rfl + rw [this, Functor.assoc] + show _ ⋙ _ ⋙ _ = _ + rw [← Functor.assoc, Quotient.lift_spec, Functor.assoc, FreeRefl.quotientFunctor, + Quotient.lift_spec] + +theorem freeRefl_naturality {X Y} [ReflQuiver X] [ReflQuiver Y] (f : X ⥤rq Y) : + free.map (X := Quiv.of X) (Y := Quiv.of Y) f.toPrefunctor ⋙ + FreeRefl.quotientFunctor ↑Y = + FreeRefl.quotientFunctor ↑X ⋙ freeRefl.map (X := ReflQuiv.of X) (Y := ReflQuiv.of Y) f := by + simp only [free_obj, FreeRefl.quotientFunctor, freeRefl, ReflQuiv.of_val] + rw [Quotient.lift_spec] + +/-- We will make use of the natural quotient map from the free category on the underlying +quiver of a refl quiver to the free category on the reflexive quiver.-/ +def freeReflNatTrans : ReflQuiv.forgetToQuiv ⋙ Cat.free ⟶ freeRefl where + app V := FreeRefl.quotientFunctor V + naturality _ _ f := freeRefl_naturality f + +end Cat + +namespace ReflQuiv +open Category Functor + +/-- The unit components are defined as the composite of the corresponding unit component for the +adjunction between categories and quivers with the map underlying the quotient functor.-/ +@[simps! toPrefunctor obj map] +def adj.unit.app (V : ReflQuiv.{max u v, u}) : V ⥤rq forget.obj (Cat.freeRefl.obj V) where + toPrefunctor := Quiv.adj.unit.app (V.toQuiv) ⋙q + Quiv.forget.map (Cat.FreeRefl.quotientFunctor V) + map_id := fun _ => Quotient.sound _ ⟨⟩ + +/-- This is used in the proof of both triangle equalities.-/ +theorem adj.unit.component_eq (V : ReflQuiv.{max u v, u}) : + forgetToQuiv.map (adj.unit.app V) = Quiv.adj.unit.app (V.toQuiv) ≫ + Quiv.forget.map (Y := Cat.of _) (Cat.FreeRefl.quotientFunctor V) := rfl + +/-- The counit components are defined using the universal property of the quotient +from the corresponding counit component for the adjunction between categories and quivers.-/ +@[simps!] +def adj.counit.app (C : Cat) : Cat.freeRefl.obj (forget.obj C) ⥤ C := by + fapply Quotient.lift + · exact Quiv.adj.counit.app C + · intro x y f g rel + cases rel + unfold Quiv.adj + simp only [Adjunction.mkOfHomEquiv_counit_app, Equiv.coe_fn_symm_mk, + Quiv.lift_map, Prefunctor.mapPath_toPath, composePath_toPath] + rfl + +/-- The counit of `ReflQuiv.adj` is closely related to the counit of `Quiv.adj`.-/ +@[simp] +theorem adj.counit.component_eq (C : Cat) : + Cat.FreeRefl.quotientFunctor C ⋙ adj.counit.app C = + Quiv.adj.counit.app C := rfl + +/-- The counit of `ReflQuiv.adj` is closely related to the counit of `Quiv.adj`. For ease of use, +we introduce primed version for unbundled categories.-/ +@[simp] +theorem adj.counit.component_eq' (C) [Category C] : + Cat.FreeRefl.quotientFunctor C ⋙ adj.counit.app (Cat.of C) = + Quiv.adj.counit.app (Cat.of C) := rfl + +/-- +The adjunction between forming the free category on a reflexive quiver, and forgetting a category +to a reflexive quiver. +-/ +nonrec def adj : Cat.freeRefl.{max u v, u} ⊣ ReflQuiv.forget := + Adjunction.mkOfUnitCounit { + unit := { + app := adj.unit.app + naturality := fun V W f ↦ by exact rfl + } + counit := { + app := adj.counit.app + naturality := fun C D F ↦ Quotient.lift_unique' _ _ _ (Quiv.adj.counit.naturality F) + } + left_triangle := by + ext V + apply Cat.FreeRefl.lift_unique' + simp only [id_obj, Cat.free_obj, comp_obj, Cat.freeRefl_obj_α, NatTrans.comp_app, + forget_obj, whiskerRight_app, associator_hom_app, whiskerLeft_app, id_comp, + NatTrans.id_app'] + rw [Cat.id_eq_id, Cat.comp_eq_comp] + simp only [Cat.freeRefl_obj_α, Functor.comp_id] + rw [← Functor.assoc, ← Cat.freeRefl_naturality, Functor.assoc] + dsimp [Cat.freeRefl] + rw [adj.counit.component_eq' (Cat.FreeRefl V)] + conv => + enter [1, 1, 2] + apply (Quiv.comp_eq_comp (X := Quiv.of _) (Y := Quiv.of _) (Z := Quiv.of _) ..).symm + rw [Cat.free.map_comp] + show (_ ⋙ ((Quiv.forget ⋙ Cat.free).map (X := Cat.of _) (Y := Cat.of _) + (Cat.FreeRefl.quotientFunctor V))) ⋙ _ = _ + rw [Functor.assoc, ← Cat.comp_eq_comp] + conv => enter [1, 2]; apply Quiv.adj.counit.naturality + rw [Cat.comp_eq_comp, ← Functor.assoc, ← Cat.comp_eq_comp] + conv => enter [1, 1]; apply Quiv.adj.left_triangle_components V.toQuiv + exact Functor.id_comp _ + right_triangle := by + ext C + exact forgetToQuiv_faithful _ _ (Quiv.adj.right_triangle_components C) + } + +end ReflQuiv + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/ChosenFiniteProducts.lean b/Mathlib/CategoryTheory/ChosenFiniteProducts.lean index 94e7ecaf158cf..7ae5f97b5511b 100644 --- a/Mathlib/CategoryTheory/ChosenFiniteProducts.lean +++ b/Mathlib/CategoryTheory/ChosenFiniteProducts.lean @@ -103,6 +103,14 @@ lemma lift_fst {T X Y : C} (f : T ⟶ X) (g : T ⟶ Y) : lift f g ≫ fst _ _ = lemma lift_snd {T X Y : C} (f : T ⟶ X) (g : T ⟶ Y) : lift f g ≫ snd _ _ = g := by simp [lift, snd] +instance mono_lift_of_mono_left {W X Y : C} (f : W ⟶ X) (g : W ⟶ Y) + [Mono f] : Mono (lift f g) := + mono_of_mono_fac <| lift_fst _ _ + +instance mono_lift_of_mono_right {W X Y : C} (f : W ⟶ X) (g : W ⟶ Y) + [Mono g] : Mono (lift f g) := + mono_of_mono_fac <| lift_snd _ _ + @[ext 1050] lemma hom_ext {T X Y : C} (f g : T ⟶ X ⊗ Y) (h_fst : f ≫ fst _ _ = g ≫ fst _ _) diff --git a/Mathlib/CategoryTheory/Closed/Cartesian.lean b/Mathlib/CategoryTheory/Closed/Cartesian.lean index c4ac634c52efb..e25efebbe63d0 100644 --- a/Mathlib/CategoryTheory/Closed/Cartesian.lean +++ b/Mathlib/CategoryTheory/Closed/Cartesian.lean @@ -226,21 +226,15 @@ end CartesianClosed open CartesianClosed -/-- Show that the exponential of the terminal object is isomorphic to itself, i.e. `X^1 ≅ X`. +/-- The exponential with the terminal object is naturally isomorphic to the identity. The typeclass +argument is explicit: any instance can be used.-/ +def expTerminalNatIso [Exponentiable (⊤_ C)] : 𝟭 C ≅ exp (⊤_ C) := + MonoidalClosed.unitNatIso (C := C) -The typeclass argument is explicit: any instance can be used. --/ +/-- The exponential of any object with the terminal object is isomorphic to itself, i.e. `X^1 ≅ X`. +The typeclass argument is explicit: any instance can be used.-/ def expTerminalIsoSelf [Exponentiable (⊤_ C)] : (⊤_ C) ⟹ X ≅ X := - Yoneda.ext ((⊤_ C) ⟹ X) X - (fun {Y} f => (Limits.prod.leftUnitor Y).inv ≫ CartesianClosed.uncurry f) - (fun {Y} f => CartesianClosed.curry ((Limits.prod.leftUnitor Y).hom ≫ f)) - (fun g => by - rw [curry_eq_iff, Iso.hom_inv_id_assoc]) - (fun g => by simp) - (fun f g => by - -- Porting note: `rw` is a bit brittle here, requiring the `dsimp` rule cancellation. - dsimp [-prod.leftUnitor_inv] - rw [uncurry_natural_left, prod.leftUnitor_inv_naturality_assoc f]) + (expTerminalNatIso.app X).symm /-- The internal element which points at the given morphism. -/ def internalizeHom (f : A ⟶ Y) : ⊤_ C ⟶ A ⟹ Y := diff --git a/Mathlib/CategoryTheory/Closed/Monoidal.lean b/Mathlib/CategoryTheory/Closed/Monoidal.lean index 8309157796ab1..43af4d461c0de 100644 --- a/Mathlib/CategoryTheory/Closed/Monoidal.lean +++ b/Mathlib/CategoryTheory/Closed/Monoidal.lean @@ -196,6 +196,10 @@ theorem curry_id_eq_coev : curry (𝟙 _) = (ihom.coev A).app X := by rw [curry_eq, (ihom A).map_id (A ⊗ _)] apply comp_id +/-- The internal hom out of the unit is naturally isomorphic to the identity functor.-/ +def unitNatIso [Closed (𝟙_ C)] : 𝟭 C ≅ ihom (𝟙_ C) := + conjugateIsoEquiv (Adjunction.id (C := C)) (ihom.adjunction (𝟙_ C)) + (leftUnitorNatIso C) section Pre variable {A B} diff --git a/Mathlib/CategoryTheory/Comma/Arrow.lean b/Mathlib/CategoryTheory/Comma/Arrow.lean index 972c94b207848..9ab800f7f7cc4 100644 --- a/Mathlib/CategoryTheory/Comma/Arrow.lean +++ b/Mathlib/CategoryTheory/Comma/Arrow.lean @@ -152,7 +152,7 @@ theorem hom.congr_right {f g : Arrow T} {φ₁ φ₂ : f ⟶ g} (h : φ₁ = φ theorem iso_w {f g : Arrow T} (e : f ≅ g) : g.hom = e.inv.left ≫ f.hom ≫ e.hom.right := by have eq := Arrow.hom.congr_right e.inv_hom_id rw [Arrow.comp_right, Arrow.id_right] at eq - erw [Arrow.w_assoc, eq, Category.comp_id] + rw [Arrow.w_assoc, eq, Category.comp_id] theorem iso_w' {W X Y Z : T} {f : W ⟶ X} {g : Y ⟶ Z} (e : Arrow.mk f ≅ Arrow.mk g) : g = e.inv.left ≫ f ≫ e.hom.right := diff --git a/Mathlib/CategoryTheory/Comma/Over.lean b/Mathlib/CategoryTheory/Comma/Over.lean index 7a62b01614f0a..12c572b50df5c 100644 --- a/Mathlib/CategoryTheory/Comma/Over.lean +++ b/Mathlib/CategoryTheory/Comma/Over.lean @@ -66,7 +66,7 @@ theorem over_right (U : Over X) : U.right = ⟨⟨⟩⟩ := by simp only theorem id_left (U : Over X) : CommaMorphism.left (𝟙 U) = 𝟙 U.left := rfl -@[simp] +@[simp, reassoc] theorem comp_left (a b c : Over X) (f : a ⟶ b) (g : b ⟶ c) : (f ≫ g).left = f.left ≫ g.left := rfl @@ -675,7 +675,7 @@ def ofStructuredArrowProjEquivalence (F : D ⥤ T) (Y : T) (X : D) : counitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by aesop_cat) /-- The canonical functor from the structured arrow category on the diagonal functor -`T ⥤ T × T` to the the structured arrow category on `Under.forget`. -/ +`T ⥤ T × T` to the structured arrow category on `Under.forget`. -/ @[simps!] def ofDiagEquivalence.functor (X : T × T) : StructuredArrow X (Functor.diag _) ⥤ StructuredArrow X.2 (Under.forget X.1) := @@ -741,7 +741,7 @@ def ofCostructuredArrowProjEquivalence (F : T ⥤ D) (Y : D) (X : T) : counitIso := NatIso.ofComponents (fun _ => Iso.refl _) (by aesop_cat) /-- The canonical functor from the costructured arrow category on the diagonal functor -`T ⥤ T × T` to the the costructured arrow category on `Under.forget`. -/ +`T ⥤ T × T` to the costructured arrow category on `Under.forget`. -/ @[simps!] def ofDiagEquivalence.functor (X : T × T) : CostructuredArrow (Functor.diag _) X ⥤ CostructuredArrow (Over.forget X.1) X.2 := diff --git a/Mathlib/CategoryTheory/ComposableArrows.lean b/Mathlib/CategoryTheory/ComposableArrows.lean index d0547116852eb..49706164e2037 100644 --- a/Mathlib/CategoryTheory/ComposableArrows.lean +++ b/Mathlib/CategoryTheory/ComposableArrows.lean @@ -550,14 +550,14 @@ lemma ext_succ {F G : ComposableArrows C (n + 1)} (h₀ : F.obj' 0 = G.obj' 0) exact Functor.ext_of_iso (isoMkSucc (eqToIso h₀) (eqToIso h) (by rw [w] dsimp [app'] - erw [eqToHom_app, assoc, assoc, eqToHom_trans, eqToHom_refl, comp_id])) this (by + rw [eqToHom_app, assoc, assoc, eqToHom_trans, eqToHom_refl, comp_id])) this (by rintro ⟨i, hi⟩ dsimp cases' i with i · erw [homMkSucc_app_zero] - · erw [homMkSucc_app_succ] + · rw [homMkSucc_app_succ] dsimp [app'] - erw [eqToHom_app]) + rw [eqToHom_app]) lemma precomp_surjective (F : ComposableArrows C (n + 1)) : ∃ (F₀ : ComposableArrows C n) (X₀ : C) (f₀ : X₀ ⟶ F₀.left), F = F₀.precomp f₀ := diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean index 0e42d549b245a..38882d4e9f448 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Basic.lean @@ -76,7 +76,7 @@ instance : HasCoeToSort X := ConcreteCategory.hasCoeToSort X -/ def ConcreteCategory.hasCoeToSort (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] : CoeSort C (Type w) where - coe := fun X => (forget C).obj X + coe X := (forget C).obj X section diff --git a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean index d2a6dab1aa44a..1fe01ebf2d14a 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/Bundled.lean @@ -22,7 +22,7 @@ universe u v namespace CategoryTheory -variable {c d : Type u → Type v} {α : Type u} +variable {c d : Type u → Type v} /-- `Bundled` is a type bundled with a type class instance for that type. Only the type class is exposed as a parameter. -/ diff --git a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean index 7293c742fab92..e4763010998ab 100644 --- a/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean +++ b/Mathlib/CategoryTheory/ConcreteCategory/BundledHom.lean @@ -74,6 +74,12 @@ instance concreteCategory : ConcreteCategory.{u} (Bundled c) where map_comp := fun f g => by dsimp; erw [𝒞.comp_toFun];rfl } forget_faithful := { map_injective := by (intros; apply 𝒞.hom_ext) } +/-- This unification hint helps `rw` to figure out how to apply statements about abstract +concrete categories to specific concrete categories. Crucially, it fires also at `reducible` +levels so `rw` can use it (and we don't have to use `erw`). -/ +unif_hint (C : Bundled c) where + ⊢ (CategoryTheory.forget (Bundled c)).obj C =?= Bundled.α C + variable {hom} attribute [local instance] ConcreteCategory.instFunLike diff --git a/Mathlib/CategoryTheory/ConnectedComponents.lean b/Mathlib/CategoryTheory/ConnectedComponents.lean index cc86ae90a2167..0d205fcbb0170 100644 --- a/Mathlib/CategoryTheory/ConnectedComponents.lean +++ b/Mathlib/CategoryTheory/ConnectedComponents.lean @@ -7,7 +7,6 @@ import Mathlib.Data.List.Chain import Mathlib.CategoryTheory.IsConnected import Mathlib.CategoryTheory.Sigma.Basic import Mathlib.CategoryTheory.FullSubcategory -import Mathlib.Data.List.Infix /-! # Connected components of a category diff --git a/Mathlib/CategoryTheory/DifferentialObject.lean b/Mathlib/CategoryTheory/DifferentialObject.lean index b5463218d54bf..a4cb04addaf1f 100644 --- a/Mathlib/CategoryTheory/DifferentialObject.lean +++ b/Mathlib/CategoryTheory/DifferentialObject.lean @@ -256,7 +256,7 @@ nonrec def shiftFunctorAdd (m n : S) : · dsimp rw [← cancel_epi ((shiftFunctorAdd C m n).inv.app X.obj)] simp only [Category.assoc, Iso.inv_hom_id_app_assoc] - erw [← NatTrans.naturality_assoc] + rw [← NatTrans.naturality_assoc] dsimp simp only [Functor.map_comp, Category.assoc, shiftFunctorComm_hom_app_comp_shift_shiftFunctorAdd_hom_app 1 m n X.obj, diff --git a/Mathlib/CategoryTheory/Elements.lean b/Mathlib/CategoryTheory/Elements.lean index 3269eddc6bd86..3ff60562fdb11 100644 --- a/Mathlib/CategoryTheory/Elements.lean +++ b/Mathlib/CategoryTheory/Elements.lean @@ -223,9 +223,9 @@ def fromCostructuredArrow (F : Cᵒᵖ ⥤ Type v) : (CostructuredArrow yoneda F Category.comp_id, yoneda_obj_map] have : yoneda.map f.unop.left ≫ (unop X).hom = (unop Y).hom := by convert f.unop.3 - erw [← this] + rw [← this] simp only [yoneda_map_app, FunctorToTypes.comp] - erw [Category.id_comp]⟩ + rw [Category.id_comp]⟩ @[simp] theorem fromCostructuredArrow_obj_mk (F : Cᵒᵖ ⥤ Type v) {X : C} (f : yoneda.obj X ⟶ F) : diff --git a/Mathlib/CategoryTheory/Extensive.lean b/Mathlib/CategoryTheory/Extensive.lean index 887e41f0debb8..94619f08a21bb 100644 --- a/Mathlib/CategoryTheory/Extensive.lean +++ b/Mathlib/CategoryTheory/Extensive.lean @@ -527,7 +527,7 @@ instance FinitaryPreExtensive.hasPullbacks_of_inclusions [FinitaryPreExtensive C {α : Type*} (f : X ⟶ Z) {Y : (a : α) → C} (i : (a : α) → Y a ⟶ Z) [Finite α] [hi : IsIso (Sigma.desc i)] (a : α) : HasPullback f (i a) := by apply FinitaryPreExtensive.hasPullbacks_of_is_coproduct (c := Cofan.mk Z i) - exact @IsColimit.ofPointIso (t := Cofan.mk Z i) (P := _) hi + exact @IsColimit.ofPointIso (t := Cofan.mk Z i) (P := _) (i := hi) lemma FinitaryPreExtensive.sigma_desc_iso [FinitaryPreExtensive C] {α : Type} [Finite α] {X : C} {Z : α → C} (π : (a : α) → Z a ⟶ X) {Y : C} (f : Y ⟶ X) (hπ : IsIso (Sigma.desc π)) : @@ -536,7 +536,7 @@ lemma FinitaryPreExtensive.sigma_desc_iso [FinitaryPreExtensive C] {α : Type} [ change IsIso (this.coconePointUniqueUpToIso (getColimitCocone _).2).inv infer_instance let this : IsColimit (Cofan.mk X π) := by - refine @IsColimit.ofPointIso (t := Cofan.mk X π) (P := coproductIsCoproduct Z) ?_ + refine @IsColimit.ofPointIso (t := Cofan.mk X π) (P := coproductIsCoproduct Z) (i := ?_) convert hπ simp [coproductIsCoproduct] refine (FinitaryPreExtensive.isUniversal_finiteCoproducts this diff --git a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean index c2f4a20e934c0..b6f222bcedcbc 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Cartesian.lean @@ -119,6 +119,7 @@ lemma map_self : IsCartesian.map p f φ φ = 𝟙 a := by /-- The canonical isomorphism between the domains of two cartesian morphisms lying over the same object. -/ +@[simps] noncomputable def domainUniqueUpToIso {a' : 𝒳} (φ' : a' ⟶ b) [IsCartesian p f φ'] : a' ≅ a where hom := IsCartesian.map p f φ φ' inv := IsCartesian.map p f φ' φ @@ -131,6 +132,14 @@ noncomputable def domainUniqueUpToIso {a' : 𝒳} (φ' : a' ⟶ b) [IsCartesian apply IsCartesian.ext p (p.map φ) φ simp only [assoc, fac, id_comp] +instance domainUniqueUpToIso_inv_isHomLift {a' : 𝒳} (φ' : a' ⟶ b) [IsCartesian p f φ'] : + IsHomLift p (𝟙 R) (domainUniqueUpToIso p f φ φ').hom := + domainUniqueUpToIso_hom p f φ φ' ▸ IsCartesian.map_isHomLift p f φ φ' + +instance domainUniqueUpToIso_hom_isHomLift {a' : 𝒳} (φ' : a' ⟶ b) [IsCartesian p f φ'] : + IsHomLift p (𝟙 R) (domainUniqueUpToIso p f φ φ').inv := + domainUniqueUpToIso_inv p f φ φ' ▸ IsCartesian.map_isHomLift p f φ' φ + /-- Precomposing a cartesian morphism with an isomorphism lifting the identity is cartesian. -/ instance of_iso_comp {a' : 𝒳} (φ' : a' ≅ a) [IsHomLift p (𝟙 R) φ'.hom] : IsCartesian p f (φ'.hom ≫ φ) where @@ -351,15 +360,34 @@ lemma isIso_of_base_isIso (φ : a ⟶ b) [IsStronglyCartesian p f φ] [IsIso f] end +section + +variable {R R' S : 𝒮} {a a' b : 𝒳} {f : R ⟶ S} {f' : R' ⟶ S} {g : R' ≅ R} + /-- The canonical isomorphism between the domains of two strongly cartesian morphisms lying over isomorphic objects. -/ -noncomputable def domainIsoOfBaseIso {R R' S : 𝒮} {a a' b : 𝒳} {f : R ⟶ S} {f' : R' ⟶ S} - {g : R' ≅ R} (h : f' = g.hom ≫ f) (φ : a ⟶ b) (φ' : a' ⟶ b) [IsStronglyCartesian p f φ] - [IsStronglyCartesian p f' φ'] : a' ≅ a where +@[simps] +noncomputable def domainIsoOfBaseIso (h : f' = g.hom ≫ f) (φ : a ⟶ b) (φ' : a' ⟶ b) + [IsStronglyCartesian p f φ] [IsStronglyCartesian p f' φ'] : a' ≅ a where hom := map p f φ h φ' - inv := by - convert map p f' φ' (congrArg (g.inv ≫ ·) h.symm) φ + inv := + haveI : p.IsHomLift ((fun x ↦ g.inv ≫ x) (g.hom ≫ f)) φ := by + simpa using IsCartesian.toIsHomLift + map p f' φ' (congrArg (g.inv ≫ ·) h.symm) φ + +instance domainUniqueUpToIso_inv_isHomLift (h : f' = g.hom ≫ f) (φ : a ⟶ b) (φ' : a' ⟶ b) + [IsStronglyCartesian p f φ] [IsStronglyCartesian p f' φ'] : + IsHomLift p g.hom (domainIsoOfBaseIso p h φ φ').hom := + domainIsoOfBaseIso_hom p h φ φ' ▸ IsStronglyCartesian.map_isHomLift p f φ h φ' + +instance domainUniqueUpToIso_hom_isHomLift (h : f' = g.hom ≫ f) (φ : a ⟶ b) (φ' : a' ⟶ b) + [IsStronglyCartesian p f φ] [IsStronglyCartesian p f' φ'] : + IsHomLift p g.inv (domainIsoOfBaseIso p h φ φ').inv := by + haveI : p.IsHomLift ((fun x ↦ g.inv ≫ x) (g.hom ≫ f)) φ := by simpa using IsCartesian.toIsHomLift + simpa using IsStronglyCartesian.map_isHomLift p f' φ' (congrArg (g.inv ≫ ·) h.symm) φ + +end end IsStronglyCartesian diff --git a/Mathlib/CategoryTheory/FiberedCategory/Fibered.lean b/Mathlib/CategoryTheory/FiberedCategory/Fibered.lean index c3342d615089e..b826fc429e660 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/Fibered.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/Fibered.lean @@ -17,6 +17,15 @@ This file defines what it means for a functor `p : 𝒳 ⥤ 𝒮` to be (pre)fib - `IsPreFibered p` expresses `𝒳` is fibered over `𝒮` via a functor `p : 𝒳 ⥤ 𝒮`, as in SGA VI.6.1. This means that any morphism in the base `𝒮` can be lifted to a cartesian morphism in `𝒳`. +- `IsFibered p` expresses `𝒳` is fibered over `𝒮` via a functor `p : 𝒳 ⥤ 𝒮`, as in SGA VI.6.1. +This means that it is prefibered, and that the composition of any two cartesian morphisms is +cartesian. + +In the literature one often sees the notion of a fibered category defined as the existence of +strongly cartesian morphisms lying over any given morphism in the base. This is equivalent to the +notion above, and we give an alternate constructor `IsFibered.of_exists_isCartesian'` for +constructing a fibered category this way. + ## Implementation The constructor of `IsPreFibered` is called `exists_isCartesian'`. The reason for the prime is that @@ -47,7 +56,18 @@ protected lemma IsPreFibered.exists_isCartesian (p : 𝒳 ⥤ 𝒮) [p.IsPreFibe (ha : p.obj a = S) (f : R ⟶ S) : ∃ (b : 𝒳) (φ : b ⟶ a), IsCartesian p f φ := by subst ha; exact IsPreFibered.exists_isCartesian' f -namespace IsPreFibered +/-- Definition of a fibered category. + +See SGA 1 VI.6.1. -/ +class Functor.IsFibered (p : 𝒳 ⥤ 𝒮) extends IsPreFibered p : Prop where + comp {R S T : 𝒮} (f : R ⟶ S) (g : S ⟶ T) {a b c : 𝒳} (φ : a ⟶ b) (ψ : b ⟶ c) + [IsCartesian p f φ] [IsCartesian p g ψ] : IsCartesian p (f ≫ g) (φ ≫ ψ) + +instance (p : 𝒳 ⥤ 𝒮) [p.IsFibered] {R S T : 𝒮} (f : R ⟶ S) (g : S ⟶ T) {a b c : 𝒳} (φ : a ⟶ b) + (ψ : b ⟶ c) [IsCartesian p f φ] [IsCartesian p g ψ] : IsCartesian p (f ≫ g) (φ ≫ ψ) := + IsFibered.comp f g φ ψ + +namespace Functor.IsPreFibered open IsCartesian @@ -70,6 +90,97 @@ instance pullbackMap.IsCartesian : IsCartesian p f (pullbackMap ha f) := lemma pullbackObj_proj : p.obj (pullbackObj ha f) = R := domain_eq p f (pullbackMap ha f) -end IsPreFibered +end Functor.IsPreFibered + +namespace Functor.IsFibered + +open IsCartesian IsPreFibered + +/-- In a fibered category, any cartesian morphism is strongly cartesian. -/ +instance isStronglyCartesian_of_isCartesian (p : 𝒳 ⥤ 𝒮) [p.IsFibered] {R S : 𝒮} (f : R ⟶ S) + {a b : 𝒳} (φ : a ⟶ b) [p.IsCartesian f φ] : p.IsStronglyCartesian f φ where + universal_property' g φ' hφ' := by + -- Let `ψ` be a cartesian arrow lying over `g` + let ψ := pullbackMap (domain_eq p f φ) g + -- Let `τ` be the map induced by the universal property of `ψ ≫ φ`. + let τ := IsCartesian.map p (g ≫ f) (ψ ≫ φ) φ' + use τ ≫ ψ + -- It is easily verified that `τ ≫ ψ` lifts `g` and `τ ≫ ψ ≫ φ = φ'` + refine ⟨⟨inferInstance, by simp only [assoc, IsCartesian.fac, τ]⟩, ?_⟩ + -- It remains to check that `τ ≫ ψ` is unique. + -- So fix another lift `π` of `g` satisfying `π ≫ φ = φ'`. + intro π ⟨hπ, hπ_comp⟩ + -- Write `π` as `π = τ' ≫ ψ` for some `τ'` induced by the universal property of `ψ`. + rw [← fac p g ψ π] + -- It remains to show that `τ' = τ`. This follows again from the universal property of `ψ`. + congr 1 + apply map_uniq + rwa [← assoc, IsCartesian.fac] + +/-- In a category which admits strongly cartesian pullbacks, any cartesian morphism is +strongly cartesian. This is a helper-lemma for the fact that admitting strongly cartesian pullbacks +implies being fibered. -/ +lemma isStronglyCartesian_of_exists_isCartesian (p : 𝒳 ⥤ 𝒮) (h : ∀ (a : 𝒳) (R : 𝒮) + (f : R ⟶ p.obj a), ∃ (b : 𝒳) (φ : b ⟶ a), IsStronglyCartesian p f φ) {R S : 𝒮} (f : R ⟶ S) + {a b : 𝒳} (φ : a ⟶ b) [p.IsCartesian f φ] : p.IsStronglyCartesian f φ := by + constructor + intro c g φ' hφ' + subst_hom_lift p f φ; clear a b R S + -- Let `ψ` be a cartesian arrow lying over `g` + obtain ⟨a', ψ, hψ⟩ := h _ _ (p.map φ) + -- Let `τ' : c ⟶ a'` be the map induced by the universal property of `ψ` + let τ' := IsStronglyCartesian.map p (p.map φ) ψ (f':= g ≫ p.map φ) rfl φ' + -- Let `Φ : a' ≅ a` be natural isomorphism induced between `φ` and `ψ`. + let Φ := domainUniqueUpToIso p (p.map φ) φ ψ + -- The map induced by `φ` will be `τ' ≫ Φ.hom` + use τ' ≫ Φ.hom + -- It is easily verified that `τ' ≫ Φ.hom` lifts `g` and `τ' ≫ Φ.hom ≫ φ = φ'` + refine ⟨⟨by simp only [Φ]; infer_instance, ?_⟩, ?_⟩ + · simp [τ', Φ, IsStronglyCartesian.map_uniq p (p.map φ) ψ rfl φ'] + -- It remains to check that it is unique. This follows from the universal property of `ψ`. + intro π ⟨hπ, hπ_comp⟩ + rw [← Iso.comp_inv_eq] + apply IsStronglyCartesian.map_uniq p (p.map φ) ψ rfl φ' + simp [hπ_comp, Φ] + +/-- Alternate constructor for `IsFibered`, a functor `p : 𝒳 ⥤ 𝒴` is fibered if any diagram of the +form +``` + a + - + | + v +R --f--> p(a) +``` +admits a strongly cartesian lift `b ⟶ a` of `f`. -/ +lemma of_exists_isStronglyCartesian {p : 𝒳 ⥤ 𝒮} + (h : ∀ (a : 𝒳) (R : 𝒮) (f : R ⟶ p.obj a), + ∃ (b : 𝒳) (φ : b ⟶ a), IsStronglyCartesian p f φ) : + IsFibered p where + exists_isCartesian' := by + intro a R f + obtain ⟨b, φ, hφ⟩ := h a R f + refine ⟨b, φ, inferInstance⟩ + comp := fun R S T f g {a b c} φ ψ _ _ => + have : p.IsStronglyCartesian f φ := isStronglyCartesian_of_exists_isCartesian p h _ _ + have : p.IsStronglyCartesian g ψ := isStronglyCartesian_of_exists_isCartesian p h _ _ + inferInstance + +/-- Given a diagram +``` + a + - + | + v +T --g--> R --f--> S +``` +we have an isomorphism `T ×_S a ≅ T ×_R (R ×_S a)` -/ +noncomputable def pullbackPullbackIso {p : 𝒳 ⥤ 𝒮} [IsFibered p] + {R S T : 𝒮} {a : 𝒳} (ha : p.obj a = S) (f : R ⟶ S) (g : T ⟶ R) : + pullbackObj ha (g ≫ f) ≅ pullbackObj (pullbackObj_proj ha f) g := + domainUniqueUpToIso p (g ≫ f) (pullbackMap (pullbackObj_proj ha f) g ≫ pullbackMap ha f) + (pullbackMap ha (g ≫ f)) + +end Functor.IsFibered end CategoryTheory diff --git a/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean b/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean index 595fb845dc473..8de8bf2c92401 100644 --- a/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean +++ b/Mathlib/CategoryTheory/FiberedCategory/HomLift.lean @@ -142,7 +142,7 @@ instance comp_lift_id_left {a b c : 𝒳} {S T : 𝒮} (f : S ⟶ T) (ψ : b ⟶ lemma comp_lift_id_left' {a b c : 𝒳} (R : 𝒮) (φ : a ⟶ b) [p.IsHomLift (𝟙 R) φ] {S T : 𝒮} (f : S ⟶ T) (ψ : b ⟶ c) [p.IsHomLift f ψ] : p.IsHomLift f (φ ≫ ψ) := by obtain rfl : R = S := by rw [← codomain_eq p (𝟙 R) φ, domain_eq p f ψ] - simpa using inferInstanceAs (p.IsHomLift (𝟙 R ≫ f) (φ ≫ ψ)) + infer_instance lemma eqToHom_domain_lift_id {p : 𝒳 ⥤ 𝒮} {a b : 𝒳} (hab : a = b) {R : 𝒮} (hR : p.obj a = R) : p.IsHomLift (𝟙 R) (eqToHom hab) := by diff --git a/Mathlib/CategoryTheory/Functor/Currying.lean b/Mathlib/CategoryTheory/Functor/Currying.lean index edaba6e369347..e130aedb422c8 100644 --- a/Mathlib/CategoryTheory/Functor/Currying.lean +++ b/Mathlib/CategoryTheory/Functor/Currying.lean @@ -3,6 +3,7 @@ Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ +import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Products.Basic /-! diff --git a/Mathlib/CategoryTheory/Functor/KanExtension/Adjunction.lean b/Mathlib/CategoryTheory/Functor/KanExtension/Adjunction.lean index 57c9c1c9353e0..fe8433c905fb7 100644 --- a/Mathlib/CategoryTheory/Functor/KanExtension/Adjunction.lean +++ b/Mathlib/CategoryTheory/Functor/KanExtension/Adjunction.lean @@ -168,7 +168,7 @@ precomposition by `L`. -/ noncomputable def ranAdjunction : (whiskeringLeft C D H).obj L ⊣ L.ran := Adjunction.mkOfHomEquiv { homEquiv := fun F G => - (homEquivOfIsRightKanExtension (α := L.ranCounit.app G) F).symm + (homEquivOfIsRightKanExtension (α := L.ranCounit.app G) _ F).symm homEquiv_naturality_right := fun {F G₁ G₂} β f ↦ hom_ext_of_isRightKanExtension _ (L.ranCounit.app G₂) _ _ (by ext X diff --git a/Mathlib/CategoryTheory/Functor/KanExtension/Pointwise.lean b/Mathlib/CategoryTheory/Functor/KanExtension/Pointwise.lean index cf9297f47d979..9d4cb7a6c2ea1 100644 --- a/Mathlib/CategoryTheory/Functor/KanExtension/Pointwise.lean +++ b/Mathlib/CategoryTheory/Functor/KanExtension/Pointwise.lean @@ -343,6 +343,27 @@ instance : (pointwiseLeftKanExtension L F).IsLeftKanExtension instance : HasLeftKanExtension L F := HasLeftKanExtension.mk _ (pointwiseLeftKanExtensionUnit L F) +/-- An auxiliary cocone used in the lemma `pointwiseLeftKanExtension_desc_app` -/ +@[simps] +def costructuredArrowMapCocone (G : D ⥤ H) (α : F ⟶ L ⋙ G) (Y : D) : + Cocone (CostructuredArrow.proj L Y ⋙ F) where + pt := G.obj Y + ι := { + app := fun f ↦ α.app f.left ≫ G.map f.hom + naturality := by simp [← G.map_comp] } + +@[simp] +lemma pointwiseLeftKanExtension_desc_app (G : D ⥤ H) (α : F ⟶ L ⋙ G) (Y : D) : + ((pointwiseLeftKanExtension L F).descOfIsLeftKanExtension (pointwiseLeftKanExtensionUnit L F) + G α |>.app Y) = colimit.desc _ (costructuredArrowMapCocone L F G α Y) := by + let β : L.pointwiseLeftKanExtension F ⟶ G := + { app := fun Y ↦ colimit.desc _ (costructuredArrowMapCocone L F G α Y) } + have h : (pointwiseLeftKanExtension L F).descOfIsLeftKanExtension + (pointwiseLeftKanExtensionUnit L F) G α = β := by + apply hom_ext_of_isLeftKanExtension (α := pointwiseLeftKanExtensionUnit L F) + aesop + exact NatTrans.congr_app h Y + variable {F L} /-- If `F` admits a pointwise left Kan extension along `L`, then any left Kan extension of `F` @@ -421,6 +442,28 @@ instance : (pointwiseRightKanExtension L F).IsRightKanExtension instance : HasRightKanExtension L F := HasRightKanExtension.mk _ (pointwiseRightKanExtensionCounit L F) +/-- An auxiliary cocone used in the lemma `pointwiseRightKanExtension_lift_app` -/ +@[simps] +def structuredArrowMapCone (G : D ⥤ H) (α : L ⋙ G ⟶ F) (Y : D) : + Cone (StructuredArrow.proj Y L ⋙ F) where + pt := G.obj Y + π := { + app := fun f ↦ G.map f.hom ≫ α.app f.right + naturality := by simp [← α.naturality, ← G.map_comp_assoc] } + +@[simp] +lemma pointwiseRightKanExtension_lift_app (G : D ⥤ H) (α : L ⋙ G ⟶ F) (Y : D) : + ((pointwiseRightKanExtension L F).liftOfIsRightKanExtension + (pointwiseRightKanExtensionCounit L F) G α |>.app Y) = + limit.lift _ (structuredArrowMapCone L F G α Y) := by + let β : G ⟶ L.pointwiseRightKanExtension F := + { app := fun Y ↦ limit.lift _ (structuredArrowMapCone L F G α Y) } + have h : (pointwiseRightKanExtension L F).liftOfIsRightKanExtension + (pointwiseRightKanExtensionCounit L F) G α = β := by + apply hom_ext_of_isRightKanExtension (α := pointwiseRightKanExtensionCounit L F) + aesop + exact NatTrans.congr_app h Y + variable {F L} /-- If `F` admits a pointwise right Kan extension along `L`, then any right Kan extension of `F` diff --git a/Mathlib/CategoryTheory/Galois/Basic.lean b/Mathlib/CategoryTheory/Galois/Basic.lean index 70049a038bcc4..a0cd79ac0d2fe 100644 --- a/Mathlib/CategoryTheory/Galois/Basic.lean +++ b/Mathlib/CategoryTheory/Galois/Basic.lean @@ -334,11 +334,12 @@ lemma surjective_of_nonempty_fiber_of_isConnected {X A : C} [Nonempty (F.obj X)] /-- If `X : ι → C` is a finite family of objects with non-empty fiber, then also `∏ᶜ X` has non-empty fiber. -/ -instance nonempty_fiber_pi_of_nonempty_of_finite {ι : Type*} [Fintype ι] (X : ι → C) - [∀ i, Nonempty (F.obj (X i))] : Nonempty (F.obj (∏ᶜ X)) := +instance nonempty_fiber_pi_of_nonempty_of_finite {ι : Type*} [Finite ι] (X : ι → C) + [∀ i, Nonempty (F.obj (X i))] : Nonempty (F.obj (∏ᶜ X)) := by + cases nonempty_fintype ι let f (i : ι) : FintypeCat.{w} := F.obj (X i) let i : F.obj (∏ᶜ X) ≅ ∏ᶜ f := PreservesProduct.iso F _ - Nonempty.elim inferInstance (fun x : (∏ᶜ f : FintypeCat.{w}) ↦ ⟨i.inv x⟩) + exact Nonempty.elim inferInstance fun x : (∏ᶜ f : FintypeCat.{w}) ↦ ⟨i.inv x⟩ section CardFiber diff --git a/Mathlib/CategoryTheory/Galois/EssSurj.lean b/Mathlib/CategoryTheory/Galois/EssSurj.lean new file mode 100644 index 0000000000000..06f9db4d4af8d --- /dev/null +++ b/Mathlib/CategoryTheory/Galois/EssSurj.lean @@ -0,0 +1,263 @@ +/- +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.Galois.Full +import Mathlib.CategoryTheory.Galois.Topology +import Mathlib.Topology.Algebra.OpenSubgroup + +/-! + +# Essential surjectivity of fiber functors + +Let `F : C ⥤ FintypeCat` be a fiber functor of a Galois category `C` and denote by +`H` the induced functor `C ⥤ Action FintypeCat (Aut F)`. + +In this file we show that the essential image of `H` consists of the finite `Aut F`-sets where +the `Aut F` action is continuous. + +## Main results + +- `exists_lift_of_quotient_openSubgroup`: If `U` is an open subgroup of `Aut F`, then + there exists an object `X` such that `F.obj X` is isomorphic to `Aut F ⧸ U` as + `Aut F`-sets. +- `exists_lift_of_continuous`: If `X` is a finite, discrete `Aut F`-set, then + there exists an object `A` such that `F.obj A` is isomorphic to `X` as + `Aut F`-sets. + +## Strategy + +We first show that every finite, discrete `Aut F`-set `Y` has a decomposition into connected +components and each connected component is of the form `Aut F ⧸ U` for an open subgroup `U`. +Since `H` preserves finite coproducts, it hence suffices to treat the case `Y = Aut F ⧸ U`. +For the case `Y = Aut F ⧸ U` we closely follow the second part of Stacks Project Tag 0BN4. + +-/ + +noncomputable section + +universe u₁ u₂ + +namespace CategoryTheory + +namespace PreGaloisCategory + +variable {C : Type u₁} [Category.{u₂} C] {F : C ⥤ FintypeCat.{u₁}} + +open Limits Functor + +variable [GaloisCategory C] [FiberFunctor F] + +variable {G : Type*} [Group G] [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] + +private local instance fintypeQuotient (H : OpenSubgroup (G)) : + Fintype (G ⧸ (H : Subgroup (G))) := + have : Finite (G ⧸ H.toSubgroup) := H.toSubgroup.quotient_finite_of_isOpen H.isOpen' + Fintype.ofFinite _ + +private local instance fintypeQuotientStabilizer {X : Type*} [MulAction G X] + [TopologicalSpace X] [ContinuousSMul G X] [DiscreteTopology X] (x : X) : + Fintype (G ⧸ (MulAction.stabilizer (G) x)) := + fintypeQuotient ⟨MulAction.stabilizer (G) x, stabilizer_isOpen (G) x⟩ + +/-- If `X` is a finite discrete `G`-set, it can be written as the finite disjoint union +of quotients of the form `G ⧸ Uᵢ` for open subgroups `(Uᵢ)`. Note that this +is simply the decomposition into orbits. -/ +lemma has_decomp_quotients (X : Action FintypeCat (MonCat.of G)) + [TopologicalSpace X.V] [DiscreteTopology X.V] [ContinuousSMul G X.V] : + ∃ (ι : Type) (_ : Finite ι) (f : ι → OpenSubgroup (G)), + Nonempty ((∐ fun i ↦ G ⧸ₐ (f i).toSubgroup) ≅ X) := by + obtain ⟨ι, hf, f, u, hc⟩ := has_decomp_connected_components' X + letI (i : ι) : TopologicalSpace (f i).V := ⊥ + haveI (i : ι) : DiscreteTopology (f i).V := ⟨rfl⟩ + have (i : ι) : ContinuousSMul G (f i).V := ContinuousSMul.mk <| by + let r : f i ⟶ X := Sigma.ι f i ≫ u.hom + let r'' (p : G × (f i).V) : G × X.V := (p.1, r.hom p.2) + let q (p : G × X.V) : X.V := X.ρ p.1 p.2 + let q' (p : G × (f i).V) : (f i).V := (f i).ρ p.1 p.2 + have heq : q ∘ r'' = r.hom ∘ q' := by + ext (p : G × (f i).V) + exact (congr_fun (r.comm p.1) p.2).symm + have hrinj : Function.Injective r.hom := + (ConcreteCategory.mono_iff_injective_of_preservesPullback r).mp <| mono_comp _ _ + let t₁ : TopologicalSpace (G × (f i).V) := inferInstance + show @Continuous _ _ _ ⊥ q' + have : TopologicalSpace.induced r.hom inferInstance = ⊥ := by + rw [← le_bot_iff] + exact fun s _ ↦ ⟨r.hom '' s, ⟨isOpen_discrete (r.hom '' s), Set.preimage_image_eq s hrinj⟩⟩ + rw [← this, continuous_induced_rng, ← heq] + exact Continuous.comp continuous_smul (by fun_prop) + have (i : ι) : ∃ (U : OpenSubgroup (G)), (Nonempty ((f i) ≅ G ⧸ₐ U.toSubgroup)) := by + obtain ⟨(x : (f i).V)⟩ := nonempty_fiber_of_isConnected (forget₂ _ _) (f i) + let U : OpenSubgroup (G) := ⟨MulAction.stabilizer (G) x, stabilizer_isOpen (G) x⟩ + letI : Fintype (G ⧸ MulAction.stabilizer (G) x) := fintypeQuotient U + exact ⟨U, ⟨FintypeCat.isoQuotientStabilizerOfIsConnected (f i) x⟩⟩ + choose g ui using this + exact ⟨ι, hf, g, ⟨(Sigma.mapIso (fun i ↦ (ui i).some)).symm ≪≫ u⟩⟩ + +/-- If `X` is connected and `x` is in the fiber of `X`, `F.obj X` is isomorphic +to the quotient of `Aut F` by the stabilizer of `x` as `Aut F`-sets. -/ +def fiberIsoQuotientStabilizer (X : C) [IsConnected X] (x : F.obj X) : + (functorToAction F).obj X ≅ Aut F ⧸ₐ MulAction.stabilizer (Aut F) x := + haveI : IsConnected ((functorToAction F).obj X) := PreservesIsConnected.preserves + letI : Fintype (Aut F ⧸ MulAction.stabilizer (Aut F) x) := fintypeQuotientStabilizer x + FintypeCat.isoQuotientStabilizerOfIsConnected ((functorToAction F).obj X) x + +section + +open Action.FintypeCat + +variable (V : OpenSubgroup (Aut F)) {U : OpenSubgroup (Aut F)} + (h : Subgroup.Normal U.toSubgroup) {A : C} (u : (functorToAction F).obj A ≅ Aut F ⧸ₐ U.toSubgroup) + +/- + +### Strategy outline + +Let `A` be an object of `C` with fiber `Aut F`-isomorphic to `Aut F ⧸ U` for an open normal +subgroup `U`. Then for any open subgroup `V` of `Aut F`, `V ⧸ (U ⊓ V)` acts on `A`. This +induces the diagram `quotientDiag`. Now assume `U ≤ V`. Then we can also postcompose +the diagram `quotientDiag` with `F`. The goal of this section is to compute that the colimit +of this composed diagram is `Aut F ⧸ V`. Finally, we obtain `F.obj (A ⧸ V) ≅ Aut F ⧸ V` as +`Aut F`-sets. +-/ + +private def quotientToEndObjectHom : + V.toSubgroup ⧸ Subgroup.subgroupOf U.toSubgroup V.toSubgroup →* End A := + let ff : (functorToAction F).FullyFaithful := FullyFaithful.ofFullyFaithful (functorToAction F) + let e : End A ≃* End (Aut F ⧸ₐ U.toSubgroup) := (ff.mulEquivEnd A).trans (Iso.conj u) + e.symm.toMonoidHom.comp (quotientToEndHom V.toSubgroup U.toSubgroup) + +private lemma functorToAction_map_quotientToEndObjectHom + (m : SingleObj.star (V ⧸ Subgroup.subgroupOf U.toSubgroup V.toSubgroup) ⟶ + SingleObj.star (V ⧸ Subgroup.subgroupOf U.toSubgroup V.toSubgroup)) : + (functorToAction F).map (quotientToEndObjectHom V h u m) = + u.hom ≫ quotientToEndHom V.toSubgroup U.toSubgroup m ≫ u.inv := by + simp [← cancel_epi u.inv, ← cancel_mono u.hom, ← Iso.conj_apply, quotientToEndObjectHom] + +@[simps!] +private def quotientDiag : SingleObj (V.toSubgroup ⧸ Subgroup.subgroupOf U V) ⥤ C := + SingleObj.functor (quotientToEndObjectHom V h u) + +variable {V} (hUinV : U ≤ V) + +@[simps] +private def coconeQuotientDiag : + Cocone (quotientDiag V h u ⋙ functorToAction F) where + pt := Aut F ⧸ₐ V.toSubgroup + ι := SingleObj.natTrans (u.hom ≫ quotientToQuotientOfLE V.toSubgroup U.toSubgroup hUinV) <| by + intro (m : V ⧸ Subgroup.subgroupOf U V) + simp only [const_obj_obj, Functor.comp_map, const_obj_map, Category.comp_id] + rw [← cancel_epi (u.inv), Iso.inv_hom_id_assoc] + apply Action.hom_ext + ext (x : Aut F ⧸ U.toSubgroup) + induction' m, x using Quotient.inductionOn₂ with σ μ + suffices h : ⟦μ * σ⁻¹⟧ = ⟦μ⟧ by + simp only [quotientToQuotientOfLE_hom_mk, quotientDiag_map, + functorToAction_map_quotientToEndObjectHom V _ u] + simpa + apply Quotient.sound + apply (QuotientGroup.leftRel_apply).mpr + simp + +@[simps] +private def coconeQuotientDiagDesc + (s : Cocone (quotientDiag V h u ⋙ functorToAction F)) : + (coconeQuotientDiag h u hUinV).pt ⟶ s.pt where + hom := Quotient.lift (fun σ ↦ (u.inv ≫ s.ι.app (SingleObj.star _)).hom ⟦σ⟧) <| fun σ τ hst ↦ by + let J' := quotientDiag V h u ⋙ functorToAction F + let m : End (SingleObj.star (V.toSubgroup ⧸ Subgroup.subgroupOf U V)) := + ⟦⟨σ⁻¹ * τ, (QuotientGroup.leftRel_apply).mp hst⟩⟧ + have h1 : J'.map m ≫ s.ι.app (SingleObj.star _) = s.ι.app (SingleObj.star _) := s.ι.naturality m + conv_rhs => rw [← h1] + have h2 : (J'.map m).hom (u.inv.hom ⟦τ⟧) = u.inv.hom ⟦σ⟧ := by + simp only [comp_obj, quotientDiag_obj, Functor.comp_map, quotientDiag_map, J', + functorToAction_map_quotientToEndObjectHom V h u m] + show (u.inv ≫ u.hom ≫ _ ≫ u.inv).hom ⟦τ⟧ = u.inv.hom ⟦σ⟧ + simp [m] + simp only [← h2, const_obj_obj, Action.comp_hom, FintypeCat.comp_apply] + comm g := by + ext (x : Aut F ⧸ V.toSubgroup) + induction' x using Quotient.inductionOn with σ + simp only [const_obj_obj] + show (((Aut F ⧸ₐ U.toSubgroup).ρ g ≫ u.inv.hom) ≫ (s.ι.app (SingleObj.star _)).hom) ⟦σ⟧ = + ((s.ι.app (SingleObj.star _)).hom ≫ s.pt.ρ g) (u.inv.hom ⟦σ⟧) + have : ((functorToAction F).obj A).ρ g ≫ (s.ι.app (SingleObj.star _)).hom = + (s.ι.app (SingleObj.star _)).hom ≫ s.pt.ρ g := + (s.ι.app (SingleObj.star _)).comm g + rw [← this, u.inv.comm g] + rfl + +/-- The constructed cocone `coconeQuotientDiag` on the diagram `quotientDiag` is colimiting. -/ +private def coconeQuotientDiagIsColimit : + IsColimit (coconeQuotientDiag h u hUinV) where + desc := coconeQuotientDiagDesc h u hUinV + fac s j := by + apply (cancel_epi u.inv).mp + apply Action.hom_ext + ext (x : Aut F ⧸ U.toSubgroup) + induction' x using Quotient.inductionOn with σ + simp + rfl + uniq s f hf := by + apply Action.hom_ext + ext (x : Aut F ⧸ V.toSubgroup) + induction' x using Quotient.inductionOn with σ + simp [← hf (SingleObj.star _)] + +end + +/-- For every open subgroup `V` of `Aut F`, there exists an `X : C` such that +`F.obj X ≅ Aut F ⧸ V` as `Aut F`-sets. -/ +lemma exists_lift_of_quotient_openSubgroup (V : OpenSubgroup (Aut F)) : + ∃ (X : C), Nonempty ((functorToAction F).obj X ≅ Aut F ⧸ₐ V.toSubgroup) := by + obtain ⟨I, hf, hc, hi⟩ := exists_set_ker_evaluation_subset_of_isOpen F (one_mem V) V.isOpen' + haveI (X : I) : IsConnected X.val := hc X X.property + haveI (X : I) : Nonempty (F.obj X.val) := nonempty_fiber_of_isConnected F X + have hn : Nonempty (F.obj <| (∏ᶜ fun X : I => X)) := nonempty_fiber_pi_of_nonempty_of_finite F _ + obtain ⟨A, f, hgal⟩ := exists_hom_from_galois_of_fiber_nonempty F (∏ᶜ fun X : I => X) hn + obtain ⟨a⟩ := nonempty_fiber_of_isConnected F A + let U : OpenSubgroup (Aut F) := ⟨MulAction.stabilizer (Aut F) a, stabilizer_isOpen (Aut F) a⟩ + let u := fiberIsoQuotientStabilizer A a + have hUnormal : U.toSubgroup.Normal := stabilizer_normal_of_isGalois F A a + have h1 (σ : Aut F) (σinU : σ ∈ U) : σ.hom.app A = 𝟙 (F.obj A) := by + have hi : (Aut F ⧸ₐ MulAction.stabilizer (Aut F) a).ρ σ = 𝟙 _ := by + refine FintypeCat.hom_ext _ _ (fun x ↦ ?_) + induction' x using Quotient.inductionOn with τ + show ⟦σ * τ⟧ = ⟦τ⟧ + apply Quotient.sound + apply (QuotientGroup.leftRel_apply).mpr + simp only [mul_inv_rev] + exact Subgroup.Normal.conj_mem hUnormal _ (Subgroup.inv_mem U.toSubgroup σinU) _ + simp [← cancel_mono u.hom.hom, show σ.hom.app A ≫ u.hom.hom = _ from u.hom.comm σ, hi] + have h2 (σ : Aut F) (σinU : σ ∈ U) : ∀ X : I, σ.hom.app X = 𝟙 (F.obj X) := by + intro ⟨X, hX⟩ + ext (x : F.obj X) + let p : A ⟶ X := f ≫ Pi.π (fun Z : I => (Z : C)) ⟨X, hX⟩ + have : IsConnected X := hc X hX + obtain ⟨a, rfl⟩ := surjective_of_nonempty_fiber_of_isConnected F p x + simp only [FintypeCat.id_apply, FunctorToFintypeCat.naturality, h1 σ σinU] + have hUinV : (U : Set (Aut F)) ≤ V := fun u uinU ↦ hi u (h2 u uinU) + have := V.quotient_finite_of_isOpen' (U.subgroupOf V) V.isOpen (V.subgroupOf_isOpen U U.isOpen) + exact ⟨colimit (quotientDiag V hUnormal u), + ⟨preservesColimitIso (functorToAction F) (quotientDiag V hUnormal u) ≪≫ + colimit.isoColimitCocone ⟨coconeQuotientDiag hUnormal u hUinV, + coconeQuotientDiagIsColimit hUnormal u hUinV⟩⟩⟩ + +/-- +If `X` is a finite, discrete `Aut F`-set with continuous `Aut F`-action, then +there exists `A : C` such that `F.obj A ≅ X` as `Aut F`-sets. +-/ +@[stacks 0BN4 "Essential surjectivity part"] +theorem exists_lift_of_continuous (X : Action FintypeCat (MonCat.of (Aut F))) + [TopologicalSpace X.V] [DiscreteTopology X.V] [ContinuousSMul (Aut F) X.V] : + ∃ A, Nonempty ((functorToAction F).obj A ≅ X) := by + obtain ⟨ι, hfin, f, ⟨u⟩⟩ := has_decomp_quotients X + choose g gu using (fun i ↦ exists_lift_of_quotient_openSubgroup (f i)) + exact ⟨∐ g, ⟨PreservesCoproduct.iso (functorToAction F) g ≪≫ + Sigma.mapIso (fun i ↦ (gu i).some) ≪≫ u⟩⟩ + +end PreGaloisCategory + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Galois/Full.lean b/Mathlib/CategoryTheory/Galois/Full.lean index db7f5c8139acc..4c09add2e62f9 100644 --- a/Mathlib/CategoryTheory/Galois/Full.lean +++ b/Mathlib/CategoryTheory/Galois/Full.lean @@ -42,7 +42,7 @@ namespace PreGaloisCategory open Limits Functor -variable {C : Type u} [Category.{u} C] (F : C ⥤ FintypeCat.{u}) [GaloisCategory C] [FiberFunctor F] +variable {C : Type u} [Category.{v} C] (F : C ⥤ FintypeCat.{u}) [GaloisCategory C] [FiberFunctor F] /-- Let `X` be an object of a Galois category with fiber functor `F` and `Y` a sub-`Aut F`-set diff --git a/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean b/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean index f5398eaad344f..7e9841375b05f 100644 --- a/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean +++ b/Mathlib/CategoryTheory/Galois/IsFundamentalgroup.lean @@ -219,7 +219,7 @@ variable (G : Type*) [Group G] [∀ (X : C), MulAction G (F.obj X)] /-- A compact, topological group `G` with a natural action on `F.obj X` for each `X : C` is a fundamental group of `F`, if `G` acts transitively on the fibers of Galois objects, -the action on `F.obj X` is continuous for all `X : C` and the only trivally acting element of `G` +the action on `F.obj X` is continuous for all `X : C` and the only trivially acting element of `G` is the identity. -/ class IsFundamentalGroup [TopologicalSpace G] [TopologicalGroup G] [CompactSpace G] extends IsNaturalSMul F G : Prop where diff --git a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean index e848bbc5c6d75..fba4b027d12de 100644 --- a/Mathlib/CategoryTheory/Galois/Prorepresentability.lean +++ b/Mathlib/CategoryTheory/Galois/Prorepresentability.lean @@ -373,7 +373,7 @@ lemma endMulEquivAutGalois_pi (f : End F) (A : PointedGaloisObject F) : /-- Any endomorphism of a fiber functor is a unit. -/ theorem FibreFunctor.end_isUnit (f : End F) : IsUnit f := - (MulEquiv.map_isUnit_iff (endMulEquivAutGalois F)).mp + (isUnit_map_iff (endMulEquivAutGalois F) _).mp (Group.isUnit ((endMulEquivAutGalois F) f)) /-- Any endomorphism of a fiber functor is an isomorphism. -/ diff --git a/Mathlib/CategoryTheory/Galois/Topology.lean b/Mathlib/CategoryTheory/Galois/Topology.lean index 62e4145b36bc7..06ad6569ca157 100644 --- a/Mathlib/CategoryTheory/Galois/Topology.lean +++ b/Mathlib/CategoryTheory/Galois/Topology.lean @@ -69,7 +69,7 @@ lemma autEmbedding_range : ext a simp only [Set.mem_range, id_obj, Set.mem_iInter, Set.mem_setOf_eq] refine ⟨fun ⟨σ, h⟩ i ↦ h.symm ▸ σ.hom.naturality i.hom, fun h ↦ ?_⟩ - · use NatIso.ofComponents (fun X => a X) (fun {X Y} f ↦ h ⟨X, Y, f⟩) + · use NatIso.ofComponents a (fun {X Y} f ↦ h ⟨X, Y, f⟩) rfl /-- The image of `Aut F` in `∀ X, Aut (F.obj X)` is closed. -/ diff --git a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean index 917484d456465..b005a034c6b49 100644 --- a/Mathlib/CategoryTheory/GradedObject/Monoidal.lean +++ b/Mathlib/CategoryTheory/GradedObject/Monoidal.lean @@ -325,7 +325,7 @@ lemma left_tensor_tensorObj₃_ext {j : I} {A : C} (Z : C) (_ ◁ ιTensorObj₃ X₁ X₂ X₃ i₁ i₂ i₃ j h) ≫ f = (_ ◁ ιTensorObj₃ X₁ X₂ X₃ i₁ i₂ i₃ j h) ≫ g) : f = g := by refine (@isColimitOfPreserves C _ C _ _ _ _ ((curriedTensor C).obj Z) _ - (isColimitCofan₃MapBifunctorBifunctor₂₃MapObj (H := H) j) hZ).hom_ext ?_ + (isColimitCofan₃MapBifunctorBifunctor₂₃MapObj (H := H) (j := j)) hZ).hom_ext ?_ intro ⟨⟨i₁, i₂, i₃⟩, hi⟩ exact h _ _ _ hi diff --git a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean index 1c901601ac535..b0d783ab327b1 100644 --- a/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean +++ b/Mathlib/CategoryTheory/GradedObject/Trifunctor.lean @@ -259,7 +259,7 @@ variable (F₁₂ : C₁ ⥤ C₂ ⥤ C₁₂) (G : C₁₂ ⥤ C₃ ⥤ C₄) /-- Given a map `r : I₁ × I₂ × I₃ → J`, a `BifunctorComp₁₂IndexData r` consists of the data of a type `I₁₂`, maps `p : I₁ × I₂ → I₁₂` and `q : I₁₂ × I₃ → J`, such that `r` is obtained by composition of `p` and `q`. -/ -structure BifunctorComp₁₂IndexData := +structure BifunctorComp₁₂IndexData where /-- an auxiliary type -/ I₁₂ : Type* /-- a map `I₁ × I₂ → I₁₂` -/ @@ -439,7 +439,7 @@ variable (F : C₁ ⥤ C₂₃ ⥤ C₄) (G₂₃ : C₂ ⥤ C₃ ⥤ C₂₃) /-- Given a map `r : I₁ × I₂ × I₃ → J`, a `BifunctorComp₂₃IndexData r` consists of the data of a type `I₂₃`, maps `p : I₂ × I₃ → I₂₃` and `q : I₁ × I₂₃ → J`, such that `r` is obtained by composition of `p` and `q`. -/ -structure BifunctorComp₂₃IndexData := +structure BifunctorComp₂₃IndexData where /-- an auxiliary type -/ I₂₃ : Type* /-- a map `I₂ × I₃ → I₂₃` -/ diff --git a/Mathlib/CategoryTheory/GradedObject/Unitor.lean b/Mathlib/CategoryTheory/GradedObject/Unitor.lean index 265f2b3635c67..6b90c959e367c 100644 --- a/Mathlib/CategoryTheory/GradedObject/Unitor.lean +++ b/Mathlib/CategoryTheory/GradedObject/Unitor.lean @@ -124,8 +124,8 @@ lemma mapBifunctorLeftUnitor_inv_naturality : rw [mapBifunctorLeftUnitor_inv_apply, mapBifunctorLeftUnitor_inv_apply, assoc, assoc, ι_mapBifunctorMapMap] dsimp - rw [Functor.map_id, NatTrans.id_app, id_comp] - erw [← NatTrans.naturality_assoc, ← NatTrans.naturality_assoc] + rw [Functor.map_id, NatTrans.id_app, id_comp, ← NatTrans.naturality_assoc, + ← NatTrans.naturality_assoc] rfl @[reassoc] @@ -242,7 +242,7 @@ lemma mapBifunctorRightUnitor_inv_naturality : ι_mapBifunctorMapMap] dsimp rw [Functor.map_id, id_comp, NatTrans.naturality_assoc] - erw [← NatTrans.naturality_assoc] + erw [← NatTrans.naturality_assoc e.inv] rfl @[reassoc] diff --git a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean index 54aa24e65b239..79f597c240e2e 100644 --- a/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean +++ b/Mathlib/CategoryTheory/Groupoid/FreeGroupoid.lean @@ -132,7 +132,7 @@ theorem of_eq : section UniversalProperty -variable {V' : Type u'} [Groupoid V'] (φ : V ⥤q V') +variable {V' : Type u'} [Groupoid V'] /-- The lift of a prefunctor to a groupoid, to a functor from `FreeGroupoid V` -/ def lift (φ : V ⥤q V') : FreeGroupoid V ⥤ V' := diff --git a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean index b1b1f5f30c036..aa1af4a9269f3 100644 --- a/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean +++ b/Mathlib/CategoryTheory/Idempotents/FunctorCategories.lean @@ -94,7 +94,7 @@ def obj (P : Karoubi (J ⥤ C)) : J ⥤ Karoubi C where simp only [NatTrans.naturality, assoc] have h := congr_app P.idem j rw [NatTrans.comp_app] at h - erw [reassoc_of% h, reassoc_of% h] } + rw [reassoc_of% h, reassoc_of% h] } /-- Tautological action on maps of the functor `Karoubi (J ⥤ C) ⥤ (J ⥤ Karoubi C)`. -/ @[simps] diff --git a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean index 121e9a8862368..a0cd003efe419 100644 --- a/Mathlib/CategoryTheory/Idempotents/Karoubi.lean +++ b/Mathlib/CategoryTheory/Idempotents/Karoubi.lean @@ -248,12 +248,12 @@ variable {C} /-- The split mono which appears in the factorisation `decompId P`. -/ @[simps] def decompId_i (P : Karoubi C) : P ⟶ P.X := - ⟨P.p, by erw [coe_p, comp_id, P.idem]⟩ + ⟨P.p, by rw [coe_p, comp_id, P.idem]⟩ /-- The split epi which appears in the factorisation `decompId P`. -/ @[simps] def decompId_p (P : Karoubi C) : (P.X : Karoubi C) ⟶ P := - ⟨P.p, by erw [coe_p, id_comp, P.idem]⟩ + ⟨P.p, by rw [coe_p, id_comp, P.idem]⟩ /-- The formal direct factor of `P.X` given by the idempotent `P.p` in the category `C` is actually a direct factor in the category `Karoubi C`. -/ diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean index 8d7ad6c8ea53a..af07a00e52f8d 100644 --- a/Mathlib/CategoryTheory/Iso.lean +++ b/Mathlib/CategoryTheory/Iso.lean @@ -332,7 +332,7 @@ instance id (X : C) : IsIso (𝟙 X) := ⟨⟨𝟙 X, by simp⟩⟩ @[deprecated (since := "2024-05-15")] alias of_iso := CategoryTheory.Iso.isIso_hom @[deprecated (since := "2024-05-15")] alias of_iso_inv := CategoryTheory.Iso.isIso_inv -variable {f g : X ⟶ Y} {h : Y ⟶ Z} +variable {f : X ⟶ Y} {h : Y ⟶ Z} instance inv_isIso [IsIso f] : IsIso (inv f) := (asIso f).isIso_inv @@ -419,7 +419,7 @@ open IsIso theorem eq_of_inv_eq_inv {f g : X ⟶ Y} [IsIso f] [IsIso g] (p : inv f = inv g) : f = g := by apply (cancel_epi (inv f)).1 - erw [inv_hom_id, p, inv_hom_id] + rw [inv_hom_id, p, inv_hom_id] theorem IsIso.inv_eq_inv {f g : X ⟶ Y} [IsIso f] [IsIso g] : inv f = inv g ↔ f = g := Iso.inv_eq_inv (asIso f) (asIso g) @@ -509,7 +509,7 @@ theorem cancel_iso_inv_right_assoc {W X X' Y Z : C} (f : W ⟶ X) (g : X ⟶ Y) section -variable {D E : Type*} [Category D] [Category E] {X Y : C} (e : X ≅ Y) +variable {D : Type*} [Category D] {X Y : C} (e : X ≅ Y) @[reassoc (attr := simp)] lemma map_hom_inv_id (F : C ⥤ D) : diff --git a/Mathlib/CategoryTheory/LiftingProperties/Basic.lean b/Mathlib/CategoryTheory/LiftingProperties/Basic.lean index 034992348ba84..6b3ab2bd33ac2 100644 --- a/Mathlib/CategoryTheory/LiftingProperties/Basic.lean +++ b/Mathlib/CategoryTheory/LiftingProperties/Basic.lean @@ -41,7 +41,7 @@ class HasLiftingProperty : Prop where sq_hasLift : ∀ {f : A ⟶ X} {g : B ⟶ Y} (sq : CommSq f i p g), sq.HasLift instance (priority := 100) sq_hasLift_of_hasLiftingProperty {f : A ⟶ X} {g : B ⟶ Y} - (sq : CommSq f i p g) [hip : HasLiftingProperty i p] : sq.HasLift := by apply hip.sq_hasLift + (sq : CommSq f i p g) [hip : HasLiftingProperty i p] : sq.HasLift := hip.sq_hasLift _ namespace HasLiftingProperty diff --git a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean index 48a15f47a5ca7..2ecb02a4b57c2 100644 --- a/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/ConcreteCategory/Basic.lean @@ -27,7 +27,7 @@ section Limits is corepresentable, then `(G ⋙ forget C).sections` is small. -/ lemma small_sections_of_hasLimit {C : Type u} [Category.{v} C] [ConcreteCategory.{v} C] - [(forget C).Corepresentable] {J : Type w} [Category.{t} J] (G : J ⥤ C) [HasLimit G] : + [(forget C).IsCorepresentable] {J : Type w} [Category.{t} J] (G : J ⥤ C) [HasLimit G] : Small.{v} (G ⋙ forget C).sections := by rw [← Types.hasLimit_iff_small_sections] infer_instance diff --git a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean index 305a3bbd5a648..0b2e0d72e2f6e 100644 --- a/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/FunctorCategory/Basic.lean @@ -146,18 +146,23 @@ def combinedIsColimit (F : J ⥤ K ⥤ C) (c : ∀ k : K, ColimitCocone (F.flip. noncomputable section +instance functorCategoryHasLimit (F : J ⥤ K ⥤ C) [∀ k, HasLimit (F.flip.obj k)] : HasLimit F := + HasLimit.mk + { cone := combineCones F fun _ => getLimitCone _ + isLimit := combinedIsLimit _ _ } + instance functorCategoryHasLimitsOfShape [HasLimitsOfShape J C] : HasLimitsOfShape J (K ⥤ C) where - has_limit F := - HasLimit.mk - { cone := combineCones F fun _ => getLimitCone _ - isLimit := combinedIsLimit _ _ } + has_limit _ := inferInstance + +instance functorCategoryHasColimit (F : J ⥤ K ⥤ C) [∀ k, HasColimit (F.flip.obj k)] : + HasColimit F := + HasColimit.mk + { cocone := combineCocones F fun _ => getColimitCocone _ + isColimit := combinedIsColimit _ _ } instance functorCategoryHasColimitsOfShape [HasColimitsOfShape J C] : HasColimitsOfShape J (K ⥤ C) where - has_colimit _ := - HasColimit.mk - { cocone := combineCocones _ fun _ => getColimitCocone _ - isColimit := combinedIsColimit _ _ } + has_colimit _ := inferInstance -- Porting note: previously Lean could see through the binders and infer_instance sufficed instance functorCategoryHasLimitsOfSize [HasLimitsOfSize.{v₁, u₁} C] : @@ -169,14 +174,20 @@ instance functorCategoryHasColimitsOfSize [HasColimitsOfSize.{v₁, u₁} C] : HasColimitsOfSize.{v₁, u₁} (K ⥤ C) where has_colimits_of_shape := fun _ _ => inferInstance +instance hasLimitCompEvalution (F : J ⥤ K ⥤ C) (k : K) [HasLimit (F.flip.obj k)] : + HasLimit (F ⋙ (evaluation _ _).obj k) := + hasLimitOfIso (F := F.flip.obj k) (Iso.refl _) + +instance evaluationPreservesLimit (F : J ⥤ K ⥤ C) [∀ k, HasLimit (F.flip.obj k)] (k : K) : + PreservesLimit F ((evaluation K C).obj k) := + -- Porting note: added a let because X was not inferred + let X : (k : K) → LimitCone (F.flip.obj k) := fun k => getLimitCone (F.flip.obj k) + preservesLimitOfPreservesLimitCone (combinedIsLimit _ X) <| + IsLimit.ofIsoLimit (limit.isLimit _) (evaluateCombinedCones F X k).symm + instance evaluationPreservesLimitsOfShape [HasLimitsOfShape J C] (k : K) : PreservesLimitsOfShape J ((evaluation K C).obj k) where - preservesLimit {F} := by - -- Porting note: added a let because X was not inferred - let X : (k : K) → LimitCone (Prefunctor.obj (Functor.flip F).toPrefunctor k) := - fun k => getLimitCone (Prefunctor.obj (Functor.flip F).toPrefunctor k) - exact preservesLimitOfPreservesLimitCone (combinedIsLimit _ _) <| - IsLimit.ofIsoLimit (limit.isLimit _) (evaluateCombinedCones F X k).symm + preservesLimit := inferInstance /-- If `F : J ⥤ K ⥤ C` is a functor into a functor category which has a limit, then the evaluation of that limit at `k` is the limit of the evaluations of `F.obj j` at `k`. @@ -225,14 +236,20 @@ theorem limit_obj_ext {H : J ⥤ K ⥤ C} [HasLimitsOfShape J C] {k : K} {W : C} ext j simpa using w j +instance hasColimitCompEvaluation (F : J ⥤ K ⥤ C) (k : K) [HasColimit (F.flip.obj k)] : + HasColimit (F ⋙ (evaluation _ _).obj k) := + hasColimitOfIso (F := F.flip.obj k) (Iso.refl _) + +instance evaluationPreservesColimit (F : J ⥤ K ⥤ C) [∀ k, HasColimit (F.flip.obj k)] (k : K) : + PreservesColimit F ((evaluation K C).obj k) := + -- Porting note: added a let because X was not inferred + let X : (k : K) → ColimitCocone (F.flip.obj k) := fun k => getColimitCocone (F.flip.obj k) + preservesColimitOfPreservesColimitCocone (combinedIsColimit _ X) <| + IsColimit.ofIsoColimit (colimit.isColimit _) (evaluateCombinedCocones F X k).symm + instance evaluationPreservesColimitsOfShape [HasColimitsOfShape J C] (k : K) : PreservesColimitsOfShape J ((evaluation K C).obj k) where - preservesColimit {F} := by - -- Porting note: added a let because X was not inferred - let X : (k : K) → ColimitCocone (Prefunctor.obj (Functor.flip F).toPrefunctor k) := - fun k => getColimitCocone (Prefunctor.obj (Functor.flip F).toPrefunctor k) - refine preservesColimitOfPreservesColimitCocone (combinedIsColimit _ _) <| - IsColimit.ofIsoColimit (colimit.isColimit _) (evaluateCombinedCocones F X k).symm + preservesColimit := inferInstance /-- If `F : J ⥤ K ⥤ C` is a functor into a functor category which has a colimit, then the evaluation of that colimit at `k` is the colimit of the evaluations of `F.obj j` at `k`. diff --git a/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean b/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean index 62eb96c6be392..ba9abc78c25d6 100644 --- a/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean +++ b/Mathlib/CategoryTheory/Limits/FunctorToTypes.lean @@ -20,15 +20,20 @@ open CategoryTheory.Limits universe w v₁ v₂ u₁ u₂ variable {J : Type u₁} [Category.{v₁} J] {K : Type u₂} [Category.{v₂} K] -variable (F : J ⥤ K ⥤ TypeMax.{u₁, w}) +variable (F : J ⥤ K ⥤ Type w) -theorem jointly_surjective (k : K) {t : Cocone F} (h : IsColimit t) (x : t.pt.obj k) : - ∃ j y, x = (t.ι.app j).app k y := by +theorem jointly_surjective (k : K) {t : Cocone F} (h : IsColimit t) (x : t.pt.obj k) + [∀ k, HasColimit (F.flip.obj k)] : ∃ j y, x = (t.ι.app j).app k y := by let hev := isColimitOfPreserves ((evaluation _ _).obj k) h obtain ⟨j, y, rfl⟩ := Types.jointly_surjective _ hev x exact ⟨j, y, by simp⟩ -theorem jointly_surjective' (k : K) (x : (colimit F).obj k) : ∃ j y, x = (colimit.ι F j).app k y := +theorem jointly_surjective' [∀ k, HasColimit (F.flip.obj k)] (k : K) (x : (colimit F).obj k) : + ∃ j y, x = (colimit.ι F j).app k y := jointly_surjective _ _ (colimit.isColimit _) x +theorem colimit.map_ι_apply [HasColimit F] (j : J) {k k' : K} {f : k ⟶ k'} {x} : + (colimit F).map f ((colimit.ι F j).app _ x) = (colimit.ι F j).app _ ((F.obj j).map f x) := + congrFun ((colimit.ι F j).naturality _).symm _ + end CategoryTheory.FunctorToTypes diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Finite.lean b/Mathlib/CategoryTheory/Limits/Preserves/Finite.lean index 87c35359a609f..eea8e1113af03 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Finite.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Finite.lean @@ -27,7 +27,7 @@ open CategoryTheory namespace CategoryTheory.Limits -- declare the `v`'s first; see `CategoryTheory.Category` for an explanation -universe w w₂ v₁ v₂ v₃ u₁ u₂ u₃ +universe u w w₂ v₁ v₂ v₃ u₁ u₂ u₃ variable {C : Type u₁} [Category.{v₁} C] variable {D : Type u₂} [Category.{v₂} D] @@ -84,6 +84,11 @@ def compPreservesFiniteLimits (F : C ⥤ D) (G : D ⥤ E) [PreservesFiniteLimits [PreservesFiniteLimits G] : PreservesFiniteLimits (F ⋙ G) := ⟨fun _ _ _ => inferInstance⟩ +/-- Transfer preservation of finite limits along a natural isomorphism in the functor. -/ +def preservesFiniteLimitsOfNatIso {F G : C ⥤ D} (h : F ≅ G) [PreservesFiniteLimits F] : + PreservesFiniteLimits G where + preservesFiniteLimits _ _ _ := preservesLimitsOfShapeOfNatIso h + /- Porting note: adding this class because quantified classes don't behave well [#2764](https://github.com/leanprover-community/mathlib4/pull/2764) -/ /-- A functor `F` preserves finite products if it preserves all from `Discrete J` @@ -93,6 +98,12 @@ class PreservesFiniteProducts (F : C ⥤ D) where attribute [instance] PreservesFiniteProducts.preserves +noncomputable instance (priority := 100) (F : C ⥤ D) (J : Type u) [Finite J] + [PreservesFiniteProducts F] : PreservesLimitsOfShape (Discrete J) F := by + apply Nonempty.some + obtain ⟨n, ⟨e⟩⟩ := Finite.exists_equiv_fin J + exact ⟨preservesLimitsOfShapeOfEquiv (Discrete.equivalence e.symm) F⟩ + instance compPreservesFiniteProducts (F : C ⥤ D) (G : D ⥤ E) [PreservesFiniteProducts F] [PreservesFiniteProducts G] : PreservesFiniteProducts (F ⋙ G) where @@ -225,6 +236,11 @@ def compPreservesFiniteColimits (F : C ⥤ D) (G : D ⥤ E) [PreservesFiniteColi [PreservesFiniteColimits G] : PreservesFiniteColimits (F ⋙ G) := ⟨fun _ _ _ => inferInstance⟩ +/-- Transfer preservation of finite colimits along a natural isomorphism in the functor. -/ +def preservesFiniteColimitsOfNatIso {F G : C ⥤ D} (h : F ≅ G) [PreservesFiniteColimits F] : + PreservesFiniteColimits G where + preservesFiniteColimits _ _ _ := preservesColimitsOfShapeOfNatIso h + /- Porting note: adding this class because quantified classes don't behave well [#2764](https://github.com/leanprover-community/mathlib4/pull/2764) -/ /-- A functor `F` preserves finite products if it preserves all from `Discrete J` @@ -233,14 +249,15 @@ class PreservesFiniteCoproducts (F : C ⥤ D) where /-- preservation of colimits indexed by `Discrete J` when `[Fintype J]` -/ preserves : ∀ (J : Type) [Fintype J], PreservesColimitsOfShape (Discrete J) F -noncomputable instance (F : C ⥤ D) (J : Type*) [Finite J] [PreservesFiniteCoproducts F] : - PreservesColimitsOfShape (Discrete J) F := by +attribute [instance] PreservesFiniteCoproducts.preserves + +noncomputable instance (priority := 100) (F : C ⥤ D) (J : Type u) [Finite J] + [PreservesFiniteCoproducts F] : PreservesColimitsOfShape (Discrete J) F := by apply Nonempty.some obtain ⟨n, ⟨e⟩⟩ := Finite.exists_equiv_fin J - have : PreservesColimitsOfShape (Discrete (Fin n)) F := PreservesFiniteCoproducts.preserves _ exact ⟨preservesColimitsOfShapeOfEquiv (Discrete.equivalence e.symm) F⟩ -noncomputable instance compPreservesFiniteCoproducts (F : C ⥤ D) (G : D ⥤ E) +instance compPreservesFiniteCoproducts (F : C ⥤ D) (G : D ⥤ E) [PreservesFiniteCoproducts F] [PreservesFiniteCoproducts G] : PreservesFiniteCoproducts (F ⋙ G) where preserves _ _ := inferInstance @@ -248,7 +265,6 @@ noncomputable instance compPreservesFiniteCoproducts (F : C ⥤ D) (G : D ⥤ E) noncomputable instance (F : C ⥤ D) [PreservesFiniteColimits F] : PreservesFiniteCoproducts F where preserves _ _ := inferInstance - /-- A functor is said to reflect finite colimits, if it reflects all colimits of shape `J`, where `J : Type` is a finite category. diff --git a/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean b/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean index 4b4cde050f773..0d33dbbf72e5a 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/FunctorCategory.lean @@ -5,6 +5,7 @@ Authors: Bhavik Mehta -/ import Mathlib.CategoryTheory.Limits.FunctorCategory.Basic import Mathlib.CategoryTheory.Limits.Preserves.Shapes.BinaryProducts +import Mathlib.CategoryTheory.Limits.Preserves.Finite import Mathlib.CategoryTheory.Limits.Yoneda import Mathlib.CategoryTheory.Limits.Presheaf @@ -104,4 +105,16 @@ noncomputable def preservesLimitOfLanPreservesLimit {C D : Type u} [SmallCategor apply @preservesLimitsOfShapeOfReflectsOfPreserves _ _ _ _ _ _ _ _ F yoneda ?_ exact preservesLimitsOfShapeOfNatIso (Presheaf.compYonedaIsoYonedaCompLan F).symm +/-- `F : C ⥤ D ⥤ E` preserves finite limits if it does for each `d : D`. -/ +def preservesFiniteLimitsOfEvaluation {D : Type*} [Category D] {E : Type*} [Category E] + (F : C ⥤ D ⥤ E) (h : ∀ d : D, PreservesFiniteLimits (F ⋙ (evaluation D E).obj d)) : + PreservesFiniteLimits F := + ⟨fun J _ _ => preservesLimitsOfShapeOfEvaluation F J fun k => (h k).preservesFiniteLimits _⟩ + +/-- `F : C ⥤ D ⥤ E` preserves finite limits if it does for each `d : D`. -/ +def preservesFiniteColimitsOfEvaluation {D : Type*} [Category D] {E : Type*} [Category E] + (F : C ⥤ D ⥤ E) (h : ∀ d : D, PreservesFiniteColimits (F ⋙ (evaluation D E).obj d)) : + PreservesFiniteColimits F := + ⟨fun J _ _ => preservesColimitsOfShapeOfEvaluation F J fun k => (h k).preservesFiniteColimits _⟩ + end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean b/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean index 37599d523f5f6..10c785ddbe059 100644 --- a/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean +++ b/Mathlib/CategoryTheory/Limits/Preserves/Limits.lean @@ -148,10 +148,10 @@ def preservesColimitNatIso : colim ⋙ G ≅ (whiskeringRight J C D).obj G ⋙ c rw [← Iso.inv_comp_eq, ← Category.assoc, ← Iso.eq_comp_inv] apply colimit.hom_ext; intro j dsimp - erw [ι_colimMap_assoc] + rw [ι_colimMap_assoc] simp only [ι_preservesColimitsIso_inv, whiskerRight_app, Category.assoc, ι_preservesColimitsIso_inv_assoc, ← G.map_comp] - erw [ι_colimMap]) + rw [ι_colimMap]) end diff --git a/Mathlib/CategoryTheory/Limits/Presheaf.lean b/Mathlib/CategoryTheory/Limits/Presheaf.lean index d7b3844ba9d24..8dd0215926fc0 100644 --- a/Mathlib/CategoryTheory/Limits/Presheaf.lean +++ b/Mathlib/CategoryTheory/Limits/Presheaf.lean @@ -202,8 +202,7 @@ noncomputable def coconeOfRepresentable (P : Cᵒᵖ ⥤ Type v₁) : { app := fun x => yonedaEquiv.symm x.unop.2 naturality := fun {x₁ x₂} f => by dsimp - rw [comp_id] - erw [← yonedaEquiv_symm_map] + rw [comp_id, ← yonedaEquiv_symm_map] congr 1 rw [f.unop.2] } diff --git a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean index 4ea865a6b1d0d..1c442221fe532 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/BinaryProducts.lean @@ -29,9 +29,7 @@ braiding and associating isomorphisms, and the product comparison morphism. -/ -noncomputable section - -universe v u u₂ +universe v v₁ u u₁ u₂ open CategoryTheory @@ -48,8 +46,12 @@ open WalkingPair /-- The equivalence swapping left and right. -/ def WalkingPair.swap : WalkingPair ≃ WalkingPair where - toFun j := WalkingPair.recOn j right left - invFun j := WalkingPair.recOn j right left + toFun j := match j with + | left => right + | right => left + invFun j := match j with + | left => right + | right => left left_inv j := by cases j; repeat rfl right_inv j := by cases j; repeat rfl @@ -72,7 +74,9 @@ theorem WalkingPair.swap_symm_apply_ff : WalkingPair.swap.symm right = left := /-- An equivalence from `WalkingPair` to `Bool`, sometimes useful when reindexing limits. -/ def WalkingPair.equivBool : WalkingPair ≃ Bool where - toFun j := WalkingPair.recOn j true false + toFun j := match j with + | left => true + | right => false -- to match equiv.sum_equiv_sigma_bool invFun b := Bool.recOn b right left left_inv j := by cases j; repeat rfl @@ -132,7 +136,9 @@ attribute [local aesop safe tactic (rule_sets := [CategoryTheory])] /-- The natural transformation between two functors out of the walking pair, specified by its components. -/ def mapPair : F ⟶ G where - app j := Discrete.recOn j fun j => WalkingPair.casesOn j f g + app j := match j with + | ⟨left⟩ => f + | ⟨right⟩ => g naturality := fun ⟨X⟩ ⟨Y⟩ ⟨⟨u⟩⟩ => by aesop_cat @[simp] @@ -147,7 +153,9 @@ theorem mapPair_right : (mapPair f g).app ⟨right⟩ = g := components. -/ @[simps!] def mapPairIso (f : F.obj ⟨left⟩ ≅ G.obj ⟨left⟩) (g : F.obj ⟨right⟩ ≅ G.obj ⟨right⟩) : F ≅ G := - NatIso.ofComponents (fun j => Discrete.recOn j fun j => WalkingPair.casesOn j f g) + NatIso.ofComponents (fun j ↦ match j with + | ⟨left⟩ => f + | ⟨right⟩ => g) (fun ⟨⟨u⟩⟩ => by aesop_cat) end @@ -160,7 +168,7 @@ def diagramIsoPair (F : Discrete WalkingPair ⥤ C) : section -variable {D : Type u} [Category.{v} D] +variable {D : Type u₁} [Category.{v₁} D] /-- The natural isomorphism between `pair X Y ⋙ F` and `pair (F.obj X) (F.obj Y)`. -/ def pairComp (X Y : C) (F : C ⥤ D) : pair X Y ⋙ F ≅ pair (F.obj X) (F.obj Y) := @@ -461,12 +469,12 @@ abbrev HasBinaryCoproduct (X Y : C) := /-- If we have a product of `X` and `Y`, we can access it using `prod X Y` or `X ⨯ Y`. -/ -abbrev prod (X Y : C) [HasBinaryProduct X Y] := +noncomputable abbrev prod (X Y : C) [HasBinaryProduct X Y] := limit (pair X Y) /-- If we have a coproduct of `X` and `Y`, we can access it using `coprod X Y` or `X ⨿ Y`. -/ -abbrev coprod (X Y : C) [HasBinaryCoproduct X Y] := +noncomputable abbrev coprod (X Y : C) [HasBinaryCoproduct X Y] := colimit (pair X Y) /-- Notation for the product -/ @@ -476,23 +484,23 @@ notation:20 X " ⨯ " Y:20 => prod X Y notation:20 X " ⨿ " Y:20 => coprod X Y /-- The projection map to the first component of the product. -/ -abbrev prod.fst {X Y : C} [HasBinaryProduct X Y] : X ⨯ Y ⟶ X := +noncomputable abbrev prod.fst {X Y : C} [HasBinaryProduct X Y] : X ⨯ Y ⟶ X := limit.π (pair X Y) ⟨WalkingPair.left⟩ /-- The projection map to the second component of the product. -/ -abbrev prod.snd {X Y : C} [HasBinaryProduct X Y] : X ⨯ Y ⟶ Y := +noncomputable abbrev prod.snd {X Y : C} [HasBinaryProduct X Y] : X ⨯ Y ⟶ Y := limit.π (pair X Y) ⟨WalkingPair.right⟩ /-- The inclusion map from the first component of the coproduct. -/ -abbrev coprod.inl {X Y : C} [HasBinaryCoproduct X Y] : X ⟶ X ⨿ Y := +noncomputable abbrev coprod.inl {X Y : C} [HasBinaryCoproduct X Y] : X ⟶ X ⨿ Y := colimit.ι (pair X Y) ⟨WalkingPair.left⟩ /-- The inclusion map from the second component of the coproduct. -/ -abbrev coprod.inr {X Y : C} [HasBinaryCoproduct X Y] : Y ⟶ X ⨿ Y := +noncomputable abbrev coprod.inr {X Y : C} [HasBinaryCoproduct X Y] : Y ⟶ X ⨿ Y := colimit.ι (pair X Y) ⟨WalkingPair.right⟩ /-- The binary fan constructed from the projection maps is a limit. -/ -def prodIsProd (X Y : C) [HasBinaryProduct X Y] : +noncomputable def prodIsProd (X Y : C) [HasBinaryProduct X Y] : IsLimit (BinaryFan.mk (prod.fst : X ⨯ Y ⟶ X) prod.snd) := (limit.isLimit _).ofIsoLimit (Cones.ext (Iso.refl _) (fun ⟨u⟩ => by cases u @@ -501,7 +509,7 @@ def prodIsProd (X Y : C) [HasBinaryProduct X Y] : )) /-- The binary cofan constructed from the coprojection maps is a colimit. -/ -def coprodIsCoprod (X Y : C) [HasBinaryCoproduct X Y] : +noncomputable def coprodIsCoprod (X Y : C) [HasBinaryCoproduct X Y] : IsColimit (BinaryCofan.mk (coprod.inl : X ⟶ X ⨿ Y) coprod.inr) := (colimit.isColimit _).ofIsoColimit (Cocones.ext (Iso.refl _) (fun ⟨u⟩ => by cases u @@ -521,20 +529,22 @@ theorem coprod.hom_ext {W X Y : C} [HasBinaryCoproduct X Y] {f g : X ⨿ Y ⟶ W /-- If the product of `X` and `Y` exists, then every pair of morphisms `f : W ⟶ X` and `g : W ⟶ Y` induces a morphism `prod.lift f g : W ⟶ X ⨯ Y`. -/ -abbrev prod.lift {W X Y : C} [HasBinaryProduct X Y] (f : W ⟶ X) (g : W ⟶ Y) : W ⟶ X ⨯ Y := +noncomputable abbrev prod.lift {W X Y : C} [HasBinaryProduct X Y] + (f : W ⟶ X) (g : W ⟶ Y) : W ⟶ X ⨯ Y := limit.lift _ (BinaryFan.mk f g) /-- diagonal arrow of the binary product in the category `fam I` -/ -abbrev diag (X : C) [HasBinaryProduct X X] : X ⟶ X ⨯ X := +noncomputable abbrev diag (X : C) [HasBinaryProduct X X] : X ⟶ X ⨯ X := prod.lift (𝟙 _) (𝟙 _) /-- If the coproduct of `X` and `Y` exists, then every pair of morphisms `f : X ⟶ W` and `g : Y ⟶ W` induces a morphism `coprod.desc f g : X ⨿ Y ⟶ W`. -/ -abbrev coprod.desc {W X Y : C} [HasBinaryCoproduct X Y] (f : X ⟶ W) (g : Y ⟶ W) : X ⨿ Y ⟶ W := +noncomputable abbrev coprod.desc {W X Y : C} [HasBinaryCoproduct X Y] + (f : X ⟶ W) (g : Y ⟶ W) : X ⨿ Y ⟶ W := colimit.desc _ (BinaryCofan.mk f g) /-- codiagonal arrow of the binary coproduct -/ -abbrev codiag (X : C) [HasBinaryCoproduct X X] : X ⨿ X ⟶ X := +noncomputable abbrev codiag (X : C) [HasBinaryCoproduct X X] : X ⨿ X ⟶ X := coprod.desc (𝟙 _) (𝟙 _) -- Porting note (#10618): simp removes as simp can prove this @@ -581,30 +591,30 @@ instance coprod.epi_desc_of_epi_right {W X Y : C} [HasBinaryCoproduct X Y] (f : /-- If the product of `X` and `Y` exists, then every pair of morphisms `f : W ⟶ X` and `g : W ⟶ Y` induces a morphism `l : W ⟶ X ⨯ Y` satisfying `l ≫ Prod.fst = f` and `l ≫ Prod.snd = g`. -/ -def prod.lift' {W X Y : C} [HasBinaryProduct X Y] (f : W ⟶ X) (g : W ⟶ Y) : +noncomputable def prod.lift' {W X Y : C} [HasBinaryProduct X Y] (f : W ⟶ X) (g : W ⟶ Y) : { l : W ⟶ X ⨯ Y // l ≫ prod.fst = f ∧ l ≫ prod.snd = g } := ⟨prod.lift f g, prod.lift_fst _ _, prod.lift_snd _ _⟩ /-- If the coproduct of `X` and `Y` exists, then every pair of morphisms `f : X ⟶ W` and `g : Y ⟶ W` induces a morphism `l : X ⨿ Y ⟶ W` satisfying `coprod.inl ≫ l = f` and `coprod.inr ≫ l = g`. -/ -def coprod.desc' {W X Y : C} [HasBinaryCoproduct X Y] (f : X ⟶ W) (g : Y ⟶ W) : +noncomputable def coprod.desc' {W X Y : C} [HasBinaryCoproduct X Y] (f : X ⟶ W) (g : Y ⟶ W) : { l : X ⨿ Y ⟶ W // coprod.inl ≫ l = f ∧ coprod.inr ≫ l = g } := ⟨coprod.desc f g, coprod.inl_desc _ _, coprod.inr_desc _ _⟩ /-- If the products `W ⨯ X` and `Y ⨯ Z` exist, then every pair of morphisms `f : W ⟶ Y` and `g : X ⟶ Z` induces a morphism `prod.map f g : W ⨯ X ⟶ Y ⨯ Z`. -/ -def prod.map {W X Y Z : C} [HasBinaryProduct W X] [HasBinaryProduct Y Z] (f : W ⟶ Y) (g : X ⟶ Z) : - W ⨯ X ⟶ Y ⨯ Z := +noncomputable def prod.map {W X Y Z : C} [HasBinaryProduct W X] [HasBinaryProduct Y Z] + (f : W ⟶ Y) (g : X ⟶ Z) : W ⨯ X ⟶ Y ⨯ Z := limMap (mapPair f g) /-- If the coproducts `W ⨿ X` and `Y ⨿ Z` exist, then every pair of morphisms `f : W ⟶ Y` and `g : W ⟶ Z` induces a morphism `coprod.map f g : W ⨿ X ⟶ Y ⨿ Z`. -/ -def coprod.map {W X Y Z : C} [HasBinaryCoproduct W X] [HasBinaryCoproduct Y Z] (f : W ⟶ Y) - (g : X ⟶ Z) : W ⨿ X ⟶ Y ⨿ Z := +noncomputable def coprod.map {W X Y Z : C} [HasBinaryCoproduct W X] [HasBinaryCoproduct Y Z] + (f : W ⟶ Y) (g : X ⟶ Z) : W ⨿ X ⟶ Y ⨿ Z := colimMap (mapPair f g) -section ProdLemmas +noncomputable section ProdLemmas -- Making the reassoc version of this a simp lemma seems to be more harmful than helpful. @[reassoc, simp] @@ -706,7 +716,7 @@ instance {X : C} [HasBinaryProduct X X] : IsSplitMono (diag X) := end ProdLemmas -section CoprodLemmas +noncomputable section CoprodLemmas -- @[reassoc (attr := simp)] @[simp] -- Porting note: removing reassoc tag since result is not hygienic (two h's) @@ -847,7 +857,7 @@ theorem hasBinaryCoproducts_of_hasColimit_pair [∀ {X Y : C}, HasColimit (pair HasBinaryCoproducts C := { has_colimit := fun F => hasColimitOfIso (diagramIsoPair F) } -section +noncomputable section variable {C} @@ -938,7 +948,7 @@ theorem prod.triangle [HasBinaryProducts C] (X Y : C) : end -section +noncomputable section variable {C} variable [HasBinaryCoproducts C] @@ -1001,7 +1011,7 @@ theorem coprod.triangle (X Y : C) : end -section ProdFunctor +noncomputable section ProdFunctor -- Porting note (#10754): added category instance as it did not propagate variable {C} [Category.{v} C] [HasBinaryProducts C] @@ -1022,7 +1032,7 @@ def prod.functorLeftComp (X Y : C) : end ProdFunctor -section CoprodFunctor +noncomputable section CoprodFunctor -- Porting note (#10754): added category instance as it did not propagate variable {C} [Category.{v} C] [HasBinaryCoproducts C] @@ -1042,7 +1052,7 @@ def coprod.functorLeftComp (X Y : C) : end CoprodFunctor -section ProdComparison +noncomputable section ProdComparison universe w w' u₃ @@ -1126,7 +1136,7 @@ theorem prodComparison_comp : end ProdComparison -section CoprodComparison +noncomputable section CoprodComparison universe w @@ -1208,13 +1218,15 @@ variable {C : Type u} [Category.{v} C] /-- Auxiliary definition for `Over.coprod`. -/ @[simps] -def Over.coprodObj [HasBinaryCoproducts C] {A : C} : Over A → Over A ⥤ Over A := fun f => +noncomputable def Over.coprodObj [HasBinaryCoproducts C] {A : C} : + Over A → Over A ⥤ Over A := + fun f => { obj := fun g => Over.mk (coprod.desc f.hom g.hom) map := fun k => Over.homMk (coprod.map (𝟙 _) k.left) } /-- A category with binary coproducts has a functorial `sup` operation on over categories. -/ @[simps] -def Over.coprod [HasBinaryCoproducts C] {A : C} : Over A ⥤ Over A ⥤ Over A where +noncomputable def Over.coprod [HasBinaryCoproducts C] {A : C} : Over A ⥤ Over A ⥤ Over A where obj f := Over.coprodObj f map k := { app := fun g => Over.homMk (coprod.map k.left (𝟙 _)) (by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean index dbb941df4e33f..7a16ef661d0bf 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Biproducts.lean @@ -403,6 +403,14 @@ instance (priority := 100) hasFiniteCoproducts_of_hasFiniteBiproducts [HasFinite HasFiniteCoproducts C where out _ := ⟨fun _ => hasColimitOfIso Discrete.natIsoFunctor⟩ +instance (priority := 100) hasProductsOfShape_of_hasBiproductsOfShape [HasBiproductsOfShape J C] : + HasProductsOfShape J C where + has_limit _ := hasLimitOfIso Discrete.natIsoFunctor.symm + +instance (priority := 100) hasCoproductsOfShape_of_hasBiproductsOfShape [HasBiproductsOfShape J C] : + HasCoproductsOfShape J C where + has_colimit _ := hasColimitOfIso Discrete.natIsoFunctor + variable {C} /-- The isomorphism between the specified limit and the specified colimit for @@ -547,6 +555,17 @@ theorem biproduct.isoCoproduct_hom {f : J → C} [HasBiproduct f] : (biproduct.isoCoproduct f).hom = biproduct.desc (Sigma.ι f) := biproduct.hom_ext' _ _ fun j => by simp [← Iso.eq_comp_inv] +/-- If a category has biproducts of a shape `J`, its `colim` and `lim` functor on diagrams over `J` +are isomorphic. -/ +@[simps!] +def HasBiproductsOfShape.colimIsoLim [HasBiproductsOfShape J C] : + colim (J := Discrete J) (C := C) ≅ lim := + NatIso.ofComponents (fun F => (Sigma.isoColimit F).symm ≪≫ + (biproduct.isoCoproduct _).symm ≪≫ biproduct.isoProduct _ ≪≫ Pi.isoLimit F) + fun η => colimit.hom_ext fun ⟨i⟩ => limit.hom_ext fun ⟨j⟩ => by + by_cases h : i = j <;> + simp_all [h, Sigma.isoColimit, Pi.isoLimit, biproduct.ι_π, biproduct.ι_π_assoc] + theorem biproduct.map_eq_map' {f g : J → C} [HasBiproduct f] [HasBiproduct g] (p : ∀ b, f b ⟶ g b) : biproduct.map p = biproduct.map' p := by ext @@ -840,7 +859,7 @@ def kernelForkBiproductToSubtype (p : Set K) : ext j k simp only [Category.assoc, biproduct.ι_fromSubtype_assoc, biproduct.ι_toSubtype_assoc, comp_zero, zero_comp] - erw [dif_neg k.2] + rw [dif_neg k.2] simp only [zero_comp]) isLimit := KernelFork.IsLimit.ofι _ _ (fun {W} g _ => g ≫ biproduct.toSubtype f pᶜ) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean index 22aa87a4a18cd..10e2d68009de0 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Images.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Images.lean @@ -81,8 +81,6 @@ attribute [reassoc (attr := simp)] MonoFactorisation.fac attribute [instance] MonoFactorisation.m_mono -attribute [instance] MonoFactorisation.m_mono - namespace MonoFactorisation /-- The obvious factorisation of a monomorphism through itself. -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean index c05a2ec92eaab..b829a05e80be7 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean @@ -79,7 +79,7 @@ variable {f} @[reassoc (attr := simp)] theorem KernelFork.condition (s : KernelFork f) : Fork.ι s ≫ f = 0 := by - erw [Fork.condition, HasZeroMorphisms.comp_zero] + rw [Fork.condition, HasZeroMorphisms.comp_zero] -- Porting note (#10618): simp can prove this, removed simp tag theorem KernelFork.app_one (s : KernelFork f) : s.π.app one = 0 := by @@ -435,7 +435,7 @@ def kernel.zeroKernelFork : KernelFork f where def kernel.isLimitConeZeroCone [Mono f] : IsLimit (kernel.zeroKernelFork f) := Fork.IsLimit.mk _ (fun s => 0) (fun s => by - erw [zero_comp] + rw [zero_comp] refine (zero_of_comp_mono f ?_).symm exact KernelFork.condition _) fun _ _ _ => zero_of_to_zero _ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean index e0595886fe9d9..aa816cb1ee4da 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Products.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Products.lean @@ -481,6 +481,50 @@ from a family of isomorphisms between the factors. abbrev Sigma.mapIso {f g : β → C} [HasCoproductsOfShape β C] (p : ∀ b, f b ≅ g b) : ∐ f ≅ ∐ g := colim.mapIso (Discrete.natIso fun X => p X.as) +section + +/- In this section, we provide some API for coproducts when we are given a functor +`Discrete α ⥤ C` instead of a map `α → C`. -/ + +variable (X : Discrete α ⥤ C) [HasCoproduct (fun j => X.obj (Discrete.mk j))] + +/-- A colimit cocone for `X : Discrete α ⥤ C` that is given +by `∐ (fun j => X.obj (Discrete.mk j))`. -/ +@[simps] +def Sigma.cocone : Cocone X where + pt := ∐ (fun j => X.obj (Discrete.mk j)) + ι := Discrete.natTrans (fun _ => Sigma.ι (fun j ↦ X.obj ⟨j⟩) _) + +/-- The cocone `Sigma.cocone X` is a colimit cocone. -/ +def coproductIsCoproduct' : + IsColimit (Sigma.cocone X) where + desc s := Sigma.desc (fun j => s.ι.app ⟨j⟩) + fac s := by simp + uniq s m hm := by + dsimp + ext + simp only [colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app] + apply hm + +variable [HasColimit X] + +/-- The isomorphism `∐ (fun j => X.obj (Discrete.mk j)) ≅ colimit X`. -/ +def Sigma.isoColimit : + ∐ (fun j => X.obj (Discrete.mk j)) ≅ colimit X := + IsColimit.coconePointUniqueUpToIso (coproductIsCoproduct' X) (colimit.isColimit X) + +@[reassoc (attr := simp)] +lemma Sigma.ι_isoColimit_hom (j : α) : + Sigma.ι _ j ≫ (Sigma.isoColimit X).hom = colimit.ι _ (Discrete.mk j) := + IsColimit.comp_coconePointUniqueUpToIso_hom (coproductIsCoproduct' X) _ _ + +@[reassoc (attr := simp)] +lemma Sigma.ι_isoColimit_inv (j : α) : + colimit.ι _ ⟨j⟩ ≫ (Sigma.isoColimit X).inv = Sigma.ι (fun j ↦ X.obj ⟨j⟩) _ := + IsColimit.comp_coconePointUniqueUpToIso_inv _ _ _ + +end + /-- Two products which differ by an equivalence in the indexing type, and up to isomorphism in the factors, are isomorphic. -/ diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean index e22ae9d2d8bed..423fed53f4080 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/CommSq.lean @@ -280,22 +280,22 @@ noncomputable def isoIsPullback (h : IsPullback fst snd f g) (h' : IsPullback fs @[reassoc (attr := simp)] theorem isoIsPullback_hom_fst (h : IsPullback fst snd f g) (h' : IsPullback fst' snd' f g) : - (h.isoIsPullback h').hom ≫ fst' = fst := + (h.isoIsPullback _ _ h').hom ≫ fst' = fst := IsLimit.conePointUniqueUpToIso_hom_comp h.isLimit h'.isLimit WalkingCospan.left @[reassoc (attr := simp)] theorem isoIsPullback_hom_snd (h : IsPullback fst snd f g) (h' : IsPullback fst' snd' f g) : - (h.isoIsPullback h').hom ≫ snd' = snd := + (h.isoIsPullback _ _ h').hom ≫ snd' = snd := IsLimit.conePointUniqueUpToIso_hom_comp h.isLimit h'.isLimit WalkingCospan.right @[reassoc (attr := simp)] theorem isoIsPullback_inv_fst (h : IsPullback fst snd f g) (h' : IsPullback fst' snd' f g) : - (h.isoIsPullback h').inv ≫ fst = fst' := by + (h.isoIsPullback _ _ h').inv ≫ fst = fst' := by simp only [Iso.inv_comp_eq, isoIsPullback_hom_fst] @[reassoc (attr := simp)] theorem isoIsPullback_inv_snd (h : IsPullback fst snd f g) (h' : IsPullback fst' snd' f g) : - (h.isoIsPullback h').inv ≫ snd = snd' := by + (h.isoIsPullback _ _ h').inv ≫ snd = snd' := by simp only [Iso.inv_comp_eq, isoIsPullback_hom_snd] end @@ -468,22 +468,22 @@ noncomputable def isoIsPushout (h : IsPushout f g inl inr) (h' : IsPushout f g i @[reassoc (attr := simp)] theorem inl_isoIsPushout_hom (h : IsPushout f g inl inr) (h' : IsPushout f g inl' inr') : - inl ≫ (h.isoIsPushout h').hom = inl' := + inl ≫ (h.isoIsPushout _ _ h').hom = inl' := IsColimit.comp_coconePointUniqueUpToIso_hom h.isColimit h'.isColimit WalkingSpan.left @[reassoc (attr := simp)] theorem inr_isoIsPushout_hom (h : IsPushout f g inl inr) (h' : IsPushout f g inl' inr') : - inr ≫ (h.isoIsPushout h').hom = inr' := + inr ≫ (h.isoIsPushout _ _ h').hom = inr' := IsColimit.comp_coconePointUniqueUpToIso_hom h.isColimit h'.isColimit WalkingSpan.right @[reassoc (attr := simp)] theorem inl_isoIsPushout_inv (h : IsPushout f g inl inr) (h' : IsPushout f g inl' inr') : - inl' ≫ (h.isoIsPushout h').inv = inl := by + inl' ≫ (h.isoIsPushout _ _ h').inv = inl := by simp only [Iso.comp_inv_eq, inl_isoIsPushout_hom] @[reassoc (attr := simp)] theorem inr_isoIsPushout_inv (h : IsPushout f g inl inr) (h' : IsPushout f g inl' inr') : - inr' ≫ (h.isoIsPushout h').inv = inr := by + inr' ≫ (h.isoIsPushout _ _ h').inv = inr := by simp only [Iso.comp_inv_eq, inr_isoIsPushout_hom] end diff --git a/Mathlib/CategoryTheory/Limits/Types.lean b/Mathlib/CategoryTheory/Limits/Types.lean index cfa274313257e..b67691c5eca11 100644 --- a/Mathlib/CategoryTheory/Limits/Types.lean +++ b/Mathlib/CategoryTheory/Limits/Types.lean @@ -632,7 +632,7 @@ instance : HasImageMaps (Type u) where have p := st.w replace p := congr_fun p (Classical.choose x.2) simp only [Functor.id_obj, Functor.id_map, types_comp_apply] at p - erw [p, Classical.choose_spec x.2]⟩⟩) rfl + rw [p, Classical.choose_spec x.2]⟩⟩) rfl variable {F : ℕᵒᵖ ⥤ Type u} {c : Cone F} (hc : IsLimit c) (hF : ∀ n, Function.Surjective (F.map (homOfLE (Nat.le_succ n)).op)) diff --git a/Mathlib/CategoryTheory/Limits/VanKampen.lean b/Mathlib/CategoryTheory/Limits/VanKampen.lean index fc1ab0865d6d2..429dea9a1687b 100644 --- a/Mathlib/CategoryTheory/Limits/VanKampen.lean +++ b/Mathlib/CategoryTheory/Limits/VanKampen.lean @@ -701,7 +701,7 @@ theorem isVanKampenColimit_extendCofan {n : ℕ} (f : Fin (n + 1) → C) rotate_left · ext ⟨j⟩ dsimp - erw [colimit.ι_desc] -- Why? + rw [colimit.ι_desc] rfl simpa [Functor.const_obj_obj, Discrete.functor_obj, extendCofan_pt, extendCofan_ι_app, Fin.cases_succ, BinaryCofan.mk_pt, colimit.cocone_x, Cofan.mk_pt, Cofan.mk_ι_app, diff --git a/Mathlib/CategoryTheory/Limits/Yoneda.lean b/Mathlib/CategoryTheory/Limits/Yoneda.lean index 26ac00460355a..2442748a1c2e5 100644 --- a/Mathlib/CategoryTheory/Limits/Yoneda.lean +++ b/Mathlib/CategoryTheory/Limits/Yoneda.lean @@ -193,7 +193,7 @@ namespace Functor section Representable -variable (F : Cᵒᵖ ⥤ Type v) [F.Representable] {J : Type*} [Category J] +variable (F : Cᵒᵖ ⥤ Type v) [F.IsRepresentable] {J : Type*} [Category J] noncomputable instance representablePreservesLimit (G : J ⥤ Cᵒᵖ) : PreservesLimit G F := @@ -210,7 +210,7 @@ end Representable section Corepresentable -variable (F : C ⥤ Type v) [F.Corepresentable] {J : Type*} [Category J] +variable (F : C ⥤ Type v) [F.IsCorepresentable] {J : Type*} [Category J] noncomputable instance corepresentablePreservesLimit (G : J ⥤ C) : PreservesLimit G F := diff --git a/Mathlib/CategoryTheory/Linear/Yoneda.lean b/Mathlib/CategoryTheory/Linear/Yoneda.lean index 4836d3c76a695..ee468da7d7708 100644 --- a/Mathlib/CategoryTheory/Linear/Yoneda.lean +++ b/Mathlib/CategoryTheory/Linear/Yoneda.lean @@ -28,7 +28,7 @@ namespace CategoryTheory variable (R : Type w) [Ring R] {C : Type u} [Category.{v} C] [Preadditive C] [Linear R C] variable (C) --- Porting note: inserted specific `ModuleCat.ofHom` in the definition of `linearYoneda` +-- Porting note: inserted specific `ModuleCat.asHom` in the definition of `linearYoneda` -- and similarly in `linearCoyoneda`, otherwise many simp lemmas are not triggered automatically. -- Eventually, doing so allows more proofs to be automatic! /-- The Yoneda embedding for `R`-linear categories `C`, @@ -38,9 +38,9 @@ with value on `Y : Cᵒᵖ` given by `ModuleCat.of R (unop Y ⟶ X)`. -/ def linearYoneda : C ⥤ Cᵒᵖ ⥤ ModuleCat R where obj X := { obj := fun Y => ModuleCat.of R (unop Y ⟶ X) - map := fun f => ModuleCat.ofHom (Linear.leftComp R _ f.unop) } + map := fun f => ModuleCat.asHom (Linear.leftComp R _ f.unop) } map {X₁ X₂} f := - { app := fun Y => @ModuleCat.ofHom R _ (Y.unop ⟶ X₁) (Y.unop ⟶ X₂) _ _ _ _ + { app := fun Y => @ModuleCat.asHom R _ (Y.unop ⟶ X₁) (Y.unop ⟶ X₂) _ _ _ _ (Linear.rightComp R _ f) } /-- The Yoneda embedding for `R`-linear categories `C`, @@ -50,9 +50,9 @@ with value on `X : C` given by `ModuleCat.of R (unop Y ⟶ X)`. -/ def linearCoyoneda : Cᵒᵖ ⥤ C ⥤ ModuleCat R where obj Y := { obj := fun X => ModuleCat.of R (unop Y ⟶ X) - map := fun f => ModuleCat.ofHom (Linear.rightComp R _ f) } + map := fun f => ModuleCat.asHom (Linear.rightComp R _ f) } map {Y₁ Y₂} f := - { app := fun X => @ModuleCat.ofHom R _ (unop Y₁ ⟶ X) (unop Y₂ ⟶ X) _ _ _ _ + { app := fun X => @ModuleCat.asHom R _ (unop Y₁ ⟶ X) (unop Y₂ ⟶ X) _ _ _ _ (Linear.leftComp _ _ f.unop) } instance linearYoneda_obj_additive (X : C) : ((linearYoneda R C).obj X).Additive where diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean index a46ca7ab8e22f..07d49115d1bb7 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions.lean @@ -500,7 +500,7 @@ lemma homMk_comp_homMk {X Y Z : C} (z₁ : W.LeftFraction X Y) (z₂ : W.LeftFra (z₃ : W.LeftFraction z₁.Y' z₂.Y') (h₃ : z₂.f ≫ z₃.s = z₁.s ≫ z₃.f) : homMk z₁ ≫ homMk z₂ = homMk (z₁.comp₀ z₂ z₃) := by change Hom.comp _ _ = _ - erw [Hom.comp_eq, comp_eq z₁ z₂ z₃ h₃] + rw [Hom.comp_eq, comp_eq z₁ z₂ z₃ h₃] lemma homMk_eq_of_leftFractionRel {X Y : C} (z₁ z₂ : W.LeftFraction X Y) (h : LeftFractionRel z₁ z₂) : diff --git a/Mathlib/CategoryTheory/Localization/LocalizerMorphism.lean b/Mathlib/CategoryTheory/Localization/LocalizerMorphism.lean index c0f59f13389ca..a0c71108f57aa 100644 --- a/Mathlib/CategoryTheory/Localization/LocalizerMorphism.lean +++ b/Mathlib/CategoryTheory/Localization/LocalizerMorphism.lean @@ -128,7 +128,7 @@ lemma isEquivalence_iff : G.IsEquivalence ↔ G'.IsEquivalence := end /-- Condition that a `LocalizerMorphism` induces an equivalence on the localized categories -/ -class IsLocalizedEquivalence : Prop := +class IsLocalizedEquivalence : Prop where /-- the induced functor on the constructed localized categories is an equivalence -/ isEquivalence : (Φ.localizedFunctor W₁.Q W₂.Q).IsEquivalence diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean index aa27e2567dea6..bb6cb9ad83759 100644 --- a/Mathlib/CategoryTheory/Localization/SmallHom.lean +++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean @@ -249,11 +249,7 @@ lemma equiv_smallHomMap (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ have hγ : ∀ (X : C₁), γ.hom.app (W₁.Q.obj X) = E₂.map (β.inv.app X) ≫ α₂.hom.app (Φ.functor.obj X) ≫ e.hom.app X ≫ G.map (α₁.inv.app X) := fun X ↦ by - dsimp [γ] - rw [liftNatTrans_app] - dsimp - rw [id_comp, id_comp, comp_id] - erw [id_comp, comp_id] + simp [γ, id_comp, comp_id] simp only [Functor.map_comp, assoc] erw [← NatIso.naturality_1 γ] simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α₁.hom.app X)), diff --git a/Mathlib/CategoryTheory/Monad/Kleisli.lean b/Mathlib/CategoryTheory/Monad/Kleisli.lean index 7b0bfe3c11446..1bea86e9b33ad 100644 --- a/Mathlib/CategoryTheory/Monad/Kleisli.lean +++ b/Mathlib/CategoryTheory/Monad/Kleisli.lean @@ -75,7 +75,7 @@ def fromKleisli : Kleisli T ⥤ C where -- Porting note: hack for missing unfold_projs tactic change T.map (f ≫ T.map g ≫ T.μ.app Z) ≫ T.μ.app Z = _ simp only [Functor.map_comp, Category.assoc] - erw [← T.μ.naturality_assoc g, T.assoc] + rw [← T.μ.naturality_assoc g, T.assoc] rfl /-- The Kleisli adjunction which gives rise to the monad `(T, η_ T, μ_ T)`. @@ -159,7 +159,7 @@ def adj : fromCokleisli U ⊣ toCokleisli U := homEquiv_naturality_right := fun {X} {Y} {_} f g => by -- Porting note: working around lack of unfold_projs change f ≫ g = U.δ.app X ≫ U.map f ≫ U.ε.app Y ≫ g - erw [← Category.assoc (U.map f), U.ε.naturality]; dsimp + rw [← Category.assoc (U.map f), U.ε.naturality]; dsimp simp only [← Category.assoc, Comonad.left_counit, Category.id_comp] } /-- The composition of the adjunction gives the original functor. -/ diff --git a/Mathlib/CategoryTheory/Monoidal/Category.lean b/Mathlib/CategoryTheory/Monoidal/Category.lean index c38de64d692f4..d80764aa71802 100644 --- a/Mathlib/CategoryTheory/Monoidal/Category.lean +++ b/Mathlib/CategoryTheory/Monoidal/Category.lean @@ -3,6 +3,7 @@ Copyright (c) 2018 Michael Jendrusch. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Jendrusch, Kim Morrison, Bhavik Mehta, Jakob von Raumer -/ +import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Functor.Trifunctor import Mathlib.CategoryTheory.Products.Basic diff --git a/Mathlib/CategoryTheory/Monoidal/Functor.lean b/Mathlib/CategoryTheory/Monoidal/Functor.lean index 1cd5fbc682a6c..1581d1d32ba35 100644 --- a/Mathlib/CategoryTheory/Monoidal/Functor.lean +++ b/Mathlib/CategoryTheory/Monoidal/Functor.lean @@ -309,6 +309,27 @@ noncomputable def MonoidalFunctor.toOplaxMonoidalFunctor (F : MonoidalFunctor C rw [← F.map_comp, Iso.hom_inv_id, F.map_id] simp } +/-- Construct a (strong) monoidal functor out of an oplax monoidal functor whose tensorators and +unitors are isomorphisms -/ +@[simps] +noncomputable def MonoidalFunctor.fromOplaxMonoidalFunctor (F : OplaxMonoidalFunctor C D) + [IsIso F.η] [∀ (X Y : C), IsIso (F.δ X Y)] : MonoidalFunctor C D := + { F with + ε := inv F.η + μ := fun X Y => inv (F.δ X Y) + associativity := by + intro X Y Z + rw [← inv_whiskerRight, IsIso.inv_comp_eq, IsIso.inv_comp_eq] + simp + left_unitality := by + intro X + rw [← inv_whiskerRight, ← IsIso.inv_comp_eq] + simp + right_unitality := by + intro X + rw [← inv_whiskerLeft, ← IsIso.inv_comp_eq] + simp } + end open MonoidalCategory diff --git a/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean b/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean index 5395fd61f0a08..813049284961d 100644 --- a/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean +++ b/Mathlib/CategoryTheory/Monoidal/OfHasFiniteProducts.lean @@ -297,13 +297,13 @@ def Functor.toMonoidalFunctorOfHasFiniteProducts : MonoidalFunctor C D where dsimp simp only [prod.map_map_assoc, IsIso.hom_inv_id, Category.comp_id, prod.map_id_id, Category.id_comp, IsIso.eq_inv_comp] - erw [prod.map_snd, Category.comp_id, prodComparison_snd] + rw [prod.map_snd, Category.comp_id, prodComparison_snd] right_unitality X := by rw [← cancel_epi (prod.map (𝟙 (F.obj X)) (terminalComparison F))] dsimp simp only [prod.map_map_assoc, Category.comp_id, IsIso.hom_inv_id, prod.map_id_id, Category.id_comp, IsIso.eq_inv_comp] - erw [prod.map_fst, Category.comp_id, prodComparison_fst] + rw [prod.map_fst, Category.comp_id, prodComparison_fst] instance [F.IsEquivalence] : F.toMonoidalFunctorOfHasFiniteProducts.IsEquivalence := by assumption diff --git a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean index ffeef6490f80e..0a3a382da8016 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Basic.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Basic.lean @@ -13,8 +13,11 @@ import Mathlib.Order.CompleteBooleanAlgebra We provide the basic framework for talking about properties of morphisms. The following meta-property is defined -* `RespectsIso`: `P` respects isomorphisms if `P f → P (e ≫ f)` and `P f → P (f ≫ e)`, where - `e` is an isomorphism. +* `RespectsLeft P Q`: `P` respects the property `Q` on the left if `P f → P (i ≫ f)` where + `i` satisfies `Q`. +* `RespectsRight P Q`: `P` respects the property `Q` on the right if `P f → P (f ≫ i)` where + `i` satisfies `Q`. +* `Respects`: `P` respects `Q` if `P` respects `Q` both on the left and on the right. -/ @@ -93,22 +96,79 @@ lemma monotone_map (F : C ⥤ D) : intro P Q h X Y f ⟨X', Y', f', hf', ⟨e⟩⟩ exact ⟨X', Y', f', h _ hf', ⟨e⟩⟩ -/-- A morphism property `RespectsIso` if it still holds when composed with an isomorphism -/ -class RespectsIso (P : MorphismProperty C) : Prop where - precomp {X Y Z} (e : X ≅ Y) (f : Y ⟶ Z) (hf : P f) : P (e.hom ≫ f) - postcomp {X Y Z} (e : Y ≅ Z) (f : X ⟶ Y) (hf : P f) : P (f ≫ e.hom) +/-- A morphism property `P` satisfies `P.RespectsRight Q` if it is stable under post-composition +with morphisms satisfying `Q`, i.e. whenever `P` holds for `f` and `Q` holds for `i` then `P` +holds for `f ≫ i`. -/ +class RespectsRight (P Q : MorphismProperty C) : Prop where + postcomp {X Y Z : C} (i : Y ⟶ Z) (hi : Q i) (f : X ⟶ Y) (hf : P f) : P (f ≫ i) -instance RespectsIso.op (P : MorphismProperty C) [h : RespectsIso P] : RespectsIso P.op := - ⟨fun e f hf => h.2 e.unop f.unop hf, fun e f hf => h.1 e.unop f.unop hf⟩ +/-- A morphism property `P` satisfies `P.RespectsLeft Q` if it is stable under +pre-composition with morphisms satisfying `Q`, i.e. whenever `P` holds for `f` +and `Q` holds for `i` then `P` holds for `i ≫ f`. -/ +class RespectsLeft (P Q : MorphismProperty C) : Prop where + precomp {X Y Z : C} (i : X ⟶ Y) (hi : Q i) (f : Y ⟶ Z) (hf : P f) : P (i ≫ f) -instance RespectsIso.unop (P : MorphismProperty Cᵒᵖ) [h : RespectsIso P] : RespectsIso P.unop := - ⟨fun e f hf => h.2 e.op f.op hf, fun e f hf => h.1 e.op f.op hf⟩ +/-- A morphism property `P` satisfies `P.Respects Q` if it is stable under composition on the +left and right by morphisms satisfying `Q`. -/ +class Respects (P Q : MorphismProperty C) extends P.RespectsLeft Q, P.RespectsRight Q : Prop where -/-- The intersection of two isomorphism respecting morphism properties respects isomorphisms. -/ -instance RespectsIso.inf (P Q : MorphismProperty C) [RespectsIso P] [RespectsIso Q] : - RespectsIso (P ⊓ Q) where - precomp e f hf := ⟨RespectsIso.precomp e f hf.left, RespectsIso.precomp e f hf.right⟩ - postcomp e f hf := ⟨RespectsIso.postcomp e f hf.left, RespectsIso.postcomp e f hf.right⟩ +instance (P Q : MorphismProperty C) [P.RespectsLeft Q] [P.RespectsRight Q] : P.Respects Q where + +instance (P Q : MorphismProperty C) [P.RespectsLeft Q] : P.op.RespectsRight Q.op where + postcomp i hi f hf := RespectsLeft.precomp (Q := Q) i.unop hi f.unop hf + +instance (P Q : MorphismProperty C) [P.RespectsRight Q] : P.op.RespectsLeft Q.op where + precomp i hi f hf := RespectsRight.postcomp (Q := Q) i.unop hi f.unop hf + +instance RespectsLeft.inf (P₁ P₂ Q : MorphismProperty C) [P₁.RespectsLeft Q] + [P₂.RespectsLeft Q] : (P₁ ⊓ P₂).RespectsLeft Q where + precomp i hi f hf := ⟨precomp i hi f hf.left, precomp i hi f hf.right⟩ + +instance RespectsRight.inf (P₁ P₂ Q : MorphismProperty C) [P₁.RespectsRight Q] + [P₂.RespectsRight Q] : (P₁ ⊓ P₂).RespectsRight Q where + postcomp i hi f hf := ⟨postcomp i hi f hf.left, postcomp i hi f hf.right⟩ + +variable (C) + +/-- The `MorphismProperty C` satisfied by isomorphisms in `C`. -/ +def isomorphisms : MorphismProperty C := fun _ _ f => IsIso f + +/-- The `MorphismProperty C` satisfied by monomorphisms in `C`. -/ +def monomorphisms : MorphismProperty C := fun _ _ f => Mono f + +/-- The `MorphismProperty C` satisfied by epimorphisms in `C`. -/ +def epimorphisms : MorphismProperty C := fun _ _ f => Epi f + +section + +variable {C} + +/-- `P` respects isomorphisms, if it respects the morphism property `isomorphisms C`, i.e. +it is stable under pre- and postcomposition with isomorphisms. -/ +abbrev RespectsIso (P : MorphismProperty C) : Prop := P.Respects (isomorphisms C) + +lemma RespectsIso.mk (P : MorphismProperty C) + (hprecomp : ∀ {X Y Z : C} (e : X ≅ Y) (f : Y ⟶ Z) (_ : P f), P (e.hom ≫ f)) + (hpostcomp : ∀ {X Y Z : C} (e : Y ≅ Z) (f : X ⟶ Y) (_ : P f), P (f ≫ e.hom)) : + P.RespectsIso where + precomp e (_ : IsIso e) f hf := hprecomp (asIso e) f hf + postcomp e (_ : IsIso e) f hf := hpostcomp (asIso e) f hf + +lemma RespectsIso.precomp (P : MorphismProperty C) [P.RespectsIso] {X Y Z : C} (e : X ⟶ Y) + [IsIso e] (f : Y ⟶ Z) (hf : P f) : P (e ≫ f) := + RespectsLeft.precomp (Q := isomorphisms C) e ‹IsIso e› f hf + +lemma RespectsIso.postcomp (P : MorphismProperty C) [P.RespectsIso] {X Y Z : C} (e : Y ⟶ Z) + [IsIso e] (f : X ⟶ Y) (hf : P f) : P (f ≫ e) := + RespectsRight.postcomp (Q := isomorphisms C) e ‹IsIso e› f hf + +instance RespectsIso.op (P : MorphismProperty C) [RespectsIso P] : RespectsIso P.op where + precomp e (_ : IsIso e) f hf := postcomp P e.unop f.unop hf + postcomp e (_ : IsIso e) f hf := precomp P e.unop f.unop hf + +instance RespectsIso.unop (P : MorphismProperty Cᵒᵖ) [RespectsIso P] : RespectsIso P.unop where + precomp e (_ : IsIso e) f hf := postcomp P e.op f.op hf + postcomp e (_ : IsIso e) f hf := precomp P e.op f.op hf /-- The closure by isomorphisms of a `MorphismProperty` -/ def isoClosure (P : MorphismProperty C) : MorphismProperty C := @@ -119,10 +179,10 @@ lemma le_isoClosure (P : MorphismProperty C) : P ≤ P.isoClosure := instance isoClosure_respectsIso (P : MorphismProperty C) : RespectsIso P.isoClosure where - precomp := fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', - ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ e.symm) (asIso iso.hom.right) (by simp)⟩⟩ - postcomp := fun e f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', - ⟨Arrow.isoMk (asIso iso.hom.left) (asIso iso.hom.right ≪≫ e) (by simp)⟩⟩ + precomp := fun e (he : IsIso e) f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', + ⟨Arrow.isoMk (asIso iso.hom.left ≪≫ asIso (inv e)) (asIso iso.hom.right) (by simp)⟩⟩ + postcomp := fun e (he : IsIso e) f ⟨_, _, f', hf', ⟨iso⟩⟩ => ⟨_, _, f', hf', + ⟨Arrow.isoMk (asIso iso.hom.left) (asIso iso.hom.right ≪≫ asIso e) (by simp)⟩⟩ lemma monotone_isoClosure : Monotone (isoClosure (C := C)) := by intro P Q h X Y f ⟨X', Y', f', hf', ⟨e⟩⟩ @@ -130,11 +190,11 @@ lemma monotone_isoClosure : Monotone (isoClosure (C := C)) := by theorem cancel_left_of_respectsIso (P : MorphismProperty C) [hP : RespectsIso P] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso f] : P (f ≫ g) ↔ P g := - ⟨fun h => by simpa using hP.1 (asIso f).symm (f ≫ g) h, hP.1 (asIso f) g⟩ + ⟨fun h => by simpa using RespectsIso.precomp P (inv f) (f ≫ g) h, RespectsIso.precomp P f g⟩ theorem cancel_right_of_respectsIso (P : MorphismProperty C) [hP : RespectsIso P] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [IsIso g] : P (f ≫ g) ↔ P f := - ⟨fun h => by simpa using hP.2 (asIso g).symm (f ≫ g) h, hP.2 (asIso g) f⟩ + ⟨fun h => by simpa using RespectsIso.postcomp P (inv g) (f ≫ g) h, RespectsIso.postcomp P g f⟩ theorem arrow_iso_iff (P : MorphismProperty C) [RespectsIso P] {f g : Arrow C} (e : f ≅ g) : P f.hom ↔ P g.hom := by @@ -146,16 +206,13 @@ theorem arrow_mk_iso_iff (P : MorphismProperty C) [RespectsIso P] {W X Y Z : C} P.arrow_iso_iff e theorem RespectsIso.of_respects_arrow_iso (P : MorphismProperty C) - (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P := by - constructor - · intro X Y Z e f hf - refine hP (Arrow.mk f) (Arrow.mk (e.hom ≫ f)) (Arrow.isoMk e.symm (Iso.refl _) ?_) hf - dsimp - simp only [Iso.inv_hom_id_assoc, Category.comp_id] - · intro X Y Z e f hf - refine hP (Arrow.mk f) (Arrow.mk (f ≫ e.hom)) (Arrow.isoMk (Iso.refl _) e ?_) hf - dsimp - simp only [Category.id_comp] + (hP : ∀ (f g : Arrow C) (_ : f ≅ g) (_ : P f.hom), P g.hom) : RespectsIso P where + precomp {X Y Z} e (he : IsIso e) f hf := by + refine hP (Arrow.mk f) (Arrow.mk (e ≫ f)) (Arrow.isoMk (asIso (inv e)) (Iso.refl _) ?_) hf + simp + postcomp {X Y Z} e (he : IsIso e) f hf := by + refine hP (Arrow.mk f) (Arrow.mk (f ≫ e)) (Arrow.isoMk (Iso.refl _) (asIso e) ?_) hf + simp lemma isoClosure_eq_iff (P : MorphismProperty C) : P.isoClosure = P ↔ P.RespectsIso := by @@ -227,12 +284,11 @@ lemma map_map (P : MorphismProperty C) (F : C ⥤ D) {E : Type*} [Category E] (G exact map_mem_map _ _ _ (map_mem_map _ _ _ hf) instance RespectsIso.inverseImage (P : MorphismProperty D) [RespectsIso P] (F : C ⥤ D) : - RespectsIso (P.inverseImage F) := by - constructor - all_goals - intro X Y Z e f hf - simpa [MorphismProperty.inverseImage, cancel_left_of_respectsIso, - cancel_right_of_respectsIso] using hf + RespectsIso (P.inverseImage F) where + precomp {X Y Z} e (he : IsIso e) f hf := by + simpa [MorphismProperty.inverseImage, cancel_left_of_respectsIso] using hf + postcomp {X Y Z} e (he : IsIso e) f hf := by + simpa [MorphismProperty.inverseImage, cancel_right_of_respectsIso] using hf lemma map_eq_of_iso (P : MorphismProperty C) {F G : C ⥤ D} (e : F ≅ G) : P.map F = P.map G := by @@ -275,17 +331,7 @@ lemma inverseImage_map_eq_of_isEquivalence erw [((P.map F).inverseImage_equivalence_inverse_eq_map_functor (F.asEquivalence)), map_map, P.map_eq_of_iso F.asEquivalence.unitIso.symm, map_id] - -variable (C) - -/-- The `MorphismProperty C` satisfied by isomorphisms in `C`. -/ -def isomorphisms : MorphismProperty C := fun _ _ f => IsIso f - -/-- The `MorphismProperty C` satisfied by monomorphisms in `C`. -/ -def monomorphisms : MorphismProperty C := fun _ _ f => Mono f - -/-- The `MorphismProperty C` satisfied by epimorphisms in `C`. -/ -def epimorphisms : MorphismProperty C := fun _ _ f => Epi f +end section @@ -313,21 +359,21 @@ theorem epimorphisms.infer_property [hf : Epi f] : (epimorphisms C) f := end instance RespectsIso.monomorphisms : RespectsIso (monomorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [monomorphisms.iff] intro apply mono_comp instance RespectsIso.epimorphisms : RespectsIso (epimorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [epimorphisms.iff] intro apply epi_comp instance RespectsIso.isomorphisms : RespectsIso (isomorphisms C) := by - constructor <;> + apply RespectsIso.mk <;> · intro X Y Z e f simp only [isomorphisms.iff] intro diff --git a/Mathlib/CategoryTheory/MorphismProperty/Composition.lean b/Mathlib/CategoryTheory/MorphismProperty/Composition.lean index 056a5add8631c..aff2f87e7acc0 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Composition.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Composition.lean @@ -24,7 +24,7 @@ namespace MorphismProperty variable {C : Type u} [Category.{v} C] {D : Type u'} [Category.{v'} D] /-- Typeclass expressing that a morphism property contain identities. -/ -class ContainsIdentities (W : MorphismProperty C) : Prop := +class ContainsIdentities (W : MorphismProperty C) : Prop where /-- for all `X : C`, the identity of `X` satisfies the morphism property -/ id_mem : ∀ (X : C), W (𝟙 X) @@ -63,7 +63,7 @@ instance Pi.containsIdentities {J : Type w} {C : J → Type u} /-- A morphism property satisfies `IsStableUnderComposition` if the composition of two such morphisms still falls in the class. -/ -class IsStableUnderComposition (P : MorphismProperty C) : Prop := +class IsStableUnderComposition (P : MorphismProperty C) : Prop where comp_mem {X Y Z} (f : X ⟶ Y) (g : Y ⟶ Z) : P f → P g → P (f ≫ g) lemma comp_mem (W : MorphismProperty C) [W.IsStableUnderComposition] @@ -91,9 +91,9 @@ theorem StableUnderInverse.unop {P : MorphismProperty Cᵒᵖ} (h : StableUnderI theorem respectsIso_of_isStableUnderComposition {P : MorphismProperty C} [P.IsStableUnderComposition] (hP : isomorphisms C ≤ P) : - RespectsIso P := - ⟨fun _ _ hf => P.comp_mem _ _ (hP _ (isomorphisms.infer_property _)) hf, - fun _ _ hf => P.comp_mem _ _ hf (hP _ (isomorphisms.infer_property _))⟩ + RespectsIso P := RespectsIso.mk _ + (fun _ _ hf => P.comp_mem _ _ (hP _ (isomorphisms.infer_property _)) hf) + (fun _ _ hf => P.comp_mem _ _ hf (hP _ (isomorphisms.infer_property _))) instance IsStableUnderComposition.inverseImage {P : MorphismProperty D} [P.IsStableUnderComposition] (F : C ⥤ D) : (P.inverseImage F).IsStableUnderComposition where @@ -129,7 +129,7 @@ end naturalityProperty /-- A morphism property is multiplicative if it contains identities and is stable by composition. -/ class IsMultiplicative (W : MorphismProperty C) - extends W.ContainsIdentities, W.IsStableUnderComposition : Prop := + extends W.ContainsIdentities, W.IsStableUnderComposition : Prop namespace IsMultiplicative diff --git a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean index e41f911a77318..7352e3fdd289a 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Limits.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Limits.lean @@ -190,7 +190,7 @@ abbrev IsStableUnderProductsOfShape (J : Type*) := W.IsStableUnderLimitsOfShape lemma IsStableUnderProductsOfShape.mk (J : Type*) [W.RespectsIso] [HasProductsOfShape J C] (hW : ∀ (X₁ X₂ : J → C) (f : ∀ j, X₁ j ⟶ X₂ j) (_ : ∀ (j : J), W (f j)), - W (Pi.map f)) : W.IsStableUnderProductsOfShape J := by + W (Limits.Pi.map f)) : W.IsStableUnderProductsOfShape J := by intro X₁ X₂ c₁ c₂ hc₁ hc₂ f hf let φ := fun j => f.app (Discrete.mk j) have hf' := hW _ _ φ (fun j => hf (Discrete.mk j)) @@ -203,7 +203,7 @@ lemma IsStableUnderProductsOfShape.mk (J : Type*) simp /-- The condition that a property of morphisms is stable by finite products. -/ -class IsStableUnderFiniteProducts : Prop := +class IsStableUnderFiniteProducts : Prop where isStableUnderProductsOfShape (J : Type) [Finite J] : W.IsStableUnderProductsOfShape J lemma isStableUnderProductsOfShape_of_isStableUnderFiniteProducts @@ -225,7 +225,7 @@ theorem diagonal_iff {X Y : C} {f : X ⟶ Y} : P.diagonal f ↔ P (pullback.diag Iff.rfl instance RespectsIso.diagonal [P.RespectsIso] : P.diagonal.RespectsIso := by - constructor + apply RespectsIso.mk · introv H rwa [diagonal_iff, pullback.diagonal_comp, P.cancel_left_of_respectsIso, P.cancel_left_of_respectsIso, ← P.cancel_right_of_respectsIso _ @@ -260,7 +260,7 @@ def universally (P : MorphismProperty C) : MorphismProperty C := fun X Y f => ∀ ⦃X' Y' : C⦄ (i₁ : X' ⟶ X) (i₂ : Y' ⟶ Y) (f' : X' ⟶ Y') (_ : IsPullback f' i₁ i₂ f), P f' instance universally_respectsIso (P : MorphismProperty C) : P.universally.RespectsIso := by - constructor + apply RespectsIso.mk · intro X Y Z e f hf X' Z' i₁ i₂ f' H have : IsPullback (𝟙 _) (i₁ ≫ e.hom) i₁ e.inv := IsPullback.of_horiz_isIso diff --git a/Mathlib/CategoryTheory/MorphismProperty/Representable.lean b/Mathlib/CategoryTheory/MorphismProperty/Representable.lean index ba9ba8a06a053..e2ff92296f5c9 100644 --- a/Mathlib/CategoryTheory/MorphismProperty/Representable.lean +++ b/Mathlib/CategoryTheory/MorphismProperty/Representable.lean @@ -12,7 +12,7 @@ import Mathlib.CategoryTheory.MorphismProperty.Limits In this file we define and develop basic results about relatively representable morphisms. -Classically, a morphism `f : X ⟶ Y` of presheaves is said to be representable if for any morphism +Classically, a morphism `f : F ⟶ G` of presheaves is said to be representable if for any morphism `g : yoneda.obj X ⟶ G`, there exists a pullback square of the following form ``` yoneda.obj Y --yoneda.map snd--> yoneda.obj X @@ -25,16 +25,14 @@ Classically, a morphism `f : X ⟶ Y` of presheaves is said to be representable In this file, we define a notion of relative representability which works with respect to any functor, and not just `yoneda`. The fact that a morphism `f : F ⟶ G` between presheaves is -representable in the classical case will then be given by `yoneda.relativelyRepresentable f`. - - - +representable in the classical case will then be given by `F.relativelyRepresentable f`. +` ## Main definitions Throughout this file, `F : C ⥤ D` is a functor between categories `C` and `D`. -* We define `relativelyRepresentable` as a `MorphismProperty`. A morphism `f : X ⟶ Y` in `D` is - said to be relatively representable with respect to `F`, if for any `g : F.obj a ⟶ Y`, there - exists a pullback square of the following form +* `Functor.relativelyRepresentable`: A morphism `f : X ⟶ Y` in `D` is said to be relatively + representable with respect to `F`, if for any `g : F.obj a ⟶ Y`, there exists a pullback square + of the following form ``` F.obj b --F.map snd--> F.obj a | | @@ -44,6 +42,10 @@ Throughout this file, `F : C ⥤ D` is a functor between categories `C` and `D`. X ------- f --------> Y ``` +* `MorphismProperty.relative`: Given a morphism property `P` in `C`, a morphism `f : X ⟶ Y` in `D` + satisfies `P.relative F` if it is relatively representable and for any `g : F.obj a ⟶ Y`, the + property `P` holds for any represented pullback of `f` by `g`. + ## API Given `hf : relativelyRepresentable f`, with `f : X ⟶ Y` and `g : F.obj a ⟶ Y`, we provide: @@ -259,7 +261,8 @@ end /-- When `C` has pullbacks, then `F.map f` is representable with respect to `F` for any `f : a ⟶ b` in `C`. -/ -lemma map [Full F] [PreservesLimitsOfShape WalkingCospan F] [HasPullbacks C] {a b : C} (f : a ⟶ b) : +lemma map [Full F] [HasPullbacks C] {a b : C} (f : a ⟶ b) + [∀ c (g : c ⟶ b), PreservesLimit (cospan f g) F] : F.relativelyRepresentable (F.map f) := fun c g ↦ by obtain ⟨g, rfl⟩ := F.map_surjective g refine ⟨Limits.pullback f g, Limits.pullback.snd f g, F.map (Limits.pullback.fst f g), ?_⟩ @@ -280,12 +283,95 @@ instance isMultiplicative : IsMultiplicative F.relativelyRepresentable where lemma stableUnderBaseChange : StableUnderBaseChange F.relativelyRepresentable := by intro X Y Y' X' f g f' g' P₁ hg a h refine ⟨hg.pullback (h ≫ f), hg.snd (h ≫ f), ?_, ?_⟩ - apply P₁.lift (hg.fst (h ≫ f)) (F.map (hg.snd (h ≫ f)) ≫ h) (by simpa using hg.w (h ≫ f)) - apply IsPullback.of_right' (hg.isPullback (h ≫ f)) P₁ + · apply P₁.lift (hg.fst (h ≫ f)) (F.map (hg.snd (h ≫ f)) ≫ h) (by simpa using hg.w (h ≫ f)) + · apply IsPullback.of_right' (hg.isPullback (h ≫ f)) P₁ instance respectsIso : RespectsIso F.relativelyRepresentable := (stableUnderBaseChange F).respectsIso end Functor.relativelyRepresentable +namespace MorphismProperty + +open Functor.relativelyRepresentable + +variable {X Y : D} (P : MorphismProperty C) + +/-- Given a morphism property `P` in a category `C`, a functor `F : C ⥤ D` and a morphism +`f : X ⟶ Y` in `D`. Then `f` satisfies the morphism property `P.relative` with respect to `F` iff: +* The morphism is representable with respect to `F` +* For any morphism `g : F.obj a ⟶ Y`, the property `P` holds for any represented pullback of + `f` by `g`. -/ +def relative : MorphismProperty D := + fun X Y f ↦ F.relativelyRepresentable f ∧ + ∀ ⦃a b : C⦄ (g : F.obj a ⟶ Y) (fst : F.obj b ⟶ X) (snd : b ⟶ a) + (_ : IsPullback fst (F.map snd) f g), P snd + +/-- Given a morphism property `P` in a category `C`, a morphism `f : F ⟶ G` of presheaves in the +category `Cᵒᵖ ⥤ Type v` satisfies the morphism property `P.presheaf` iff: +* The morphism is representable. +* For any morphism `g : F.obj a ⟶ G`, the property `P` holds for any represented pullback of + `f` by `g`. + +This is implemented as a special case of the more general notion of `P.relative`, to the case when +the functor `F` is `yoneda`. -/ +abbrev presheaf : MorphismProperty (Cᵒᵖ ⥤ Type v₁) := P.relative yoneda + +variable {P} {F} + +/-- A morphism satisfying `P.relative` is representable. -/ +lemma relative.rep {f : X ⟶ Y} (hf : P.relative F f) : F.relativelyRepresentable f := + hf.1 + +lemma relative.property {f : X ⟶ Y} (hf : P.relative F f) : + ∀ ⦃a b : C⦄ (g : F.obj a ⟶ Y) (fst : F.obj b ⟶ X) (snd : b ⟶ a) + (_ : IsPullback fst (F.map snd) f g), P snd := + hf.2 + +lemma relative.property_snd {f : X ⟶ Y} (hf : P.relative F f) {a : C} (g : F.obj a ⟶ Y) : + P (hf.rep.snd g) := + hf.property g _ _ (hf.rep.isPullback g) + +/-- Given a morphism property `P` which respects isomorphisms, then to show that a morphism +`f : X ⟶ Y` satisfies `P.relative` it suffices to show that: +* The morphism is representable. +* For any morphism `g : F.obj a ⟶ G`, the property `P` holds for *some* represented pullback +of `f` by `g`. -/ +lemma relative.of_exists [F.Faithful] [F.Full] [P.RespectsIso] {f : X ⟶ Y} + (h₀ : ∀ ⦃a : C⦄ (g : F.obj a ⟶ Y), ∃ (b : C) (fst : F.obj b ⟶ X) (snd : b ⟶ a) + (_ : IsPullback fst (F.map snd) f g), P snd) : P.relative F f := by + refine ⟨fun a g ↦ ?_, fun a b g fst snd h ↦ ?_⟩ + all_goals obtain ⟨c, g_fst, g_snd, BC, H⟩ := h₀ g + · refine ⟨c, g_snd, g_fst, BC⟩ + · refine (P.arrow_mk_iso_iff ?_).2 H + exact Arrow.isoMk (F.preimageIso (h.isoIsPullback X (F.obj a) BC)) (Iso.refl _) + (F.map_injective (by simp)) + +lemma relative_of_snd [F.Faithful] [F.Full] [P.RespectsIso] {f : X ⟶ Y} + (hf : F.relativelyRepresentable f) (h : ∀ ⦃a : C⦄ (g : F.obj a ⟶ Y), P (hf.snd g)) : + P.relative F f := + relative.of_exists (fun _ g ↦ ⟨hf.pullback g, hf.fst g, hf.snd g, hf.isPullback g, h g⟩) + +/-- If `P : MorphismProperty C` is stable under base change, `F` is fully faithful and preserves +pullbacks, and `C` has all pullbacks, then for any `f : a ⟶ b` in `C`, `F.map f` satisfies +`P.relative` if `f` satisfies `P`. -/ +lemma relative_map [F.Faithful] [F.Full] [HasPullbacks C] (hP : StableUnderBaseChange P) + {a b : C} {f : a ⟶ b} [∀ c (g : c ⟶ b), PreservesLimit (cospan f g) F] + (hf : P f) : P.relative F (F.map f) := by + have := StableUnderBaseChange.respectsIso hP + apply relative.of_exists + intro Y' g + obtain ⟨g, rfl⟩ := F.map_surjective g + exact ⟨_, _, _, (IsPullback.of_hasPullback f g).map F, hP.snd _ _ hf⟩ + +lemma of_relative_map {a b : C} {f : a ⟶ b} (hf : P.relative F (F.map f)) : P f := + hf.property (𝟙 _) (𝟙 _) f (IsPullback.id_horiz (F.map f)) + +lemma relative_map_iff [F.Faithful] [F.Full] [PreservesLimitsOfShape WalkingCospan F] + [HasPullbacks C] (hP : StableUnderBaseChange P) {X Y : C} {f : X ⟶ Y} : + P.relative F (F.map f) ↔ P f := + ⟨fun hf ↦ of_relative_map hf, fun hf ↦ relative_map hP hf⟩ + +end MorphismProperty + end CategoryTheory diff --git a/Mathlib/CategoryTheory/NatTrans.lean b/Mathlib/CategoryTheory/NatTrans.lean index 0c12f372eaeac..af2c4079f9b36 100644 --- a/Mathlib/CategoryTheory/NatTrans.lean +++ b/Mathlib/CategoryTheory/NatTrans.lean @@ -72,7 +72,7 @@ open CategoryTheory.Functor section -variable {F G H I : C ⥤ D} +variable {F G H : C ⥤ D} /-- `vcomp α β` is the vertical compositions of natural transformations. -/ def vcomp (α : NatTrans F G) (β : NatTrans G H) : NatTrans F H where diff --git a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean index adf26a8d7c01e..0dd92b9817e6a 100644 --- a/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean +++ b/Mathlib/CategoryTheory/Preadditive/AdditiveFunctor.lean @@ -69,6 +69,8 @@ instance : Additive (𝟭 C) where instance {E : Type*} [Category E] [Preadditive E] (G : D ⥤ E) [Functor.Additive G] : Additive (F ⋙ G) where +instance {J : Type*} [Category J] (j : J) : ((evaluation J C).obj j).Additive where + @[simp] theorem map_neg {X Y : C} {f : X ⟶ Y} : F.map (-f) = -F.map f := (F.mapAddHom : (X ⟶ Y) →+ (F.obj X ⟶ F.obj Y)).map_neg _ diff --git a/Mathlib/CategoryTheory/Preadditive/EilenbergMoore.lean b/Mathlib/CategoryTheory/Preadditive/EilenbergMoore.lean index 6770c026e762f..f7dd3eabd7f76 100644 --- a/Mathlib/CategoryTheory/Preadditive/EilenbergMoore.lean +++ b/Mathlib/CategoryTheory/Preadditive/EilenbergMoore.lean @@ -78,7 +78,6 @@ instance Monad.algebraPreadditive : Preadditive (Monad.Algebra T) where zsmul_succ' := by intros ext - dsimp simp only [natCast_zsmul, succ_nsmul] rfl zsmul_neg' := by @@ -159,7 +158,6 @@ instance Comonad.coalgebraPreadditive : Preadditive (Comonad.Coalgebra U) where zsmul_succ' := by intros ext - dsimp simp only [natCast_zsmul, succ_nsmul] rfl zsmul_neg' := by diff --git a/Mathlib/CategoryTheory/Preadditive/EndoFunctor.lean b/Mathlib/CategoryTheory/Preadditive/EndoFunctor.lean index 006286e5be91c..f7fd470a65628 100644 --- a/Mathlib/CategoryTheory/Preadditive/EndoFunctor.lean +++ b/Mathlib/CategoryTheory/Preadditive/EndoFunctor.lean @@ -78,7 +78,6 @@ instance Endofunctor.algebraPreadditive : Preadditive (Endofunctor.Algebra F) wh zsmul_succ' := by intros apply Algebra.Hom.ext - dsimp simp only [natCast_zsmul, succ_nsmul] rfl zsmul_neg' := by @@ -156,7 +155,6 @@ instance Endofunctor.coalgebraPreadditive : Preadditive (Endofunctor.Coalgebra F zsmul_succ' := by intros apply Coalgebra.Hom.ext - dsimp simp only [natCast_zsmul, succ_nsmul] rfl zsmul_neg' := by diff --git a/Mathlib/CategoryTheory/Preadditive/Injective.lean b/Mathlib/CategoryTheory/Preadditive/Injective.lean index b5a5accf6ee7f..3b33277d8bf28 100644 --- a/Mathlib/CategoryTheory/Preadditive/Injective.lean +++ b/Mathlib/CategoryTheory/Preadditive/Injective.lean @@ -108,7 +108,7 @@ instance (X : Type u₁) [Nonempty X] : Injective X where change dite (f y ∈ Set.range f) (fun h => g (Classical.choose h)) _ = _ split_ifs <;> rename_i h · rw [mono_iff_injective] at mono - erw [mono (Classical.choose_spec h)] + rw [mono (Classical.choose_spec h)] · exact False.elim (h ⟨y, rfl⟩)⟩ instance Type.enoughInjectives : EnoughInjectives (Type u₁) where diff --git a/Mathlib/CategoryTheory/Preadditive/Schur.lean b/Mathlib/CategoryTheory/Preadditive/Schur.lean index 407e246e350e0..2fd3b980f6f59 100644 --- a/Mathlib/CategoryTheory/Preadditive/Schur.lean +++ b/Mathlib/CategoryTheory/Preadditive/Schur.lean @@ -70,7 +70,7 @@ noncomputable instance [HasKernels C] {X : C} [Simple X] : DivisionRing (End X) qsmul := _ qsmul_def := fun q a => rfl -open FiniteDimensional +open Module section diff --git a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean index 96b1f0270625c..3e19f976a5b18 100644 --- a/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean +++ b/Mathlib/CategoryTheory/Preadditive/Yoneda/Basic.lean @@ -39,7 +39,7 @@ object `X` to the `End Y`-module of morphisms `X ⟶ Y`. @[simps] def preadditiveYonedaObj (Y : C) : Cᵒᵖ ⥤ ModuleCat.{v} (End Y) where obj X := ModuleCat.of _ (X.unop ⟶ Y) - map f := ModuleCat.ofHom + map f := ModuleCat.asHom { toFun := fun g => f.unop ≫ g map_add' := fun g g' => comp_add _ _ _ _ _ _ map_smul' := fun r g => Eq.symm <| Category.assoc _ _ _ } @@ -66,7 +66,7 @@ object `Y` to the `End X`-module of morphisms `X ⟶ Y`. @[simps] def preadditiveCoyonedaObj (X : Cᵒᵖ) : C ⥤ ModuleCat.{v} (End X) where obj Y := ModuleCat.of _ (unop X ⟶ Y) - map f := ModuleCat.ofHom + map f := ModuleCat.asHom { toFun := fun g => g ≫ f map_add' := fun g g' => add_comp _ _ _ _ _ _ map_smul' := fun r g => Category.assoc _ _ _ } diff --git a/Mathlib/CategoryTheory/Products/Basic.lean b/Mathlib/CategoryTheory/Products/Basic.lean index c38b430629b3b..58958ff88a2de 100644 --- a/Mathlib/CategoryTheory/Products/Basic.lean +++ b/Mathlib/CategoryTheory/Products/Basic.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Stephen Morgan, Kim Morrison -/ -import Mathlib.CategoryTheory.EqToHom import Mathlib.CategoryTheory.Functor.Const import Mathlib.CategoryTheory.Opposites import Mathlib.Data.Prod.Basic @@ -296,7 +295,18 @@ end Equivalence /-- `F.flip` composed with evaluation is the same as evaluating `F`. -/ @[simps!] def flipCompEvaluation (F : A ⥤ B ⥤ C) (a) : F.flip ⋙ (evaluation _ _).obj a ≅ F.obj a := - NatIso.ofComponents fun b => eqToIso rfl + NatIso.ofComponents fun b => Iso.refl _ + +theorem flip_comp_evaluation (F : A ⥤ B ⥤ C) (a) : F.flip ⋙ (evaluation _ _).obj a = F.obj a := + rfl + +/-- `F` composed with evaluation is the same as evaluating `F.flip`. -/ +@[simps!] +def compEvaluation (F : A ⥤ B ⥤ C) (b) : F ⋙ (evaluation _ _).obj b ≅ F.flip.obj b := + NatIso.ofComponents fun a => Iso.refl _ + +theorem comp_evaluation (F : A ⥤ B ⥤ C) (b) : F ⋙ (evaluation _ _).obj b = F.flip.obj b := + rfl variable (A B C) diff --git a/Mathlib/CategoryTheory/Shift/CommShift.lean b/Mathlib/CategoryTheory/Shift/CommShift.lean index 5f75457aa59db..e75c095dca271 100644 --- a/Mathlib/CategoryTheory/Shift/CommShift.lean +++ b/Mathlib/CategoryTheory/Shift/CommShift.lean @@ -246,7 +246,7 @@ variable {C D E J : Type*} [Category C] [Category D] [Category E] [Category J] /-- If `τ : F₁ ⟶ F₂` is a natural transformation between two functors which commute with a shift by an additive monoid `A`, this typeclass asserts a compatibility of `τ` with these shifts. -/ -class CommShift : Prop := +class CommShift : Prop where comm' (a : A) : (F₁.commShiftIso a).hom ≫ whiskerRight τ _ = whiskerLeft _ τ ≫ (F₂.commShiftIso a).hom diff --git a/Mathlib/CategoryTheory/Shift/Localization.lean b/Mathlib/CategoryTheory/Shift/Localization.lean index 5e9f9b7a925b5..1f74884924d44 100644 --- a/Mathlib/CategoryTheory/Shift/Localization.lean +++ b/Mathlib/CategoryTheory/Shift/Localization.lean @@ -32,7 +32,7 @@ namespace MorphismProperty /-- A morphism property `W` on a category `C` is compatible with the shift by a monoid `A` when for all `a : A`, a morphism `f` belongs to `W` if and only if `f⟦a⟧'` does. -/ -class IsCompatibleWithShift : Prop := +class IsCompatibleWithShift : Prop where /-- the condition that for all `a : A`, the morphism property `W` is not changed when we take its inverse image by the shift functor by `a` -/ condition : ∀ (a : A), W.inverseImage (shiftFunctor C a) = W diff --git a/Mathlib/CategoryTheory/Shift/Quotient.lean b/Mathlib/CategoryTheory/Shift/Quotient.lean index d029cd486c714..f789f82c2883c 100644 --- a/Mathlib/CategoryTheory/Shift/Quotient.lean +++ b/Mathlib/CategoryTheory/Shift/Quotient.lean @@ -32,7 +32,7 @@ namespace HomRel /-- A relation on morphisms is compatible with the shift by a monoid `A` when the relation if preserved by the shift. -/ -class IsCompatibleWithShift : Prop := +class IsCompatibleWithShift : Prop where /-- the condition that the relation is preserved by the shift -/ condition : ∀ (a : A) ⦃X Y : C⦄ (f g : X ⟶ Y), r f g → r (f⟦a⟧') (g⟦a⟧') diff --git a/Mathlib/CategoryTheory/Sites/Canonical.lean b/Mathlib/CategoryTheory/Sites/Canonical.lean index 9c6a4291a3191..ec5fdd447f5e9 100644 --- a/Mathlib/CategoryTheory/Sites/Canonical.lean +++ b/Mathlib/CategoryTheory/Sites/Canonical.lean @@ -203,7 +203,7 @@ theorem isSheaf_yoneda_obj (X : C) : Presieve.IsSheaf (canonicalTopology C) (yon fun _ _ hS => sheaf_for_finestTopology _ (Set.mem_range_self _) _ hS /-- A representable functor is a sheaf for the canonical topology. -/ -theorem isSheaf_of_representable (P : Cᵒᵖ ⥤ Type v) [P.Representable] : +theorem isSheaf_of_isRepresentable (P : Cᵒᵖ ⥤ Type v) [P.IsRepresentable] : Presieve.IsSheaf (canonicalTopology C) P := Presieve.isSheaf_iso (canonicalTopology C) P.reprW (isSheaf_yoneda_obj _) @@ -224,9 +224,9 @@ theorem of_yoneda_isSheaf (J : GrothendieckTopology C) apply h) /-- If `J` is subcanonical, then any representable is a `J`-sheaf. -/ -theorem isSheaf_of_representable {J : GrothendieckTopology C} (hJ : Subcanonical J) - (P : Cᵒᵖ ⥤ Type v) [P.Representable] : Presieve.IsSheaf J P := - Presieve.isSheaf_of_le _ hJ (Sheaf.isSheaf_of_representable P) +theorem isSheaf_of_isRepresentable {J : GrothendieckTopology C} (hJ : Subcanonical J) + (P : Cᵒᵖ ⥤ Type v) [P.IsRepresentable] : Presieve.IsSheaf J P := + Presieve.isSheaf_of_le _ hJ (Sheaf.isSheaf_of_isRepresentable P) variable {J} @@ -238,7 +238,7 @@ into the sheaf category. def yoneda (hJ : Subcanonical J) : C ⥤ Sheaf J (Type v) where obj X := ⟨CategoryTheory.yoneda.obj X, by rw [isSheaf_iff_isSheaf_of_type] - apply hJ.isSheaf_of_representable⟩ + apply hJ.isSheaf_of_isRepresentable⟩ map f := ⟨CategoryTheory.yoneda.map f⟩ variable (hJ : Subcanonical J) diff --git a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean index 7f2817071b11a..a20deb1ceff5d 100644 --- a/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean +++ b/Mathlib/CategoryTheory/Sites/Coherent/SheafComparison.lean @@ -85,7 +85,15 @@ lemma eq_induced : haveI := F.reflects_precoherent instance : haveI := F.reflects_precoherent; F.IsDenseSubsite (coherentTopology C) (coherentTopology D) where - functorPushforward_mem_iff := by simp_rw [eq_induced F]; rfl + functorPushforward_mem_iff := by + rw [eq_induced F] + #adaptation_note + /-- + This proof used to be `rfl`, + but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. + It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 + -/ + exact Iff.rfl lemma coverPreserving : haveI := F.reflects_precoherent CoverPreserving (coherentTopology _) (coherentTopology _) F := @@ -181,7 +189,15 @@ lemma eq_induced : haveI := F.reflects_preregular instance : haveI := F.reflects_preregular; F.IsDenseSubsite (regularTopology C) (regularTopology D) where - functorPushforward_mem_iff := by simp_rw [eq_induced F]; rfl + functorPushforward_mem_iff := by + rw [eq_induced F] + #adaptation_note + /-- + This proof used to be `rfl`, + but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. + It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 + -/ + exact Iff.rfl lemma coverPreserving : haveI := F.reflects_preregular CoverPreserving (regularTopology _) (regularTopology _) F := diff --git a/Mathlib/CategoryTheory/Sites/Grothendieck.lean b/Mathlib/CategoryTheory/Sites/Grothendieck.lean index 3e453496f9a9d..0d3552925cc54 100644 --- a/Mathlib/CategoryTheory/Sites/Grothendieck.lean +++ b/Mathlib/CategoryTheory/Sites/Grothendieck.lean @@ -263,7 +263,13 @@ instance : InfSet (GrothendieckTopology C) where /-- See -/ theorem isGLB_sInf (s : Set (GrothendieckTopology C)) : IsGLB s (sInf s) := by refine @IsGLB.of_image _ _ _ _ sieves ?_ _ _ ?_ - · rfl + · #adaptation_note + /-- + This proof used to be `rfl`, + but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. + It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 + -/ + exact Iff.rfl · exact _root_.isGLB_sInf _ /-- Construct a complete lattice from the `Inf`, but make the trivial and discrete topologies diff --git a/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean b/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean index ee99ef8e05d4a..7e02c805dd32b 100644 --- a/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean +++ b/Mathlib/CategoryTheory/Sites/PreservesSheafification.lean @@ -8,7 +8,7 @@ import Mathlib.CategoryTheory.Sites.CompatibleSheafification import Mathlib.CategoryTheory.Sites.Whiskering import Mathlib.CategoryTheory.Sites.Sheafification -/-! # Functors which preserves sheafification +/-! # Functors which preserve sheafification In this file, given a Grothendieck topology `J` on `C` and `F : A ⥤ B`, we define a type class `J.PreservesSheafification F`. We say that `F` preserves @@ -20,7 +20,7 @@ this property for the map from any presheaf `P` to its associated sheaf, see In general, we define `Sheaf.composeAndSheafify J F : Sheaf J A ⥤ Sheaf J B` as the functor which sends a sheaf `G` to the sheafification of the composition `G.val ⋙ F`. -It `J.PreservesSheafification F`, we show that this functor can also be thought +If `J.PreservesSheafification F`, we show that this functor can also be thought of as the localization of the functor `_ ⋙ F` on presheaves: we construct an isomorphism `presheafToSheafCompComposeAndSheafifyIso` between `presheafToSheaf J A ⋙ Sheaf.composeAndSheafify J F` and @@ -29,7 +29,7 @@ as the localization of the functor `_ ⋙ F` on presheaves: we construct an isom Moreover, if we assume `J.HasSheafCompose F`, we obtain an isomorphism `sheafifyComposeIso J F P : sheafify J (P ⋙ F) ≅ sheafify J P ⋙ F`. -We show that under suitable assumptions, the forget functor from a concrete +We show that under suitable assumptions, the forgetful functor from a concrete category preserves sheafification; this holds more generally for functors between such concrete categories which commute both with suitable limits and colimits. diff --git a/Mathlib/CategoryTheory/Skeletal.lean b/Mathlib/CategoryTheory/Skeletal.lean index 2ff548def5bb3..af988c24022a5 100644 --- a/Mathlib/CategoryTheory/Skeletal.lean +++ b/Mathlib/CategoryTheory/Skeletal.lean @@ -67,7 +67,7 @@ variable (C D) /-- Construct the skeleton category as the induced category on the isomorphism classes, and derive its category structure. -/ -def Skeleton : Type u₁ := InducedCategory C Quotient.out +def Skeleton : Type u₁ := InducedCategory (C := Quotient (isIsomorphicSetoid C)) C Quotient.out instance [Inhabited C] : Inhabited (Skeleton C) := ⟨⟦default⟧⟩ diff --git a/Mathlib/CategoryTheory/SmallObject/Iteration.lean b/Mathlib/CategoryTheory/SmallObject/Iteration.lean index 4e9947245dd1b..a9470418b418d 100644 --- a/Mathlib/CategoryTheory/SmallObject/Iteration.lean +++ b/Mathlib/CategoryTheory/SmallObject/Iteration.lean @@ -123,7 +123,7 @@ lemma mapSucc_eq (i : J) (hi : i < j) : end -variable (iter₁ iter₂ iter₃ : Φ.Iteration ε j) +variable (iter₁ iter₂ : Φ.Iteration ε j) /-- A morphism between two objects `iter₁` and `iter₂` in the category `Φ.Iteration ε j` of `j`th iterations of a functor `Φ` @@ -148,7 +148,7 @@ attribute [simp, reassoc] natTrans_app_zero def id : Hom iter₁ iter₁ where natTrans := 𝟙 _ -variable {iter₁ iter₂ iter₃} +variable {iter₁ iter₂} -- Note: this is not made a global ext lemma because it is shown below -- that the type of morphisms is a subsingleton. diff --git a/Mathlib/CategoryTheory/Triangulated/Basic.lean b/Mathlib/CategoryTheory/Triangulated/Basic.lean index 308f5456a6a29..e76c664d5f1d3 100644 --- a/Mathlib/CategoryTheory/Triangulated/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/Basic.lean @@ -260,9 +260,9 @@ variable {J : Type*} (T : J → Triangle C) /-- The product of a family of triangles. -/ @[simps!] def productTriangle : Triangle C := - Triangle.mk (Pi.map (fun j => (T j).mor₁)) - (Pi.map (fun j => (T j).mor₂)) - (Pi.map (fun j => (T j).mor₃) ≫ inv (piComparison _ _)) + Triangle.mk (Limits.Pi.map (fun j => (T j).mor₁)) + (Limits.Pi.map (fun j => (T j).mor₂)) + (Limits.Pi.map (fun j => (T j).mor₃) ≫ inv (piComparison _ _)) /-- A projection from the product of a family of triangles. -/ @[simps] diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean index d78ec3c589a8f..9507a7937e954 100644 --- a/Mathlib/CategoryTheory/Triangulated/Functor.lean +++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean @@ -310,6 +310,6 @@ lemma isTriangulated_of_essSurj_mapComposableArrows_two exact ⟨Octahedron.ofIso (e₁ := (e.app 0).symm) (e₂ := (e.app 1).symm) (e₃ := (e.app 2).symm) (comm₁₂ := ComposableArrows.naturality' e.inv 0 1) (comm₂₃ := ComposableArrows.naturality' e.inv 1 2) - (H := (someOctahedron rfl h₁₂' h₂₃' h₁₃').map F) _ _ _ _ _⟩ + (H := (someOctahedron rfl h₁₂' h₂₃' h₁₃').map F) ..⟩ end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/Opposite.lean b/Mathlib/CategoryTheory/Triangulated/Opposite.lean index 4de06f2ff9fb9..3b6c664323762 100644 --- a/Mathlib/CategoryTheory/Triangulated/Opposite.lean +++ b/Mathlib/CategoryTheory/Triangulated/Opposite.lean @@ -105,7 +105,7 @@ lemma shiftFunctorAdd'_op_hom_app (X : Cᵒᵖ) (a₁ a₂ a₃ : ℤ) (h : a₁ (shiftFunctor Cᵒᵖ a₂).map ((shiftFunctorOpIso C _ _ h₁).inv.app X) := by erw [@pullbackShiftFunctorAdd'_hom_app (OppositeShift C ℤ) _ _ _ _ _ _ _ X a₁ a₂ a₃ h b₁ b₂ b₃ (by dsimp; omega) (by dsimp; omega) (by dsimp; omega)] - erw [oppositeShiftFunctorAdd'_hom_app] + rw [oppositeShiftFunctorAdd'_hom_app] obtain rfl : b₁ = -a₁ := by omega obtain rfl : b₂ = -a₂ := by omega obtain rfl : b₃ = -a₃ := by omega diff --git a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean index 091de90c8c3c1..c3b954b379632 100644 --- a/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean +++ b/Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean @@ -563,7 +563,7 @@ lemma productTriangle_distinguished {J : Type*} (T : J → Triangle C) `φ'.hom₁` and `φ'.hom₂` are identities. Then, it suffices to show that `φ'.hom₃` is an isomorphism, which is achieved by using Yoneda's lemma and diagram chases. -/ - let f₁ := Pi.map (fun j => (T j).mor₁) + let f₁ := Limits.Pi.map (fun j => (T j).mor₁) obtain ⟨Z, f₂, f₃, hT'⟩ := distinguished_cocone_triangle f₁ let T' := Triangle.mk f₁ f₂ f₃ change T' ∈ distTriang C at hT' diff --git a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean index f4c688ba57647..22baf9e9ef9b8 100644 --- a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean +++ b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean @@ -152,16 +152,16 @@ lemma isoClosure_W : S.isoClosure.W = S.W := by exact ⟨Z, g, h, mem, le_isoClosure _ _ hZ⟩ instance respectsIso_W : S.W.RespectsIso where - precomp := by - rintro X' X Y e f ⟨Z, g, h, mem, mem'⟩ - refine ⟨Z, g, h ≫ e.inv⟦(1 : ℤ)⟧', isomorphic_distinguished _ mem _ ?_, mem'⟩ - refine Triangle.isoMk _ _ e (Iso.refl _) (Iso.refl _) (by aesop_cat) (by aesop_cat) ?_ + precomp {X' X Y} e (he : IsIso e) := by + rintro f ⟨Z, g, h, mem, mem'⟩ + refine ⟨Z, g, h ≫ inv e⟦(1 : ℤ)⟧', isomorphic_distinguished _ mem _ ?_, mem'⟩ + refine Triangle.isoMk _ _ (asIso e) (Iso.refl _) (Iso.refl _) (by aesop_cat) (by aesop_cat) ?_ dsimp - simp only [assoc, ← Functor.map_comp, e.inv_hom_id, Functor.map_id, comp_id, id_comp] - postcomp := by - rintro X Y Y' e f ⟨Z, g, h, mem, mem'⟩ - refine ⟨Z, e.inv ≫ g, h, isomorphic_distinguished _ mem _ ?_, mem'⟩ - exact Triangle.isoMk _ _ (Iso.refl _) e.symm (Iso.refl _) + simp only [Functor.map_inv, assoc, IsIso.inv_hom_id, comp_id, id_comp] + postcomp {X Y Y'} e (he : IsIso e) := by + rintro f ⟨Z, g, h, mem, mem'⟩ + refine ⟨Z, inv e ≫ g, h, isomorphic_distinguished _ mem _ ?_, mem'⟩ + exact Triangle.isoMk _ _ (Iso.refl _) (asIso e).symm (Iso.refl _) instance : S.W.ContainsIdentities := by rw [← isoClosure_W] diff --git a/Mathlib/CategoryTheory/Yoneda.lean b/Mathlib/CategoryTheory/Yoneda.lean index 9d0486e458589..f06afc7170c1c 100644 --- a/Mathlib/CategoryTheory/Yoneda.lean +++ b/Mathlib/CategoryTheory/Yoneda.lean @@ -24,7 +24,7 @@ namespace CategoryTheory open Opposite -universe v₁ u₁ u₂ +universe v v₁ u₁ u₂ -- morphism levels before object levels. See note [CategoryTheory universes]. variable {C : Type u₁} [Category.{v₁} C] @@ -153,97 +153,228 @@ end Coyoneda namespace Functor -/-- A functor `F : Cᵒᵖ ⥤ Type v₁` is representable if there is object `X` so `F ≅ yoneda.obj X`. +/-- The data which expresses that a functor `F : Cᵒᵖ ⥤ Type v` is representable by `Y : C`. -/ +structure RepresentableBy (F : Cᵒᵖ ⥤ Type v) (Y : C) where + /-- the natural bijection `(X ⟶ Y) ≃ F.obj (op X)`. -/ + homEquiv {X : C} : (X ⟶ Y) ≃ F.obj (op X) + homEquiv_comp {X X' : C} (f : X ⟶ X') (g : X' ⟶ Y) : + homEquiv (f ≫ g) = F.map f.op (homEquiv g) + +/-- If `F ≅ F'`, and `F` is representable, then `F'` is representable. -/ +def RepresentableBy.ofIso {F F' : Cᵒᵖ ⥤ Type v} {Y : C} (e : F.RepresentableBy Y) (e' : F ≅ F') : + F'.RepresentableBy Y where + homEquiv {X} := e.homEquiv.trans (e'.app _).toEquiv + homEquiv_comp {X X'} f g := by + dsimp + rw [e.homEquiv_comp] + apply congr_fun (e'.hom.naturality f.op) + +/-- The data which expresses that a functor `F : C ⥤ Type v` is corepresentable by `X : C`. -/ +structure CorepresentableBy (F : C ⥤ Type v) (X : C) where + /-- the natural bijection `(X ⟶ Y) ≃ F.obj Y`. -/ + homEquiv {Y : C} : (X ⟶ Y) ≃ F.obj Y + homEquiv_comp {Y Y' : C} (g : Y ⟶ Y') (f : X ⟶ Y) : + homEquiv (f ≫ g) = F.map g (homEquiv f) + +/-- If `F ≅ F'`, and `F` is corepresentable, then `F'` is corepresentable. -/ +def CorepresentableBy.ofIso {F F' : C ⥤ Type v} {X : C} (e : F.CorepresentableBy X) + (e' : F ≅ F') : + F'.CorepresentableBy X where + homEquiv {X} := e.homEquiv.trans (e'.app _).toEquiv + homEquiv_comp {Y Y'} g f := by + dsimp + rw [e.homEquiv_comp] + apply congr_fun (e'.hom.naturality g) + +lemma RepresentableBy.homEquiv_eq {F : Cᵒᵖ ⥤ Type v} {Y : C} (e : F.RepresentableBy Y) + {X : C} (f : X ⟶ Y) : + e.homEquiv f = F.map f.op (e.homEquiv (𝟙 Y)) := by + conv_lhs => rw [← Category.comp_id f, e.homEquiv_comp] + +lemma CorepresentableBy.homEquiv_eq {F : C ⥤ Type v} {X : C} (e : F.CorepresentableBy X) + {Y : C} (f : X ⟶ Y) : + e.homEquiv f = F.map f (e.homEquiv (𝟙 X)) := by + conv_lhs => rw [← Category.id_comp f, e.homEquiv_comp] + +@[ext] +lemma RepresentableBy.ext {F : Cᵒᵖ ⥤ Type v} {Y : C} {e e' : F.RepresentableBy Y} + (h : e.homEquiv (𝟙 Y) = e'.homEquiv (𝟙 Y)) : e = e' := by + have : ∀ {X : C} (f : X ⟶ Y), e.homEquiv f = e'.homEquiv f := fun {X} f ↦ by + rw [e.homEquiv_eq, e'.homEquiv_eq, h] + obtain ⟨e, he⟩ := e + obtain ⟨e', he'⟩ := e' + obtain rfl : @e = @e' := by ext; apply this + rfl + +@[ext] +lemma CorepresentableBy.ext {F : C ⥤ Type v} {X : C} {e e' : F.CorepresentableBy X} + (h : e.homEquiv (𝟙 X) = e'.homEquiv (𝟙 X)) : e = e' := by + have : ∀ {Y : C} (f : X ⟶ Y), e.homEquiv f = e'.homEquiv f := fun {X} f ↦ by + rw [e.homEquiv_eq, e'.homEquiv_eq, h] + obtain ⟨e, he⟩ := e + obtain ⟨e', he'⟩ := e' + obtain rfl : @e = @e' := by ext; apply this + rfl + +/-- The obvious bijection `F.RepresentableBy Y ≃ (yoneda.obj Y ≅ F)` +when `F : Cᵒᵖ ⥤ Type v₁` and `[Category.{v₁} C]`. -/ +def representableByEquiv {F : Cᵒᵖ ⥤ Type v₁} {Y : C} : + F.RepresentableBy Y ≃ (yoneda.obj Y ≅ F) where + toFun r := NatIso.ofComponents (fun _ ↦ r.homEquiv.toIso) (fun {X X'} f ↦ by + ext g + simp [r.homEquiv_comp]) + invFun e := + { homEquiv := (e.app _).toEquiv + homEquiv_comp := fun {X X'} f g ↦ congr_fun (e.hom.naturality f.op) g } + left_inv _ := rfl + right_inv _ := rfl + +/-- The isomorphism `yoneda.obj Y ≅ F` induced by `e : F.RepresentableBy Y`. -/ +def RepresentableBy.toIso {F : Cᵒᵖ ⥤ Type v₁} {Y : C} (e : F.RepresentableBy Y) : + yoneda.obj Y ≅ F := + representableByEquiv e + +/-- The obvious bijection `F.CorepresentableBy X ≃ (yoneda.obj Y ≅ F)` +when `F : C ⥤ Type v₁` and `[Category.{v₁} C]`. -/ +def corepresentableByEquiv {F : C ⥤ Type v₁} {X : C} : + F.CorepresentableBy X ≃ (coyoneda.obj (op X) ≅ F) where + toFun r := NatIso.ofComponents (fun _ ↦ r.homEquiv.toIso) (fun {X X'} f ↦ by + ext g + simp [r.homEquiv_comp]) + invFun e := + { homEquiv := (e.app _).toEquiv + homEquiv_comp := fun {X X'} f g ↦ congr_fun (e.hom.naturality f) g } + left_inv _ := rfl + right_inv _ := rfl + +/-- The isomorphism `coyoneda.obj (op X) ≅ F` induced by `e : F.CorepresentableBy X`. -/ +def CorepresentableBy.toIso {F : C ⥤ Type v₁} {X : C} (e : F.CorepresentableBy X) : + coyoneda.obj (op X) ≅ F := + corepresentableByEquiv e + +/-- A functor `F : Cᵒᵖ ⥤ Type v` is representable if there is oan bject `Y` with a structure +`F.RepresentableBy Y`, i.e. there is a natural bijection `(X ⟶ Y) ≃ F.obj (op X)`, +which may also be rephrased as a natural isomorphism `yoneda.obj X ≅ F` when `Category.{v} C`. See . -/ -class Representable (F : Cᵒᵖ ⥤ Type v₁) : Prop where - /-- `Hom(-,X) ≅ F` via `f` -/ - has_representation : ∃ (X : _), Nonempty (yoneda.obj X ≅ F) +class IsRepresentable (F : Cᵒᵖ ⥤ Type v) : Prop where + has_representation : ∃ (Y : C), Nonempty (F.RepresentableBy Y) + +@[deprecated (since := "2024-10-03")] alias Representable := IsRepresentable + +lemma RepresentableBy.isRepresentable {F : Cᵒᵖ ⥤ Type v} {Y : C} (e : F.RepresentableBy Y) : + F.IsRepresentable where + has_representation := ⟨Y, ⟨e⟩⟩ -instance {X : C} : Representable (yoneda.obj X) where has_representation := ⟨X, ⟨Iso.refl _⟩⟩ +/-- Alternative constructure for `F.IsRepresentable`, which takes as an input an +isomorphism `yoneda.obj X ≅ F`. -/ +lemma IsRepresentable.mk' {F : Cᵒᵖ ⥤ Type v₁} {X : C} (e : yoneda.obj X ≅ F) : + F.IsRepresentable := + (representableByEquiv.symm e).isRepresentable + +instance {X : C} : IsRepresentable (yoneda.obj X) := + IsRepresentable.mk' (Iso.refl _) /-- A functor `F : C ⥤ Type v₁` is corepresentable if there is object `X` so `F ≅ coyoneda.obj X`. See . -/ -class Corepresentable (F : C ⥤ Type v₁) : Prop where - /-- `Hom(X,-) ≅ F` via `f` -/ - has_corepresentation : ∃ (X : _), Nonempty (coyoneda.obj X ≅ F) +class IsCorepresentable (F : C ⥤ Type v) : Prop where + has_corepresentation : ∃ (X : C), Nonempty (F.CorepresentableBy X) + +@[deprecated (since := "2024-10-03")] alias Corepresentable := IsCorepresentable + +lemma CorepresentableBy.isCorepresentable {F : C ⥤ Type v} {X : C} (e : F.CorepresentableBy X) : + F.IsCorepresentable where + has_corepresentation := ⟨X, ⟨e⟩⟩ + +/-- Alternative constructure for `F.IsCorepresentable`, which takes as an input an +isomorphism `coyoneda.obj (op X) ≅ F`. -/ +lemma IsCorepresentable.mk' {F : C ⥤ Type v₁} {X : C} (e : coyoneda.obj (op X) ≅ F) : + F.IsCorepresentable := + (corepresentableByEquiv.symm e).isCorepresentable -instance {X : Cᵒᵖ} : Corepresentable (coyoneda.obj X) where - has_corepresentation := ⟨X, ⟨Iso.refl _⟩⟩ +instance {X : Cᵒᵖ} : IsCorepresentable (coyoneda.obj X) := + IsCorepresentable.mk' (Iso.refl _) -- instance : corepresentable (𝟭 (Type v₁)) := -- corepresentable_of_nat_iso (op punit) coyoneda.punit_iso section Representable -variable (F : Cᵒᵖ ⥤ Type v₁) -variable [hF : F.Representable] +variable (F : Cᵒᵖ ⥤ Type v) [hF : F.IsRepresentable] /-- The representing object for the representable functor `F`. -/ -noncomputable def reprX : C := hF.has_representation.choose +noncomputable def reprX : C := + hF.has_representation.choose -/-- An isomorphism between a representable `F` and a functor of the -form `C(-, F.reprX)`. Note the components `F.reprW.app X` -definitionally have type `(X.unop ⟶ F.repr_X) ≅ F.obj X`. --/ -noncomputable def reprW : yoneda.obj F.reprX ≅ F := - Representable.has_representation.choose_spec.some +/-- A chosen term in `F.RepresentableBy (reprX F)` when `F.IsRepresentable` holds. -/ +noncomputable def representableBy : F.RepresentableBy F.reprX := + hF.has_representation.choose_spec.some /-- The representing element for the representable functor `F`, sometimes called the universal element of the functor. -/ noncomputable def reprx : F.obj (op F.reprX) := - F.reprW.hom.app (op F.reprX) (𝟙 F.reprX) + F.representableBy.homEquiv (𝟙 _) -theorem reprW_app_hom (X : Cᵒᵖ) (f : unop X ⟶ F.reprX) : - (F.reprW.app X).hom f = F.map f.op F.reprx := by - simp only [yoneda_obj_obj, Iso.app_hom, op_unop, reprx, ← FunctorToTypes.naturality, - yoneda_obj_map, unop_op, Quiver.Hom.unop_op, Category.comp_id] +/-- An isomorphism between a representable `F` and a functor of the +form `C(-, F.reprX)`. Note the components `F.reprW.app X` +definitionally have type `(X.unop ⟶ F.reprX) ≅ F.obj X`. +-/ +noncomputable def reprW (F : Cᵒᵖ ⥤ Type v₁) [F.IsRepresentable] : + yoneda.obj F.reprX ≅ F := F.representableBy.toIso + +theorem reprW_hom_app (F : Cᵒᵖ ⥤ Type v₁) [F.IsRepresentable] + (X : Cᵒᵖ) (f : unop X ⟶ F.reprX) : + F.reprW.hom.app X f = F.map f.op F.reprx := by + apply RepresentableBy.homEquiv_eq end Representable section Corepresentable -variable (F : C ⥤ Type v₁) -variable [hF : F.Corepresentable] +variable (F : C ⥤ Type v) [hF : F.IsCorepresentable] /-- The representing object for the corepresentable functor `F`. -/ noncomputable def coreprX : C := - hF.has_corepresentation.choose.unop + hF.has_corepresentation.choose -/-- An isomorphism between a corepresnetable `F` and a functor of the form -`C(F.corepr X, -)`. Note the components `F.coreprW.app X` -definitionally have type `F.corepr_X ⟶ X ≅ F.obj X`. --/ -noncomputable def coreprW : coyoneda.obj (op F.coreprX) ≅ F := +/-- A chosen term in `F.CorepresentableBy (coreprX F)` when `F.IsCorepresentable` holds. -/ +noncomputable def corepresentableBy : F.CorepresentableBy F.coreprX := hF.has_corepresentation.choose_spec.some /-- The representing element for the corepresentable functor `F`, sometimes called the universal element of the functor. -/ noncomputable def coreprx : F.obj F.coreprX := - F.coreprW.hom.app F.coreprX (𝟙 F.coreprX) + F.corepresentableBy.homEquiv (𝟙 _) + +/-- An isomorphism between a corepresentable `F` and a functor of the form +`C(F.corepr X, -)`. Note the components `F.coreprW.app X` +definitionally have type `F.corepr_X ⟶ X ≅ F.obj X`. +-/ +noncomputable def coreprW (F : C ⥤ Type v₁) [F.IsCorepresentable] : + coyoneda.obj (op F.coreprX) ≅ F := + F.corepresentableBy.toIso -theorem coreprW_app_hom (X : C) (f : F.coreprX ⟶ X) : - (F.coreprW.app X).hom f = F.map f F.coreprx := by - simp only [coyoneda_obj_obj, unop_op, Iso.app_hom, coreprx, ← FunctorToTypes.naturality, - coyoneda_obj_map, Category.id_comp] +theorem coreprW_hom_app (F : C ⥤ Type v₁) [F.IsCorepresentable] (X : C) (f : F.coreprX ⟶ X) : + F.coreprW.hom.app X f = F.map f F.coreprx := by + apply CorepresentableBy.homEquiv_eq end Corepresentable end Functor -theorem representable_of_natIso (F : Cᵒᵖ ⥤ Type v₁) {G} (i : F ≅ G) [F.Representable] : - G.Representable := - { has_representation := ⟨F.reprX, ⟨F.reprW ≪≫ i⟩⟩ } +theorem isRepresentable_of_natIso (F : Cᵒᵖ ⥤ Type v₁) {G} (i : F ≅ G) [F.IsRepresentable] : + G.IsRepresentable := + (F.representableBy.ofIso i).isRepresentable -theorem corepresentable_of_natIso (F : C ⥤ Type v₁) {G} (i : F ≅ G) [F.Corepresentable] : - G.Corepresentable := - { has_corepresentation := ⟨op F.coreprX, ⟨F.coreprW ≪≫ i⟩⟩ } +theorem corepresentable_of_natIso (F : C ⥤ Type v₁) {G} (i : F ≅ G) [F.IsCorepresentable] : + G.IsCorepresentable := + (F.corepresentableBy.ofIso i).isCorepresentable -instance : Functor.Corepresentable (𝟭 (Type v₁)) := +instance : Functor.IsCorepresentable (𝟭 (Type v₁)) := corepresentable_of_natIso (coyoneda.obj (op PUnit)) Coyoneda.punitIso open Opposite @@ -286,6 +417,7 @@ theorem yonedaEquiv_symm_app_apply {X : C} {F : Cᵒᵖ ⥤ Type v₁} (x : F.ob (f : Y.unop ⟶ X) : (yonedaEquiv.symm x).app Y f = F.map f.op x := rfl +/-- See also `yonedaEquiv_naturality'` for a more general version. -/ lemma yonedaEquiv_naturality {X Y : C} {F : Cᵒᵖ ⥤ Type v₁} (f : yoneda.obj X ⟶ F) (g : Y ⟶ X) : F.map g.op (yonedaEquiv f) = yonedaEquiv (yoneda.map g ≫ f) := by change (f.app (op X) ≫ F.map g.op) (𝟙 X) = f.app (op Y) (𝟙 Y ≫ g) @@ -293,6 +425,9 @@ lemma yonedaEquiv_naturality {X Y : C} {F : Cᵒᵖ ⥤ Type v₁} (f : yoneda.o dsimp simp +/-- Variant of `yonedaEquiv_naturality` with general `g`. This is technically strictly more general + than `yonedaEquiv_naturality`, but `yonedaEquiv_naturality` is sometimes preferable because it + can avoid the "motive is not type correct" error. -/ lemma yonedaEquiv_naturality' {X Y : Cᵒᵖ} {F : Cᵒᵖ ⥤ Type v₁} (f : yoneda.obj (unop X) ⟶ F) (g : X ⟶ Y) : F.map g (yonedaEquiv f) = yonedaEquiv (yoneda.map g.unop ≫ f) := yonedaEquiv_naturality _ _ @@ -305,6 +440,18 @@ lemma yonedaEquiv_yoneda_map {X Y : C} (f : X ⟶ Y) : yonedaEquiv (yoneda.map f rw [yonedaEquiv_apply] simp +/-- See also `map_yonedaEquiv'` for a more general version. -/ +lemma map_yonedaEquiv {X Y : C} {F : Cᵒᵖ ⥤ Type v₁} (f : yoneda.obj X ⟶ F) + (g : Y ⟶ X) : F.map g.op (yonedaEquiv f) = f.app (op Y) g := by + rw [yonedaEquiv_naturality, yonedaEquiv_comp, yonedaEquiv_yoneda_map] + +/-- Variant of `map_yonedaEquiv` with general `g`. This is technically strictly more general + than `map_yonedaEquiv`, but `map_yonedaEquiv` is sometimes preferable because it + can avoid the "motive is not type correct" error. -/ +lemma map_yonedaEquiv' {X Y : Cᵒᵖ} {F : Cᵒᵖ ⥤ Type v₁} (f : yoneda.obj (unop X) ⟶ F) + (g : X ⟶ Y) : F.map g (yonedaEquiv f) = f.app Y g.unop := by + rw [yonedaEquiv_naturality', yonedaEquiv_comp, yonedaEquiv_yoneda_map] + lemma yonedaEquiv_symm_map {X Y : Cᵒᵖ} (f : X ⟶ Y) {F : Cᵒᵖ ⥤ Type v₁} (t : F.obj X) : yonedaEquiv.symm (F.map f t) = yoneda.map f.unop ≫ yonedaEquiv.symm t := by obtain ⟨u, rfl⟩ := yonedaEquiv.surjective t @@ -481,6 +628,10 @@ lemma coyonedaEquiv_coyoneda_map {X Y : C} (f : X ⟶ Y) : rw [coyonedaEquiv_apply] simp +lemma map_coyonedaEquiv {X Y : C} {F : C ⥤ Type v₁} (f : coyoneda.obj (op X) ⟶ F) + (g : X ⟶ Y) : F.map g (coyonedaEquiv f) = f.app Y g := by + rw [coyonedaEquiv_naturality, coyonedaEquiv_comp, coyonedaEquiv_coyoneda_map] + lemma coyonedaEquiv_symm_map {X Y : C} (f : X ⟶ Y) {F : C ⥤ Type v₁} (t : F.obj X) : coyonedaEquiv.symm (F.map f t) = coyoneda.map f.op ≫ coyonedaEquiv.symm t := by obtain ⟨u, rfl⟩ := coyonedaEquiv.surjective t diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean index 9b660a299371d..076f7c450bcde 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Behrend.lean @@ -356,7 +356,7 @@ theorem three_le_nValue (hN : 64 ≤ N) : 3 ≤ nValue N := by rw [rpow_natCast] exact (cast_le.2 hN).trans' (by norm_num1) apply lt_of_lt_of_le _ (log_le_log (rpow_pos_of_pos zero_lt_two _) this) - rw [log_rpow zero_lt_two, ← div_lt_iff'] + rw [log_rpow zero_lt_two, ← div_lt_iff₀'] · exact log_two_gt_d9.trans_le' (by norm_num1) · norm_num1 @@ -459,7 +459,7 @@ theorem roth_lower_bound_explicit (hN : 4096 ≤ N) : theorem exp_four_lt : exp 4 < 64 := by rw [show (64 : ℝ) = 2 ^ ((6 : ℕ) : ℝ) by rw [rpow_natCast]; norm_num1, - ← lt_log_iff_exp_lt (rpow_pos_of_pos zero_lt_two _), log_rpow zero_lt_two, ← div_lt_iff'] + ← lt_log_iff_exp_lt (rpow_pos_of_pos zero_lt_two _), log_rpow zero_lt_two, ← div_lt_iff₀'] · exact log_two_gt_d9.trans_le' (by norm_num1) · norm_num diff --git a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean index 7c5f0dc5ba024..213220d6ea296 100644 --- a/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean +++ b/Mathlib/Combinatorics/Additive/AP/Three/Defs.lean @@ -43,7 +43,7 @@ the size of the biggest 3AP-free subset of `{0, ..., n - 1}`. 3AP-free, Salem-Spencer, Roth, arithmetic progression, average, three-free -/ -open Finset Function Nat +open Finset Function open scoped Pointwise variable {F α β 𝕜 E : Type*} @@ -273,7 +273,7 @@ variable {s t} {n : ℕ} @[to_additive] theorem ThreeGPFree.le_mulRothNumber (hs : ThreeGPFree (s : Set α)) (h : s ⊆ t) : s.card ≤ mulRothNumber t := - le_findGreatest (card_le_card h) ⟨s, h, rfl, hs⟩ + Nat.le_findGreatest (card_le_card h) ⟨s, h, rfl, hs⟩ @[to_additive] theorem ThreeGPFree.mulRothNumber_eq (hs : ThreeGPFree (s : Set α)) : diff --git a/Mathlib/Combinatorics/Additive/Corner/Roth.lean b/Mathlib/Combinatorics/Additive/Corner/Roth.lean index 69eec794bef92..73840313536fa 100644 --- a/Mathlib/Combinatorics/Additive/Corner/Roth.lean +++ b/Mathlib/Combinatorics/Additive/Corner/Roth.lean @@ -88,7 +88,7 @@ theorem corners_theorem (ε : ℝ) (hε : 0 < ε) (hG : cornersTheoremBound ε rwa [mul_le_iff_le_one_left] at this positivity have := noAccidental hA - rw [Nat.floor_lt' (by positivity), inv_pos_lt_iff_one_lt_mul'] at hG + rw [Nat.floor_lt' (by positivity), inv_lt_iff_one_lt_mul₀'] at hG swap · have : ε / 9 ≤ 1 := by linarith positivity diff --git a/Mathlib/Combinatorics/Additive/Dissociation.lean b/Mathlib/Combinatorics/Additive/Dissociation.lean index d7dfe231cee32..f22b05d75f55d 100644 --- a/Mathlib/Combinatorics/Additive/Dissociation.lean +++ b/Mathlib/Combinatorics/Additive/Dissociation.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Group.Units.Equiv import Mathlib.Data.Fintype.Card diff --git a/Mathlib/Combinatorics/Additive/FreimanHom.lean b/Mathlib/Combinatorics/Additive/FreimanHom.lean index c196e507f58bb..01cf0ef4b01c3 100644 --- a/Mathlib/Combinatorics/Additive/FreimanHom.lean +++ b/Mathlib/Combinatorics/Additive/FreimanHom.lean @@ -5,8 +5,10 @@ Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Algebra.BigOperators.Ring import Mathlib.Algebra.CharP.Defs -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic +import Mathlib.Algebra.Group.Submonoid.Operations import Mathlib.Algebra.Order.BigOperators.Group.Multiset +import Mathlib.Algebra.Order.Ring.Nat import Mathlib.Data.ZMod.Defs /-! @@ -249,6 +251,11 @@ lemma isMulFreimanIso_empty : IsMulFreimanIso n (∅ : Set α) (∅ : Set β) f map_prod_eq_map_prod s t _ _ _ _ := by rw [← map_multiset_prod, ← map_multiset_prod, EquivLike.apply_eq_iff_eq] +@[to_additive] +lemma IsMulFreimanHom.subtypeVal {S : Type*} [SetLike S α] [SubmonoidClass S α] {s : S} : + IsMulFreimanHom n (univ : Set s) univ Subtype.val := + MonoidHomClass.isMulFreimanHom (SubmonoidClass.subtype s) (mapsTo_univ ..) + end CommMonoid section CancelCommMonoid diff --git a/Mathlib/Combinatorics/Colex.lean b/Mathlib/Combinatorics/Colex.lean index 0d59516a64ae1..54e26b8a2cc4c 100644 --- a/Mathlib/Combinatorics/Colex.lean +++ b/Mathlib/Combinatorics/Colex.lean @@ -65,7 +65,7 @@ namespace Finset /-- Type synonym of `Finset α` equipped with the colexicographic order rather than the inclusion order. -/ @[ext] -structure Colex (α) := +structure Colex (α) where /-- `toColex` is the "identity" function between `Finset α` and `Finset.Colex α`. -/ toColex :: /-- `ofColex` is the "identity" function between `Finset.Colex α` and `Finset α`. -/ diff --git a/Mathlib/Combinatorics/Configuration.lean b/Mathlib/Combinatorics/Configuration.lean index aabfcf9052b58..a703f011ed4da 100644 --- a/Mathlib/Combinatorics/Configuration.lean +++ b/Mathlib/Combinatorics/Configuration.lean @@ -128,7 +128,7 @@ theorem Nondegenerate.exists_injective_of_card_le [Nondegenerate P L] [Fintype P by_cases hs₁ : s.card = 1 -- If `s = {l}`, then pick a point `p ∉ l` · obtain ⟨l, rfl⟩ := Finset.card_eq_one.mp hs₁ - obtain ⟨p, hl⟩ := exists_point l + obtain ⟨p, hl⟩ := exists_point (P := P) l rw [Finset.card_singleton, Finset.singleton_biUnion, Nat.one_le_iff_ne_zero] exact Finset.card_ne_zero_of_mem (Set.mem_toFinset.mpr hl) suffices (s.biUnion t)ᶜ.card ≤ sᶜ.card by diff --git a/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean b/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean index 542deff1911e1..0264391a00385 100644 --- a/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean +++ b/Mathlib/Combinatorics/Enumerative/DoubleCounting.lean @@ -39,7 +39,7 @@ namespace Finset section Bipartite -variable (r : α → β → Prop) (s : Finset α) (t : Finset β) (a a' : α) (b b' : β) +variable (r : α → β → Prop) (s : Finset α) (t : Finset β) (a : α) (b : β) [DecidablePred (r a)] [∀ a, Decidable (r a b)] {m n : ℕ} /-- Elements of `s` which are "below" `b` according to relation `r`. -/ @@ -58,7 +58,7 @@ theorem coe_bipartiteBelow : s.bipartiteBelow r b = ({a ∈ s | r a b} : Set α) @[simp, norm_cast] theorem coe_bipartiteAbove : t.bipartiteAbove r a = ({b ∈ t | r a b} : Set β) := coe_filter _ _ -variable {s t a a' b b'} +variable {s t a b} @[simp] theorem mem_bipartiteBelow {a : α} : a ∈ s.bipartiteBelow r b ↔ a ∈ s ∧ r a b := mem_filter @@ -72,7 +72,7 @@ theorem sum_card_bipartiteAbove_eq_sum_card_bipartiteBelow [∀ a b, Decidable ( exact sum_comm section OrderedSemiring -variable [OrderedSemiring R] [DecidablePred (r a)] [∀ a, Decidable (r a b)] {m n : R} +variable [OrderedSemiring R] {m n : R} /-- **Double counting** argument. @@ -100,7 +100,7 @@ end OrderedSemiring section StrictOrderedSemiring variable [StrictOrderedSemiring R] (r : α → β → Prop) {s : Finset α} {t : Finset β} - (a a' : α) (b b' : β) [DecidablePred (r a)] [∀ a, Decidable (r a b)] {m n : R} + (a b) {m n : R} /-- **Double counting** argument. diff --git a/Mathlib/Combinatorics/Enumerative/DyckWord.lean b/Mathlib/Combinatorics/Enumerative/DyckWord.lean index ab393d095b11c..220e3d4c4f141 100644 --- a/Mathlib/Combinatorics/Enumerative/DyckWord.lean +++ b/Mathlib/Combinatorics/Enumerative/DyckWord.lean @@ -291,7 +291,7 @@ lemma count_take_firstReturn_add_one : lemma count_D_lt_count_U_of_lt_firstReturn {i : ℕ} (hi : i < p.firstReturn) : (p.toList.take (i + 1)).count D < (p.toList.take (i + 1)).count U := by have ne := not_of_lt_findIdx hi - rw [decide_eq_true_eq, ← ne_eq, getElem_range] at ne + rw [decide_eq_false_iff_not, ← ne_eq, getElem_range] at ne exact lt_of_le_of_ne (p.count_D_le_count_U (i + 1)) ne.symm @[simp] @@ -307,7 +307,7 @@ lemma firstReturn_add : (p + q).firstReturn = if p = 0 then q.firstReturn else p · intro j hj rw [take_append_eq_append_take, show j + 1 - p.toList.length = 0 by omega, take_zero, append_nil] - exact (count_D_lt_count_U_of_lt_firstReturn hj).ne' + simpa using (count_D_lt_count_U_of_lt_firstReturn hj).ne' · rw [length_range, u, length_append] exact Nat.lt_add_right _ (firstReturn_lt_length h) @@ -323,6 +323,7 @@ lemma firstReturn_nest : p.nest.firstReturn = p.toList.length + 1 := by beq_iff_eq, reduceCtorEq, ite_false, take_append_eq_append_take, show j - p.toList.length = 0 by omega, take_zero, append_nil] have := p.count_D_le_count_U j + simp only [add_zero, decide_eq_false_iff_not, ne_eq] omega · simp_rw [length_range, u, length_append, length_cons] exact Nat.lt_add_one _ diff --git a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean index eee23c4281a09..956feba606f04 100644 --- a/Mathlib/Combinatorics/Optimization/ValuedCSP.lean +++ b/Mathlib/Combinatorics/Optimization/ValuedCSP.lean @@ -134,7 +134,7 @@ lemma Function.HasMaxCutPropertyAt.rows_lt_aux {r : Fin 2 → D} (rin : r ∈ (ω.tt ![![a, b], ![b, a]])) : f ![a, b] < f r := by rw [FractionalOperation.tt, Multiset.mem_map] at rin - rw [show r = ![r 0, r 1] from List.ofFn_inj.mp rfl] + rw [show r = ![r 0, r 1] by simp [← List.ofFn_inj]] apply lt_of_le_of_ne (mcf.right (r 0) (r 1)).left intro equ have asymm : r 0 ≠ r 1 := by @@ -146,7 +146,7 @@ lemma Function.HasMaxCutPropertyAt.rows_lt_aux apply asymm obtain ⟨o, in_omega, rfl⟩ := rin show o (fun j => ![![a, b], ![b, a]] j 0) = o (fun j => ![![a, b], ![b, a]] j 1) - convert symmega ![a, b] ![b, a] (List.Perm.swap b a []) o in_omega using 2 <;> + convert symmega ![a, b] ![b, a] (by simp [List.Perm.swap]) o in_omega using 2 <;> simp [Matrix.const_fin1_eq] lemma Function.HasMaxCutProperty.forbids_commutativeFractionalPolymorphism @@ -159,10 +159,10 @@ lemma Function.HasMaxCutProperty.forbids_commutativeFractionalPolymorphism rw [Fin.sum_univ_two', ← mcfab.left, ← two_nsmul] at contr have sharp : 2 • ((ω.tt ![![a, b], ![b, a]]).map (fun _ => f ![a, b])).sum < - 2 • ((ω.tt ![![a, b], ![b, a]]).map (fun r => f r)).sum := by + 2 • ((ω.tt ![![a, b], ![b, a]]).map f).sum := by have half_sharp : ((ω.tt ![![a, b], ![b, a]]).map (fun _ => f ![a, b])).sum < - ((ω.tt ![![a, b], ![b, a]]).map (fun r => f r)).sum := by + ((ω.tt ![![a, b], ![b, a]]).map f).sum := by apply Multiset.sum_lt_sum · intro r rin exact le_of_lt (mcfab.rows_lt_aux hab symmega rin) diff --git a/Mathlib/Combinatorics/Quiver/ReflQuiver.lean b/Mathlib/Combinatorics/Quiver/ReflQuiver.lean new file mode 100644 index 0000000000000..b0f9c85ac7250 --- /dev/null +++ b/Mathlib/Combinatorics/Quiver/ReflQuiver.lean @@ -0,0 +1,131 @@ +/- +Copyright (c) 2024 Mario Carneiro and Emily Riehl. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Mario Carneiro, Emily Riehl +-/ +import Mathlib.Data.Set.Function +import Mathlib.CategoryTheory.Category.Cat + +/-! +# Reflexive Quivers + +This module defines reflexive quivers. A reflexive quiver, or "refl quiver" for short, extends +a quiver with a specified endoarrow on each term in its type of objects. + +We also introduce morphisms between reflexive quivers, called reflexive prefunctors or "refl +prefunctors" for short. + +Note: Currently Category does not extend ReflQuiver, although it could. (TODO: do this) +-/ +namespace CategoryTheory +universe v v₁ v₂ u u₁ u₂ + +/-- A reflexive quiver extends a quiver with a specified arrow `id X : X ⟶ X` for each `X` in its +type of objects. We denote these arrows by `id` since categories can be understood as an extension +of refl quivers. +-/ +class ReflQuiver (obj : Type u) extends Quiver.{v} obj : Type max u v where + /-- The identity morphism on an object. -/ + id : ∀ X : obj, Hom X X + +/-- Notation for the identity morphism in a category. -/ +scoped notation "𝟙rq" => ReflQuiver.id -- type as \b1 + +instance catToReflQuiver {C : Type u} [inst : Category.{v} C] : ReflQuiver.{v+1, u} C := + { inst with } + +@[simp] theorem ReflQuiver.id_eq_id {C : Type*} [Category C] (X : C) : 𝟙rq X = 𝟙 X := rfl + +/-- A morphism of reflexive quivers called a `ReflPrefunctor`. -/ +structure ReflPrefunctor (V : Type u₁) [ReflQuiver.{v₁} V] (W : Type u₂) [ReflQuiver.{v₂} W] + extends Prefunctor V W where + /-- A functor preserves identity morphisms. -/ + map_id : ∀ X : V, map (𝟙rq X) = 𝟙rq (obj X) := by aesop_cat + +namespace ReflPrefunctor + +-- These lemmas can not be `@[simp]` because after `whnfR` they have a variable on the LHS. +-- Nevertheless they are sometimes useful when building functors. +lemma mk_obj {V W : Type*} [ReflQuiver V] [ReflQuiver W] {obj : V → W} {map} {X : V} : + (Prefunctor.mk obj map).obj X = obj X := rfl + +lemma mk_map {V W : Type*} [ReflQuiver V] [ReflQuiver W] {obj : V → W} {map} {X Y : V} {f : X ⟶ Y} : + (Prefunctor.mk obj map).map f = map f := rfl + +/-- Proving equality between reflexive prefunctors. This isn't an extensionality lemma, + because usually you don't really want to do this. -/ +theorem ext {V : Type u} [ReflQuiver.{v₁} V] {W : Type u₂} [ReflQuiver.{v₂} W] + {F G : ReflPrefunctor V W} + (h_obj : ∀ X, F.obj X = G.obj X) + (h_map : ∀ (X Y : V) (f : X ⟶ Y), + F.map f = Eq.recOn (h_obj Y).symm (Eq.recOn (h_obj X).symm (G.map f))) : F = G := by + obtain ⟨⟨F_obj⟩⟩ := F + obtain ⟨⟨G_obj⟩⟩ := G + obtain rfl : F_obj = G_obj := (Set.eqOn_univ F_obj G_obj).mp fun _ _ ↦ h_obj _ + congr + funext X Y f + simpa using h_map X Y f + +/-- The identity morphism between reflexive quivers. -/ +@[simps!] +def id (V : Type*) [ReflQuiver V] : ReflPrefunctor V V where + __ := Prefunctor.id _ + map_id _ := rfl + +instance (V : Type*) [ReflQuiver V] : Inhabited (ReflPrefunctor V V) := + ⟨id V⟩ + +/-- Composition of morphisms between reflexive quivers. -/ +@[simps!] +def comp {U : Type*} [ReflQuiver U] {V : Type*} [ReflQuiver V] {W : Type*} [ReflQuiver W] + (F : ReflPrefunctor U V) (G : ReflPrefunctor V W) : ReflPrefunctor U W where + __ := F.toPrefunctor.comp G.toPrefunctor + map_id _ := by simp [F.map_id, G.map_id] + +@[simp] +theorem comp_id {U V : Type*} [ReflQuiver U] [ReflQuiver V] (F : ReflPrefunctor U V) : + F.comp (id _) = F := rfl + +@[simp] +theorem id_comp {U V : Type*} [ReflQuiver U] [ReflQuiver V] (F : ReflPrefunctor U V) : + (id _).comp F = F := rfl + +@[simp] +theorem comp_assoc {U V W Z : Type*} [ReflQuiver U] [ReflQuiver V] [ReflQuiver W] [ReflQuiver Z] + (F : ReflPrefunctor U V) (G : ReflPrefunctor V W) (H : ReflPrefunctor W Z) : + (F.comp G).comp H = F.comp (G.comp H) := rfl + +/-- Notation for a prefunctor between reflexive quivers. -/ +infixl:50 " ⥤rq " => ReflPrefunctor + +/-- Notation for composition of reflexive prefunctors. -/ +infixl:60 " ⋙rq " => ReflPrefunctor.comp + +/-- Notation for the identity prefunctor on a reflexive quiver. -/ +notation "𝟭rq" => id + +theorem congr_map {U V : Type*} [Quiver U] [Quiver V] (F : U ⥤q V) {X Y : U} {f g : X ⟶ Y} + (h : f = g) : F.map f = F.map g := congrArg F.map h + +end ReflPrefunctor + +/-- A functor has an underlying refl prefunctor.-/ +def Functor.toReflPrefunctor {C D} [Category C] [Category D] (F : C ⥤ D) : C ⥤rq D := { F with } + +@[simp] +theorem Functor.toReflPrefunctor_toPrefunctor {C D : Cat} (F : C ⥤ D) : + (Functor.toReflPrefunctor F).toPrefunctor = F.toPrefunctor := rfl + +namespace ReflQuiver +open Opposite + +/-- `Vᵒᵖ` reverses the direction of all arrows of `V`. -/ +instance opposite {V} [ReflQuiver V] : ReflQuiver Vᵒᵖ where + id X := op (𝟙rq X.unop) + +instance discreteReflQuiver (V : Type u) : ReflQuiver.{u+1} (Discrete V) := + { discreteCategory V with } + +end ReflQuiver + +end CategoryTheory diff --git a/Mathlib/Combinatorics/Schnirelmann.lean b/Mathlib/Combinatorics/Schnirelmann.lean index d56f44bd816ff..266093dff23ab 100644 --- a/Mathlib/Combinatorics/Schnirelmann.lean +++ b/Mathlib/Combinatorics/Schnirelmann.lean @@ -196,7 +196,7 @@ lemma schnirelmannDensity_finset (A : Finset ℕ) : schnirelmannDensity A = 0 := let n : ℕ := ⌊A.card / ε⌋₊ + 1 have hn : 0 < n := Nat.succ_pos _ use n, hn - rw [div_lt_iff (Nat.cast_pos.2 hn), ← div_lt_iff' hε, Nat.cast_add_one] + rw [div_lt_iff₀ (Nat.cast_pos.2 hn), ← div_lt_iff₀' hε, Nat.cast_add_one] exact (Nat.lt_floor_add_one _).trans_le' <| by gcongr; simp [subset_iff] /-- The Schnirelmann density of any finite set is `0`. -/ diff --git a/Mathlib/Combinatorics/SetFamily/Compression/Down.lean b/Mathlib/Combinatorics/SetFamily/Compression/Down.lean index 222c68d63fd87..a93982a2764cf 100644 --- a/Mathlib/Combinatorics/SetFamily/Compression/Down.lean +++ b/Mathlib/Combinatorics/SetFamily/Compression/Down.lean @@ -35,7 +35,7 @@ compression, down-compression -/ -variable {α : Type*} [DecidableEq α] {𝒜 ℬ : Finset (Finset α)} {s : Finset α} {a : α} +variable {α : Type*} [DecidableEq α] {𝒜 : Finset (Finset α)} {s : Finset α} {a : α} namespace Finset diff --git a/Mathlib/Combinatorics/SetFamily/Kleitman.lean b/Mathlib/Combinatorics/SetFamily/Kleitman.lean index 7fe6c323c2871..e534f30f51b45 100644 --- a/Mathlib/Combinatorics/SetFamily/Kleitman.lean +++ b/Mathlib/Combinatorics/SetFamily/Kleitman.lean @@ -79,5 +79,5 @@ theorem Finset.card_biUnion_le_of_intersecting (s : Finset ι) (f : ι → Finse (ih _ (fun i hi ↦ (hf₁ _ <| subset_cons _ hi).2.2) ((card_le_card <| subset_cons _).trans hs)) _).trans ?_ rw [mul_tsub, two_mul, ← pow_succ', - ← add_tsub_assoc_of_le (pow_le_pow_right' (one_le_two : (1 : ℕ) ≤ 2) tsub_le_self), + ← add_tsub_assoc_of_le (pow_right_mono₀ (one_le_two : (1 : ℕ) ≤ 2) tsub_le_self), tsub_add_eq_add_tsub hs, card_cons, add_tsub_add_eq_tsub_right] diff --git a/Mathlib/Combinatorics/SetFamily/Shadow.lean b/Mathlib/Combinatorics/SetFamily/Shadow.lean index bc4f6f690c062..a3b293b819c4c 100644 --- a/Mathlib/Combinatorics/SetFamily/Shadow.lean +++ b/Mathlib/Combinatorics/SetFamily/Shadow.lean @@ -75,7 +75,10 @@ theorem shadow_empty : ∂ (∅ : Finset (Finset α)) = ∅ := theorem shadow_singleton_empty : ∂ ({∅} : Finset (Finset α)) = ∅ := rfl ---TODO: Prove `∂ {{a}} = {∅}` quickly using `covers` and `GradeOrder` +@[simp] +theorem shadow_singleton (a : α) : ∂ {{a}} = {∅} := by + simp [shadow] + /-- The shadow is monotone. -/ @[mono] theorem shadow_monotone : Monotone (shadow : Finset (Finset α) → Finset (Finset α)) := fun _ _ => diff --git a/Mathlib/Combinatorics/SetFamily/Shatter.lean b/Mathlib/Combinatorics/SetFamily/Shatter.lean index 6efd8f20ec42e..74f21f70fbc02 100644 --- a/Mathlib/Combinatorics/SetFamily/Shatter.lean +++ b/Mathlib/Combinatorics/SetFamily/Shatter.lean @@ -79,7 +79,7 @@ def shatterer (𝒜 : Finset (Finset α)) : Finset (Finset α) := (𝒜.biUnion simp_rw [mem_biUnion, mem_powerset] exact h.exists_superset -lemma shatterer_mono (h : 𝒜 ⊆ ℬ) : 𝒜.shatterer ⊆ ℬ.shatterer := +@[gcongr] lemma shatterer_mono (h : 𝒜 ⊆ ℬ) : 𝒜.shatterer ⊆ ℬ.shatterer := fun _ ↦ by simpa using Shatters.mono_left h lemma subset_shatterer (h : IsLowerSet (𝒜 : Set (Finset α))) : 𝒜 ⊆ 𝒜.shatterer := @@ -181,6 +181,8 @@ lemma shatterer_compress_subset_shatterer (a : α) (𝒜 : Finset (Finset α)) : /-- The Vapnik-Chervonenkis dimension of a set family is the maximal size of a set it shatters. -/ def vcDim (𝒜 : Finset (Finset α)) : ℕ := 𝒜.shatterer.sup card +@[gcongr] lemma vcDim_mono (h𝒜ℬ : 𝒜 ⊆ ℬ) : 𝒜.vcDim ≤ ℬ.vcDim := by unfold vcDim; gcongr + lemma Shatters.card_le_vcDim (hs : 𝒜.Shatters s) : s.card ≤ 𝒜.vcDim := le_sup <| mem_shatterer.2 hs /-- Down-compressing decreases the VC-dimension. -/ diff --git a/Mathlib/Combinatorics/SimpleGraph/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Basic.lean index fd971bdfc268e..ed55cb02e74c6 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Basic.lean @@ -518,7 +518,7 @@ variable (G G₁ G₂) theorem edge_other_ne {e : Sym2 V} (he : e ∈ G.edgeSet) {v : V} (h : v ∈ e) : Sym2.Mem.other h ≠ v := by - erw [← Sym2.other_spec h, Sym2.eq_swap] at he + rw [← Sym2.other_spec h, Sym2.eq_swap] at he exact G.ne_of_adj he instance decidableMemEdgeSet [DecidableRel G.Adj] : DecidablePred (· ∈ G.edgeSet) := diff --git a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean index dabe8553d196a..121f720ec7a12 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Circulant.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Circulant.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Iván Renison, Bhavik Mehta. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Iván Renison, Bhavik Mehta -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Combinatorics.SimpleGraph.Hasse /-! diff --git a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean index 868f25e9ef0db..4b09938bdf173 100644 --- a/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean +++ b/Mathlib/Combinatorics/SimpleGraph/DegreeSum.lean @@ -6,7 +6,7 @@ Authors: Kyle Miller import Mathlib.Algebra.BigOperators.Ring import Mathlib.Combinatorics.SimpleGraph.Dart import Mathlib.Combinatorics.SimpleGraph.Finite -import Mathlib.Data.ZMod.Parity +import Mathlib.Data.ZMod.Basic /-! # Degree-sum formula and handshaking lemma diff --git a/Mathlib/Combinatorics/SimpleGraph/Density.lean b/Mathlib/Combinatorics/SimpleGraph/Density.lean index 6f388c7ffd277..f71bb81713dbb 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Density.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Density.lean @@ -122,7 +122,7 @@ theorem edgeDensity_nonneg (s : Finset α) (t : Finset β) : 0 ≤ edgeDensity r apply div_nonneg <;> exact mod_cast Nat.zero_le _ theorem edgeDensity_le_one (s : Finset α) (t : Finset β) : edgeDensity r s t ≤ 1 := by - apply div_le_one_of_le + apply div_le_one_of_le₀ · exact mod_cast card_interedges_le_mul r s t · exact mod_cast Nat.zero_le _ @@ -175,10 +175,10 @@ theorem edgeDensity_sub_edgeDensity_le_one_sub_mul (hs : s₂ ⊆ s₁) (ht : t refine (sub_le_sub_left (mul_edgeDensity_le_edgeDensity r hs ht hs₂ ht₂) _).trans ?_ refine le_trans ?_ (mul_le_of_le_one_right ?_ (edgeDensity_le_one r s₂ t₂)) · rw [sub_mul, one_mul] - refine sub_nonneg_of_le (mul_le_one ?_ ?_ ?_) - · exact div_le_one_of_le ((@Nat.cast_le ℚ).2 (card_le_card hs)) (Nat.cast_nonneg _) + refine sub_nonneg_of_le (mul_le_one₀ ?_ ?_ ?_) + · exact div_le_one_of_le₀ ((@Nat.cast_le ℚ).2 (card_le_card hs)) (Nat.cast_nonneg _) · apply div_nonneg <;> exact mod_cast Nat.zero_le _ - · exact div_le_one_of_le ((@Nat.cast_le ℚ).2 (card_le_card ht)) (Nat.cast_nonneg _) + · exact div_le_one_of_le₀ ((@Nat.cast_le ℚ).2 (card_le_card ht)) (Nat.cast_nonneg _) theorem abs_edgeDensity_sub_edgeDensity_le_one_sub_mul (hs : s₂ ⊆ s₁) (ht : t₂ ⊆ t₁) (hs₂ : s₂.Nonempty) (ht₂ : t₂.Nonempty) : diff --git a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean index e5a841272ed81..085bfd8720ab2 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Ends/Defs.lean @@ -179,12 +179,12 @@ theorem hom_eq_iff_not_disjoint (C : G.ComponentCompl L) (h : K ⊆ L) (D : G.Co theorem hom_refl (C : G.ComponentCompl L) : C.hom (subset_refl L) = C := by change C.map _ = C - erw [induceHom_id G Lᶜ, ConnectedComponent.map_id] + rw [induceHom_id G Lᶜ, ConnectedComponent.map_id] theorem hom_trans (C : G.ComponentCompl L) (h : K ⊆ L) (h' : M ⊆ K) : C.hom (h'.trans h) = (C.hom h).hom h' := by change C.map _ = (C.map _).map _ - erw [ConnectedComponent.map_comp, induceHom_comp] + rw [ConnectedComponent.map_comp, induceHom_comp] rfl theorem hom_mk {v : V} (vnL : v ∉ L) (h : K ⊆ L) : diff --git a/Mathlib/Combinatorics/SimpleGraph/Finite.lean b/Mathlib/Combinatorics/SimpleGraph/Finite.lean index 278ba02e0df80..3ed8afcfac7a8 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Finite.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Finite.lean @@ -92,6 +92,15 @@ theorem edgeFinset_inf [DecidableEq V] : (G₁ ⊓ G₂).edgeFinset = G₁.edgeF theorem edgeFinset_sdiff [DecidableEq V] : (G₁ \ G₂).edgeFinset = G₁.edgeFinset \ G₂.edgeFinset := by simp [edgeFinset] +lemma disjoint_edgeFinset : Disjoint G₁.edgeFinset G₂.edgeFinset ↔ Disjoint G₁ G₂ := by + simp_rw [← Finset.disjoint_coe, coe_edgeFinset, disjoint_edgeSet] + +lemma edgeFinset_eq_empty : G.edgeFinset = ∅ ↔ G = ⊥ := by + rw [← edgeFinset_bot, edgeFinset_inj] + +lemma edgeFinset_nonempty : G.edgeFinset.Nonempty ↔ G ≠ ⊥ := by + rw [Finset.nonempty_iff_ne_empty, edgeFinset_eq_empty.ne] + theorem edgeFinset_card : G.edgeFinset.card = Fintype.card G.edgeSet := Set.toFinset_card _ @@ -408,7 +417,7 @@ the best we can do in general. -/ theorem Adj.card_commonNeighbors_lt_degree {G : SimpleGraph V} [DecidableRel G.Adj] {v w : V} (h : G.Adj v w) : Fintype.card (G.commonNeighbors v w) < G.degree v := by classical - erw [← Set.toFinset_card] + rw [← Set.toFinset_card] apply Finset.card_lt_card rw [Finset.ssubset_iff] use w diff --git a/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean b/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean index 0cb730278bd98..c5f35dfab6814 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean @@ -36,7 +36,7 @@ lemma IsHamiltonian.map {H : SimpleGraph β} (f : G →g H) (hf : Bijective f) ( /-- A hamiltonian path visits every vertex. -/ @[simp] lemma IsHamiltonian.mem_support (hp : p.IsHamiltonian) (c : α) : c ∈ p.support := by - simp only [← List.count_pos_iff_mem, hp _, Nat.zero_lt_one] + simp only [← List.count_pos_iff, hp _, Nat.zero_lt_one] /-- Hamiltonian paths are paths. -/ lemma IsHamiltonian.isPath (hp : p.IsHamiltonian) : p.IsPath := @@ -45,7 +45,7 @@ lemma IsHamiltonian.isPath (hp : p.IsHamiltonian) : p.IsPath := /-- A path whose support contains every vertex is hamiltonian. -/ lemma IsPath.isHamiltonian_of_mem (hp : p.IsPath) (hp' : ∀ w, w ∈ p.support) : p.IsHamiltonian := fun _ ↦ - le_antisymm (List.nodup_iff_count_le_one.1 hp.support_nodup _) (List.count_pos_iff_mem.2 (hp' _)) + le_antisymm (List.nodup_iff_count_le_one.1 hp.support_nodup _) (List.count_pos_iff.2 (hp' _)) lemma IsPath.isHamiltonian_iff (hp : p.IsPath) : p.IsHamiltonian ↔ ∀ w, w ∈ p.support := ⟨(·.mem_support), hp.isHamiltonian_of_mem⟩ @@ -66,7 +66,7 @@ lemma IsHamiltonian.length_eq (hp : p.IsHamiltonian) : p.length = Fintype.card end /-- A hamiltonian cycle is a cycle that visits every vertex once. -/ -structure IsHamiltonianCycle (p : G.Walk a a) extends p.IsCycle : Prop := +structure IsHamiltonianCycle (p : G.Walk a a) extends p.IsCycle : Prop where isHamiltonian_tail : p.tail.IsHamiltonian variable {p : G.Walk a a} @@ -78,7 +78,7 @@ lemma IsHamiltonianCycle.map {H : SimpleGraph β} (f : G →g H) (hf : Bijective (hp : p.IsHamiltonianCycle) : (p.map f).IsHamiltonianCycle where toIsCycle := hp.isCycle.map hf.injective isHamiltonian_tail := by - simp only [IsHamiltonian, support_tail, support_map, ne_eq, List.map_eq_nil, support_ne_nil, + simp only [IsHamiltonian, support_tail, support_map, ne_eq, List.map_eq_nil_iff, support_ne_nil, not_false_eq_true, List.count_tail, List.head_map, beq_iff_eq, hf.surjective.forall, hf.injective, List.count_map_of_injective] intro x diff --git a/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean b/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean index 40f0ebf38db1e..e609a7dee3f0e 100644 --- a/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean +++ b/Mathlib/Combinatorics/SimpleGraph/LapMatrix.lean @@ -189,8 +189,8 @@ end /-- The number of connected components in `G` is the dimension of the nullspace its Laplacian. -/ theorem card_ConnectedComponent_eq_rank_ker_lapMatrix : Fintype.card G.ConnectedComponent = - FiniteDimensional.finrank ℝ (LinearMap.ker (Matrix.toLin' (G.lapMatrix ℝ))) := by + Module.finrank ℝ (LinearMap.ker (Matrix.toLin' (G.lapMatrix ℝ))) := by classical - rw [FiniteDimensional.finrank_eq_card_basis (lapMatrix_ker_basis G)] + rw [Module.finrank_eq_card_basis (lapMatrix_ker_basis G)] end SimpleGraph diff --git a/Mathlib/Combinatorics/SimpleGraph/Path.lean b/Mathlib/Combinatorics/SimpleGraph/Path.lean index 9a5f20e639064..f40c73152000a 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Path.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Path.lean @@ -590,7 +590,7 @@ end Path namespace Walk variable {G} {p} {u v : V} {H : SimpleGraph V} -variable (p : G.Walk u v) +variable {p : G.Walk u v} protected theorem IsPath.transfer (hp) (pp : p.IsPath) : (p.transfer H hp).IsPath := by diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean index bd6d68eeeb2dd..5ee0f683c85af 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Bound.lean @@ -117,7 +117,7 @@ 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 + (div_le_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] @@ -126,10 +126,10 @@ theorem hundred_le_m [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ (hPε : 100 ≤ (4 : ℝ) ^ P.parts.card * ε ^ 5) (hε : ε ≤ 1) : 100 ≤ m := mod_cast (hundred_div_ε_pow_five_le_m hPα hPε).trans' - (le_div_self (by norm_num) (by sz_positivity) <| pow_le_one _ (by sz_positivity) hε) + (le_div_self (by norm_num) (by sz_positivity) <| pow_le_one₀ (by sz_positivity) hε) theorem a_add_one_le_four_pow_parts_card : a + 1 ≤ 4 ^ P.parts.card := by - have h : 1 ≤ 4 ^ P.parts.card := one_le_pow_of_one_le (by norm_num) _ + have h : 1 ≤ 4 ^ P.parts.card := one_le_pow₀ (by norm_num) rw [stepBound, ← Nat.div_div_eq_div_mul] conv_rhs => rw [← Nat.sub_add_cancel h] rw [add_le_add_iff_right, tsub_le_iff_left, ← Nat.add_sub_assoc h] @@ -175,8 +175,8 @@ theorem initialBound_pos : 0 < initialBound ε l := theorem hundred_lt_pow_initialBound_mul {ε : ℝ} (hε : 0 < ε) (l : ℕ) : 100 < ↑4 ^ initialBound ε l * ε ^ 5 := by - rw [← rpow_natCast 4, ← div_lt_iff (pow_pos hε 5), lt_rpow_iff_log_lt _ zero_lt_four, ← - div_lt_iff, initialBound, Nat.cast_max, Nat.cast_max] + rw [← rpow_natCast 4, ← div_lt_iff₀ (pow_pos hε 5), lt_rpow_iff_log_lt _ zero_lt_four, ← + div_lt_iff₀, initialBound, Nat.cast_max, Nat.cast_max] · push_cast exact lt_max_of_lt_right (lt_max_of_lt_right <| Nat.lt_floor_add_one _) · exact log_pos (by norm_num) diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean index 4ffe166e5b4b8..14c2df9eb7249 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Chunk.lean @@ -114,7 +114,7 @@ private theorem card_nonuniformWitness_sdiff_biUnion_star (hV : V ∈ P.parts) ( rw [sum_const] refine mul_le_mul_right' ?_ _ have t := card_filter_atomise_le_two_pow (s := U) hX - refine t.trans (pow_le_pow_right (by norm_num) <| tsub_le_tsub_right ?_ _) + refine t.trans (pow_right_mono₀ (by norm_num) <| tsub_le_tsub_right ?_ _) exact card_image_le.trans (card_le_card <| filter_subset _ _) private theorem one_sub_eps_mul_card_nonuniformWitness_le_card_star (hV : V ∈ P.parts) @@ -132,7 +132,7 @@ private theorem one_sub_eps_mul_card_nonuniformWitness_le_card_star (hV : V ∈ ((2 : ℝ) * 2) ^ P.parts.card * m / U.card := by rw [mul_pow, ← mul_div_assoc, mul_assoc] _ = ↑4 ^ P.parts.card * m / U.card := by norm_num - _ ≤ 1 := div_le_one_of_le (pow_mul_m_le_card_part hP hU) (cast_nonneg _) + _ ≤ 1 := div_le_one_of_le₀ (pow_mul_m_le_card_part hP hU) (cast_nonneg _) _ ≤ ↑2 ^ P.parts.card * ε ^ 2 / 10 := by refine (one_le_sq_iff <| by positivity).1 ?_ rw [div_pow, mul_pow, pow_right_comm, ← pow_mul ε, @@ -240,7 +240,7 @@ private theorem m_add_one_div_m_le_one_add [Nonempty α] div_eq_mul_one_div _ (49 : ℝ), mul_div_left_comm (2 : ℝ), ← mul_sub_left_distrib, div_pow, div_le_iff₀ (show (0 : ℝ) < ↑100 ^ 2 by norm_num), mul_assoc, sq] refine mul_le_mul_of_nonneg_left ?_ (by sz_positivity) - exact (pow_le_one 5 (by sz_positivity) hε₁).trans (by norm_num) + exact (pow_le_one₀ (by sz_positivity) hε₁).trans (by norm_num) private theorem density_sub_eps_le_sum_density_div_card [Nonempty α] (hPα : P.parts.card * 16 ^ P.parts.card ≤ card α) (hPε : ↑100 ≤ ↑4 ^ P.parts.card * ε ^ 5) @@ -269,7 +269,7 @@ private theorem density_sub_eps_le_sum_density_div_card [Nonempty α] rw [mul_mul_mul_comm, mul_comm (x.card : ℝ), mul_comm (y.card : ℝ), le_div_iff₀, mul_assoc] · refine mul_le_of_le_one_right (cast_nonneg _) ?_ rw [div_mul_eq_mul_div, ← mul_assoc, mul_assoc] - refine div_le_one_of_le ?_ (by positivity) + refine div_le_one_of_le₀ ?_ (by positivity) refine (mul_le_mul_of_nonneg_right (one_sub_le_m_div_m_add_one_sq hPα hPε) ?_).trans ?_ · exact mod_cast _root_.zero_le _ rw [sq, mul_mul_mul_comm, mul_comm ((m : ℝ) / _), mul_comm ((m : ℝ) / _)] @@ -379,9 +379,9 @@ private theorem eps_le_card_star_div [Nonempty α] (hPα : P.parts.card * 16 ^ P (hPε : ↑100 ≤ ↑4 ^ P.parts.card * ε ^ 5) (hε₁ : ε ≤ 1) (hU : U ∈ P.parts) (hV : V ∈ P.parts) (hUV : U ≠ V) (hunif : ¬G.IsUniform ε U V) : ↑4 / ↑5 * ε ≤ (star hP G ε hU V).card / ↑4 ^ P.parts.card := by - have hm : (0 : ℝ) ≤ 1 - (↑m)⁻¹ := sub_nonneg_of_le (inv_le_one <| one_le_m_coe hPα) + have hm : (0 : ℝ) ≤ 1 - (↑m)⁻¹ := sub_nonneg_of_le (inv_le_one_of_one_le₀ <| one_le_m_coe hPα) have hε : 0 ≤ 1 - ε / 10 := - sub_nonneg_of_le (div_le_one_of_le (hε₁.trans <| by norm_num) <| by norm_num) + sub_nonneg_of_le (div_le_one_of_le₀ (hε₁.trans <| by norm_num) <| by norm_num) have hε₀ : 0 < ε := by sz_positivity calc 4 / 5 * ε = (1 - 1 / 10) * (1 - 9⁻¹) * ε := by norm_num diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean index 64284f427847f..2691d38a6f4b2 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Energy.lean @@ -40,7 +40,7 @@ theorem energy_nonneg : 0 ≤ P.energy G := by exact div_nonneg (Finset.sum_nonneg fun _ _ => sq_nonneg _) <| sq_nonneg _ theorem energy_le_one : P.energy G ≤ 1 := - div_le_of_nonneg_of_le_mul (sq_nonneg _) zero_le_one <| + div_le_of_le_mul₀ (sq_nonneg _) zero_le_one <| calc ∑ uv ∈ P.parts.offDiag, G.edgeDensity uv.1 uv.2 ^ 2 ≤ P.parts.offDiag.card • (1 : ℚ) := sum_le_card_nsmul _ _ 1 fun uv _ => diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean index d0c4c37b647fa..96d140587f9cc 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Equitabilise.lean @@ -45,8 +45,8 @@ theorem equitabilise_aux (hs : a * m + b * (m + 1) = s.card) : -- Get rid of the easy case `m = 0` obtain rfl | m_pos := m.eq_zero_or_pos · refine ⟨⊥, by simp, ?_, by simpa [Finset.filter_true_of_mem] using hs.symm⟩ - simp only [le_zero_iff, card_eq_zero, mem_biUnion, exists_prop, mem_filter, id, and_assoc, - sdiff_eq_empty_iff_subset, subset_iff] + simp only [le_zero_iff, card_eq_zero, mem_biUnion, exists_prop, mem_filter, id, + and_assoc, sdiff_eq_empty_iff_subset, subset_iff] exact fun x hx a ha => ⟨{a}, mem_map_of_mem _ (P.le hx ha), singleton_subset_iff.2 ha, mem_singleton_self _⟩ -- Prove the case `m > 0` by strong induction on `s` diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean index 5e120205aeeb8..bee7ea6b54e48 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Lemma.lean @@ -128,7 +128,7 @@ theorem szemeredi_regularity (hε : 0 < ε) (hl : l ≤ card α) : -- We gather a few numerical facts. have hεl' : 100 ≤ 4 ^ P.parts.card * ε ^ 5 := (hundred_lt_pow_initialBound_mul hε l).le.trans - (mul_le_mul_of_nonneg_right (pow_le_pow_right (by norm_num) hP₂) <| by positivity) + (mul_le_mul_of_nonneg_right (pow_right_mono₀ (by norm_num) hP₂) <| by positivity) have hi : (i : ℝ) ≤ 4 / ε ^ 5 := by have hi : ε ^ 5 / 4 * ↑i ≤ 1 := hP₄.trans (mod_cast P.energy_le_one G) rw [div_mul_eq_mul_div, div_le_iff₀ (show (0 : ℝ) < 4 by norm_num)] at hi diff --git a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean index a6610b54a4ade..572c8e65f679c 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Regularity/Uniform.lean @@ -276,7 +276,7 @@ lemma IsEquipartition.card_interedges_sparsePairs_le' (hP : P.IsEquipartition) · gcongr with UV hUV obtain ⟨U, V⟩ := UV simp [mk_mem_sparsePairs, ← card_interedges_div_card] at hUV - refine ((div_lt_iff ?_).1 hUV.2.2.2).le + refine ((div_lt_iff₀ ?_).1 hUV.2.2.2).le exact mul_pos (Nat.cast_pos.2 (P.nonempty_of_mem_parts hUV.1).card_pos) (Nat.cast_pos.2 (P.nonempty_of_mem_parts hUV.2.1).card_pos) norm_cast diff --git a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean index 9d64a2270e2d0..c0cc9e7d6ca21 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Subgraph.lean @@ -133,6 +133,9 @@ theorem coe_adj_sub (G' : Subgraph G) (u v : G'.verts) (h : G'.coe.Adj u v) : G. protected theorem Adj.coe {H : G.Subgraph} {u v : V} (h : H.Adj u v) : H.coe.Adj ⟨u, H.edge_vert h⟩ ⟨v, H.edge_vert h.symm⟩ := h +instance (G : SimpleGraph V) (H : Subgraph G) [DecidableRel H.Adj] : DecidableRel H.coe.Adj := + fun a b ↦ ‹DecidableRel H.Adj› _ _ + /-- A subgraph is called a *spanning subgraph* if it contains all the vertices of `G`. -/ def IsSpanning (G' : Subgraph G) : Prop := ∀ v : V, v ∈ G'.verts @@ -156,6 +159,8 @@ theorem Adj.of_spanningCoe {G' : Subgraph G} {u v : G'.verts} (h : G'.spanningCo G.Adj u v := G'.adj_sub h +lemma spanningCoe_le (G' : G.Subgraph) : G'.spanningCoe ≤ G := fun _ _ ↦ G'.3 + theorem spanningCoe_inj : G₁.spanningCoe = G₂.spanningCoe ↔ G₁.Adj = G₂.Adj := by simp [Subgraph.spanningCoe] @@ -209,15 +214,27 @@ theorem edgeSet_subset (G' : Subgraph G) : G'.edgeSet ⊆ G.edgeSet := Sym2.ind (fun _ _ ↦ G'.adj_sub) @[simp] -theorem mem_edgeSet {G' : Subgraph G} {v w : V} : s(v, w) ∈ G'.edgeSet ↔ G'.Adj v w := Iff.rfl +protected lemma mem_edgeSet {G' : Subgraph G} {v w : V} : s(v, w) ∈ G'.edgeSet ↔ G'.Adj v w := .rfl + +@[simp] lemma edgeSet_coe {G' : G.Subgraph} : G'.coe.edgeSet = Sym2.map (↑) ⁻¹' G'.edgeSet := by + ext e; induction' e using Sym2.ind with a b; simp -theorem mem_verts_if_mem_edge {G' : Subgraph G} {e : Sym2 V} {v : V} (he : e ∈ G'.edgeSet) +lemma image_coe_edgeSet_coe (G' : G.Subgraph) : Sym2.map (↑) '' G'.coe.edgeSet = G'.edgeSet := by + rw [edgeSet_coe, Set.image_preimage_eq_iff] + rintro e he + induction' e using Sym2.ind with a b + rw [Subgraph.mem_edgeSet] at he + exact ⟨s(⟨a, edge_vert _ he⟩, ⟨b, edge_vert _ he.symm⟩), Sym2.map_pair_eq ..⟩ + +theorem mem_verts_of_mem_edge {G' : Subgraph G} {e : Sym2 V} {v : V} (he : e ∈ G'.edgeSet) (hv : v ∈ e) : v ∈ G'.verts := by induction e rcases Sym2.mem_iff.mp hv with (rfl | rfl) · exact G'.edge_vert he · exact G'.edge_vert (G'.symm he) +@[deprecated (since := "2024-10-01")] alias mem_verts_if_mem_edge := mem_verts_of_mem_edge + /-- The `incidenceSet` is the set of edges incident to a given vertex. -/ def incidenceSet (G' : Subgraph G) (v : V) : Set (Sym2 V) := {e ∈ G'.edgeSet | v ∈ e} @@ -377,6 +394,18 @@ theorem verts_iSup {f : ι → G.Subgraph} : (⨆ i, f i).verts = ⋃ i, (f i).v @[simp] theorem verts_iInf {f : ι → G.Subgraph} : (⨅ i, f i).verts = ⋂ i, (f i).verts := by simp [iInf] +@[simp] lemma coe_bot : (⊥ : G.Subgraph).coe = ⊥ := rfl + +@[simp] lemma IsInduced.top : (⊤ : G.Subgraph).IsInduced := fun _ _ ↦ id + +/-- The graph isomorphism between the top element of `G.subgraph` and `G`. -/ +def topIso : (⊤ : G.Subgraph).coe ≃g G where + toFun := (↑) + invFun a := ⟨a, Set.mem_univ _⟩ + left_inv _ := Subtype.eta .. + right_inv _ := rfl + map_rel_iff' := .rfl + theorem verts_spanningCoe_injective : (fun G' : Subgraph G => (G'.verts, G'.spanningCoe)).Injective := by intro G₁ G₂ h @@ -551,9 +580,12 @@ theorem _root_.Disjoint.edgeSet {H₁ H₂ : Subgraph G} (h : Disjoint H₁ H₂ Disjoint H₁.edgeSet H₂.edgeSet := disjoint_iff_inf_le.mpr <| by simpa using edgeSet_mono h.le_bot +section map +variable {G' : SimpleGraph W} {f : G →g G'} + /-- Graph homomorphisms induce a covariant function on subgraphs. -/ @[simps] -protected def map {G' : SimpleGraph W} (f : G →g G') (H : G.Subgraph) : G'.Subgraph where +protected def map (f : G →g G') (H : G.Subgraph) : G'.Subgraph where verts := f '' H.verts Adj := Relation.Map H.Adj f f adj_sub := by @@ -566,29 +598,26 @@ protected def map {G' : SimpleGraph W} (f : G →g G') (H : G.Subgraph) : G'.Sub rintro _ _ ⟨u, v, h, rfl, rfl⟩ exact ⟨v, u, H.symm h, rfl, rfl⟩ -theorem map_monotone {G' : SimpleGraph W} (f : G →g G') : Monotone (Subgraph.map f) := by - intro H H' h +@[simp] lemma map_id (H : G.Subgraph) : H.map Hom.id = H := by ext <;> simp + +lemma map_comp {U : Type*} {G'' : SimpleGraph U} (H : G.Subgraph) (f : G →g G') (g : G' →g G'') : + H.map (g.comp f) = (H.map f).map g := by ext <;> simp [Subgraph.map] + +@[gcongr] lemma map_mono {H₁ H₂ : G.Subgraph} (hH : H₁ ≤ H₂) : H₁.map f ≤ H₂.map f := by constructor · intro simp only [map_verts, Set.mem_image, forall_exists_index, and_imp] rintro v hv rfl - exact ⟨_, h.1 hv, rfl⟩ + exact ⟨_, hH.1 hv, rfl⟩ · rintro _ _ ⟨u, v, ha, rfl, rfl⟩ - exact ⟨_, _, h.2 ha, rfl, rfl⟩ - -theorem map_sup {G : SimpleGraph V} {G' : SimpleGraph W} (f : G →g G') {H H' : G.Subgraph} : - (H ⊔ H').map f = H.map f ⊔ H'.map f := by - ext1 - · simp only [Set.image_union, map_verts, verts_sup] - · ext - simp only [Relation.Map, map_adj, sup_adj] - constructor - · rintro ⟨a, b, h | h, rfl, rfl⟩ - · exact Or.inl ⟨_, _, h, rfl, rfl⟩ - · exact Or.inr ⟨_, _, h, rfl, rfl⟩ - · rintro (⟨a, b, h, rfl, rfl⟩ | ⟨a, b, h, rfl, rfl⟩) - · exact ⟨_, _, Or.inl h, rfl, rfl⟩ - · exact ⟨_, _, Or.inr h, rfl, rfl⟩ + exact ⟨_, _, hH.2 ha, rfl, rfl⟩ + +lemma map_monotone : Monotone (Subgraph.map f) := fun _ _ ↦ map_mono + +theorem map_sup (f : G →g G') (H₁ H₂ : G.Subgraph) : (H₁ ⊔ H₂).map f = H₁.map f ⊔ H₂.map f := by + ext <;> simp [Set.image_union, map_adj, sup_adj, Relation.Map, or_and_right, exists_or] + +end map /-- Graph homomorphisms induce a contravariant function on subgraphs. -/ @[simps] diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean index b05bb8804a63b..96cd101472ef9 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Basic.lean @@ -256,7 +256,7 @@ lemma FarFromTriangleFree.lt_half (hG : G.FarFromTriangleFree ε) : ε < 2⁻¹ by_contra! hε refine lt_irrefl (ε * card α ^ 2) ?_ have hε₀ : 0 < ε := hε.trans_lt' (by norm_num) - rw [inv_pos_le_iff_one_le_mul (zero_lt_two' 𝕜)] at hε + rw [inv_le_iff_one_le_mul₀ (zero_lt_two' 𝕜)] at hε calc _ ≤ (G.edgeFinset.card : 𝕜) := by simpa using hG.le_card_sub_card bot_le (cliqueFree_bot (le_succ _)) @@ -276,7 +276,7 @@ lemma FarFromTriangleFree.lt_half (hG : G.FarFromTriangleFree ε) : ε < 2⁻¹ apply tsub_lt_self <;> positivity lemma FarFromTriangleFree.lt_one (hG : G.FarFromTriangleFree ε) : ε < 1 := - hG.lt_half.trans <| inv_lt_one one_lt_two + hG.lt_half.trans two_inv_lt_one theorem FarFromTriangleFree.nonpos (h₀ : G.FarFromTriangleFree ε) (h₁ : G.CliqueFree 3) : ε ≤ 0 := by diff --git a/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean b/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean index 41df6e05b9aba..f1687fb68c6d4 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Triangle/Counting.lean @@ -44,7 +44,7 @@ private lemma edgeDensity_badVertices_le (hε : 0 ≤ ε) (dst : 2 * ε ≤ G.ed G.edgeDensity (badVertices G ε s t) t ≤ G.edgeDensity s t - ε := by rw [edgeDensity_def] push_cast - refine div_le_of_nonneg_of_le_mul (by positivity) (sub_nonneg_of_le <| by linarith) ?_ + refine div_le_of_le_mul₀ (by positivity) (sub_nonneg_of_le <| by linarith) ?_ rw [mul_comm] exact G.card_interedges_badVertices_le @@ -89,7 +89,7 @@ private lemma good_vertices_triangle_card [DecidableEq α] (dst : 2 * ε ≤ G.e rw [edgeDensity_def] at this push_cast at this have hε := utu.pos.le - refine le_trans ?_ (mul_le_of_nonneg_of_le_div (Nat.cast_nonneg _) (by positivity) this) + refine le_trans ?_ (mul_le_of_le_div₀ (Nat.cast_nonneg _) (by positivity) this) refine Eq.trans_le ?_ (mul_le_mul_of_nonneg_left (mul_le_mul hY hZ (by positivity) (by positivity)) hε) ring diff --git a/Mathlib/Combinatorics/SimpleGraph/Walk.lean b/Mathlib/Combinatorics/SimpleGraph/Walk.lean index ccdc8da2c18ea..e2c574948f9c0 100644 --- a/Mathlib/Combinatorics/SimpleGraph/Walk.lean +++ b/Mathlib/Combinatorics/SimpleGraph/Walk.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kyle Miller -/ import Mathlib.Combinatorics.SimpleGraph.Maps -import Mathlib.Data.List.Lemmas /-! @@ -509,7 +508,7 @@ theorem getLast_support {G : SimpleGraph V} {a b : V} (p : G.Walk a b) : theorem tail_support_append {u v w : V} (p : G.Walk u v) (p' : G.Walk v w) : (p.append p').support.tail = p.support.tail ++ p'.support.tail := by - rw [support_append, List.tail_append_of_ne_nil _ _ (support_ne_nil _)] + rw [support_append, List.tail_append_of_ne_nil (support_ne_nil _)] theorem support_eq_cons {u v : V} (p : G.Walk u v) : p.support = u :: p.support.tail := by cases p <;> simp diff --git a/Mathlib/Combinatorics/Young/YoungDiagram.lean b/Mathlib/Combinatorics/Young/YoungDiagram.lean index 79b3e2892c891..fad6a3949ea28 100644 --- a/Mathlib/Combinatorics/Young/YoungDiagram.lean +++ b/Mathlib/Combinatorics/Young/YoungDiagram.lean @@ -67,7 +67,7 @@ namespace YoungDiagram instance : SetLike YoungDiagram (ℕ × ℕ) where -- Porting note (#11215): TODO: figure out how to do this correctly - coe := fun y => y.cells + coe y := y.cells coe_injective' μ ν h := by rwa [YoungDiagram.ext_iff, ← Finset.coe_inj] @[simp] @@ -436,7 +436,7 @@ theorem rowLens_length_ofRowLens {w : List ℕ} {hw : w.Sorted (· ≥ ·)} (hpo (ofRowLens w hw).rowLens.length = w.length := by simp only [length_rowLens, colLen, Nat.find_eq_iff, mem_cells, mem_ofRowLens, lt_self_iff_false, IsEmpty.exists_iff, Classical.not_not] - exact ⟨not_false, fun n hn => ⟨hn, hpos _ (List.getElem_mem _ _ hn)⟩⟩ + exact ⟨not_false, fun n hn => ⟨hn, hpos _ (List.getElem_mem hn)⟩⟩ /-- The length of the `i`th row in `ofRowLens w hw` is the `i`th entry of `w` -/ theorem rowLen_ofRowLens {w : List ℕ} {hw : w.Sorted (· ≥ ·)} (i : Fin w.length) : diff --git a/Mathlib/Computability/Ackermann.lean b/Mathlib/Computability/Ackermann.lean index 1b60a716c05f3..211e594b14670 100644 --- a/Mathlib/Computability/Ackermann.lean +++ b/Mathlib/Computability/Ackermann.lean @@ -3,7 +3,6 @@ Copyright (c) 2022 Violeta Hernández Palacios. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios -/ -import Mathlib.Algebra.Order.Ring.Basic import Mathlib.Computability.Primrec import Mathlib.Tactic.Ring import Mathlib.Tactic.Linarith @@ -75,26 +74,26 @@ theorem ack_succ_succ (m n : ℕ) : ack (m + 1) (n + 1) = ack m (ack (m + 1) n) @[simp] theorem ack_one (n : ℕ) : ack 1 n = n + 2 := by induction' n with n IH - · rfl + · simp · simp [IH] @[simp] theorem ack_two (n : ℕ) : ack 2 n = 2 * n + 3 := by induction' n with n IH - · rfl + · simp · simpa [mul_succ] -- Porting note: re-written to get rid of ack_three_aux @[simp] theorem ack_three (n : ℕ) : ack 3 n = 2 ^ (n + 3) - 3 := by induction' n with n IH - · rfl + · simp · rw [ack_succ_succ, IH, ack_two, Nat.succ_add, Nat.pow_succ 2 (n + 3), mul_comm _ 2, 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 rw [_root_.mul_le_mul_left two_pos] - exact pow_le_pow_right one_le_two (Nat.le_add_left 3 n) + exact pow_right_mono₀ one_le_two (Nat.le_add_left 3 n) theorem ack_pos : ∀ m n, 0 < ack m n | 0, n => by simp diff --git a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean index 65daa0a486dab..f9b3f66acc2b8 100644 --- a/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean +++ b/Mathlib/Computability/AkraBazzi/GrowsPolynomially.lean @@ -131,7 +131,7 @@ lemma eventually_zero_of_frequently_zero (hf : GrowsPolynomially f) (hf' : ∃ refine hmain ⌊-logb 2 (x / x₀)⌋₊ x le_rfl ⟨?lb, ?ub⟩ case lb => rw [← le_div_iff₀ x₀_pos] - refine (logb_le_logb (b := 2) (by norm_num) (zpow_pos_of_pos (by norm_num) _) + refine (logb_le_logb (b := 2) (by norm_num) (zpow_pos (by norm_num) _) (by positivity)).mp ?_ rw [← rpow_intCast, logb_rpow (by norm_num) (by norm_num), ← neg_le_neg_iff] simp only [Int.cast_sub, Int.cast_neg, Int.cast_natCast, Int.cast_one, neg_sub, sub_neg_eq_add] @@ -140,7 +140,7 @@ lemma eventually_zero_of_frequently_zero (hf : GrowsPolynomially f) (hf' : ∃ case ub => rw [← div_le_iff₀ x₀_pos] refine (logb_le_logb (b := 2) (by norm_num) (by positivity) - (zpow_pos_of_pos (by norm_num) _)).mp ?_ + (zpow_pos (by norm_num) _)).mp ?_ rw [← rpow_intCast, logb_rpow (by norm_num) (by norm_num), ← neg_le_neg_iff] simp only [Int.cast_neg, Int.cast_natCast, neg_neg] have : 0 ≤ -logb 2 (x / x₀) := by @@ -201,7 +201,7 @@ lemma eventually_atTop_nonneg_or_nonpos (hf : GrowsPolynomially f) : have le_2n : max n₀ 2 ≤ (2 : ℝ)^n * max n₀ 2 := by nth_rewrite 1 [← one_mul (max n₀ 2)] gcongr - exact one_le_pow_of_one_le (by norm_num : (1 : ℝ) ≤ 2) _ + exact one_le_pow₀ (by norm_num : (1 : ℝ) ≤ 2) have n₀_le_z : n₀ ≤ z := by calc n₀ ≤ max n₀ 2 := by simp _ ≤ (2 : ℝ)^n * max n₀ 2 := le_2n diff --git a/Mathlib/Computability/Halting.lean b/Mathlib/Computability/Halting.lean index 084c5246a26c6..a2de5176d359b 100644 --- a/Mathlib/Computability/Halting.lean +++ b/Mathlib/Computability/Halting.lean @@ -223,7 +223,7 @@ theorem rice₂ (C : Set Code) (H : ∀ cf cg, eval cf = eval cg → (cf ∈ C (Partrec.nat_iff.1 <| eval_part.comp (const cg) Computable.id) ((hC _).1 fC), fun h => by { obtain rfl | rfl := h <;> simpa [ComputablePred, Set.mem_empty_iff_false] using - ⟨⟨inferInstance⟩, Computable.const _⟩ }⟩ + Computable.const _}⟩ /-- The Halting problem is recursively enumerable -/ theorem halting_problem_re (n) : RePred fun c => (eval c n).Dom := @@ -281,8 +281,6 @@ namespace Nat.Partrec' open Mathlib.Vector Partrec Computable -open Nat (Partrec') - open Nat.Partrec' theorem to_part {n f} (pf : @Partrec' n f) : _root_.Partrec f := by diff --git a/Mathlib/Computability/Language.lean b/Mathlib/Computability/Language.lean index cc112e2e09266..a8779cd1c9283 100644 --- a/Mathlib/Computability/Language.lean +++ b/Mathlib/Computability/Language.lean @@ -159,7 +159,7 @@ lemma mem_kstar_iff_exists_nonempty {x : List α} : x ∈ l∗ ↔ ∃ S : List (List α), x = S.join ∧ ∀ y ∈ S, y ∈ l ∧ y ≠ [] := by constructor · rintro ⟨S, rfl, h⟩ - refine ⟨S.filter fun l ↦ !List.isEmpty l, by simp, fun y hy ↦ ?_⟩ + refine ⟨S.filter fun l ↦ !List.isEmpty l, by simp [List.join_filter_not_isEmpty], fun y hy ↦ ?_⟩ -- Porting note: The previous code was: -- rw [mem_filter, empty_iff_eq_nil] at hy rw [mem_filter, Bool.not_eq_true', ← Bool.bool_iff_false, List.isEmpty_iff] at hy diff --git a/Mathlib/Computability/PartrecCode.lean b/Mathlib/Computability/PartrecCode.lean index f563f6babf2c4..74b64e82859ab 100644 --- a/Mathlib/Computability/PartrecCode.lean +++ b/Mathlib/Computability/PartrecCode.lean @@ -170,7 +170,7 @@ private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n instance instDenumerable : Denumerable Code := mk' ⟨encodeCode, ofNatCode, fun c => by - induction c <;> try {rfl} <;> simp [encodeCode, ofNatCode, Nat.div2_val, *], + induction c <;> simp [encodeCode, ofNatCode, Nat.div2_val, *], encode_ofNatCode⟩ theorem encodeCode_eq : encode = encodeCode := @@ -900,7 +900,7 @@ private theorem hG : Primrec G := by Primrec.fst private theorem evaln_map (k c n) : - ((((List.range k)[n]?).map (evaln k c)).bind fun b => b) = evaln k c n := by + ((List.range k)[n]?.bind fun a ↦ evaln k c a) = evaln k c n := by by_cases kn : n < k · simp [List.getElem?_range kn] · rw [List.getElem?_len_le] @@ -937,7 +937,7 @@ theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a (List.range n.unpair.1).map (evaln n.unpair.1 (ofNat Code n.unpair.2))) (k', c') n = evaln k' c' n := by intro k₁ c₁ n₁ hl - simp [lup, List.getElem?_range hl, evaln_map, Bind.bind] + simp [lup, List.getElem?_range hl, evaln_map, Bind.bind, Option.bind_map] cases' c with cf cg cf cg cf cg cf <;> simp [evaln, nk, Bind.bind, Functor.map, Seq.seq, pure] · cases' encode_lt_pair cf cg with lf lg @@ -969,7 +969,7 @@ theorem evaln_prim : Primrec fun a : (ℕ × Code) × ℕ => evaln a.1.1 a.1.2 a (Primrec.option_bind (Primrec.list_get?.comp (this.comp (_root_.Primrec.const ()) (Primrec.encode_iff.2 Primrec.fst)) Primrec.snd) Primrec.snd.to₂).of_eq - fun ⟨⟨k, c⟩, n⟩ => by simp [evaln_map] + fun ⟨⟨k, c⟩, n⟩ => by simp [evaln_map, Option.bind_map] end diff --git a/Mathlib/Computability/Primrec.lean b/Mathlib/Computability/Primrec.lean index 967626fac3c92..350ee120e6376 100644 --- a/Mathlib/Computability/Primrec.lean +++ b/Mathlib/Computability/Primrec.lean @@ -275,7 +275,7 @@ end Primcodable namespace Primrec -variable {α : Type*} {σ : Type*} [Primcodable α] [Primcodable σ] +variable {α : Type*} [Primcodable α] open Nat.Primrec @@ -457,8 +457,8 @@ end Primrec₂ namespace Primrec -variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} {σ : Type*} -variable [Primcodable α] [Primcodable β] [Primcodable γ] [Primcodable δ] [Primcodable σ] +variable {α : Type*} {β : Type*} {σ : Type*} +variable [Primcodable α] [Primcodable β] [Primcodable σ] theorem to₂ {f : α × β → σ} (hf : Primrec f) : Primrec₂ fun a b => f (a, b) := hf.of_eq fun _ => rfl @@ -1088,8 +1088,7 @@ end Primrec namespace Primcodable -variable {α : Type*} {β : Type*} -variable [Primcodable α] [Primcodable β] +variable {α : Type*} [Primcodable α] open Primrec @@ -1139,8 +1138,8 @@ end Primcodable namespace Primrec -variable {α : Type*} {β : Type*} {γ : Type*} {σ : Type*} -variable [Primcodable α] [Primcodable β] [Primcodable γ] [Primcodable σ] +variable {α : Type*} {β : Type*} {σ : Type*} +variable [Primcodable α] [Primcodable β] [Primcodable σ] theorem subtype_val {p : α → Prop} [DecidablePred p] {hp : PrimrecPred p} : haveI := Primcodable.subtype hp @@ -1215,7 +1214,7 @@ theorem vector_get {n} : Primrec₂ (@Vector.get α n) := theorem list_ofFn : ∀ {n} {f : Fin n → α → σ}, (∀ i, Primrec (f i)) → Primrec fun a => List.ofFn fun i => f i a - | 0, _, _ => const [] + | 0, _, _ => by simp only [List.ofFn_zero]; exact const [] | n + 1, f, hf => by simpa [List.ofFn_succ] using list_cons.comp (hf 0) (list_ofFn fun i => hf i.succ) diff --git a/Mathlib/Computability/Reduce.lean b/Mathlib/Computability/Reduce.lean index 753ba658feba9..131ccd8fadbc5 100644 --- a/Mathlib/Computability/Reduce.lean +++ b/Mathlib/Computability/Reduce.lean @@ -311,9 +311,7 @@ protected theorem ind_on {C : ManyOneDegree → Prop} (d : ManyOneDegree) (h : ∀ p : Set ℕ, C (of p)) : C d := Quotient.inductionOn' d h -/-- Lifts a function on sets of natural numbers to many-one degrees. --/ --- @[elab_as_elim] -- Porting note: unexpected eliminator resulting type +/-- Lifts a function on sets of natural numbers to many-one degrees. -/ protected abbrev liftOn {φ} (d : ManyOneDegree) (f : Set ℕ → φ) (h : ∀ p q, ManyOneEquiv p q → f p = f q) : φ := Quotient.liftOn' d f h @@ -323,9 +321,8 @@ protected theorem liftOn_eq {φ} (p : Set ℕ) (f : Set ℕ → φ) (h : ∀ p q, ManyOneEquiv p q → f p = f q) : (of p).liftOn f h = f p := rfl -/-- Lifts a binary function on sets of natural numbers to many-one degrees. --/ -@[reducible, simp] -- @[elab_as_elim] -- Porting note: unexpected eliminator resulting type +/-- Lifts a binary function on sets of natural numbers to many-one degrees. -/ +@[reducible, simp] protected def liftOn₂ {φ} (d₁ d₂ : ManyOneDegree) (f : Set ℕ → Set ℕ → φ) (h : ∀ p₁ p₂ q₁ q₂, ManyOneEquiv p₁ p₂ → ManyOneEquiv q₁ q₂ → f p₁ q₁ = f p₂ q₂) : φ := d₁.liftOn (fun p => d₂.liftOn (f p) fun q₁ q₂ hq => h _ _ _ _ (by rfl) hq) @@ -345,7 +342,6 @@ protected theorem liftOn₂_eq {φ} (p q : Set ℕ) (f : Set ℕ → Set ℕ → @[simp] theorem of_eq_of {p : α → Prop} {q : β → Prop} : of p = of q ↔ ManyOneEquiv p q := by rw [of, of, Quotient.eq''] - unfold Setoid.r simp instance instInhabited : Inhabited ManyOneDegree := diff --git a/Mathlib/Computability/TMToPartrec.lean b/Mathlib/Computability/TMToPartrec.lean index 68249b2638fe3..79a322e54c754 100644 --- a/Mathlib/Computability/TMToPartrec.lean +++ b/Mathlib/Computability/TMToPartrec.lean @@ -1604,7 +1604,7 @@ def trStmts₁ : Λ' → Finset Λ' theorem trStmts₁_trans {q q'} : q' ∈ trStmts₁ q → trStmts₁ q' ⊆ trStmts₁ q := by induction q with | move _ _ _ q q_ih => _ | clear _ _ q q_ih => _ | copy q q_ih => _ | push _ _ q q_ih => _ - | read q q_ih => _ | succ q q_ih => _ | pred q₁ q₂ q₁_ih q₂_ih => _ | ret => _ + | read q q_ih => _ | succ q q_ih => _ | pred q₁ q₂ q₁_ih q₂_ih => _ | ret => _ <;> all_goals simp (config := { contextual := true }) only [trStmts₁, Finset.mem_insert, Finset.mem_union, or_imp, Finset.mem_singleton, Finset.Subset.refl, imp_true_iff, true_and] @@ -1801,8 +1801,8 @@ theorem trStmts₁_supports {S q} (H₁ : (q : Λ').Supports S) (HS₁ : trStmts have W := fun {q} => trStmts₁_self q induction q with | move _ _ _ q q_ih => _ | clear _ _ q q_ih => _ | copy q q_ih => _ | push _ _ q q_ih => _ - | read q q_ih => _ | succ q q_ih => _ | pred q₁ q₂ q₁_ih q₂_ih => _ | ret => _ - all_goals simp [trStmts₁, -Finset.singleton_subset_iff] at HS₁ ⊢ + | read q q_ih => _ | succ q q_ih => _ | pred q₁ q₂ q₁_ih q₂_ih => _ | ret => _ <;> + simp [trStmts₁, -Finset.singleton_subset_iff] at HS₁ ⊢ any_goals cases' Finset.insert_subset_iff.1 HS₁ with h₁ h₂ first | have h₃ := h₂ W | try simp [Finset.subset_iff] at h₂ diff --git a/Mathlib/Computability/TuringMachine.lean b/Mathlib/Computability/TuringMachine.lean index ea36cdcbb6053..0309fcce41a02 100644 --- a/Mathlib/Computability/TuringMachine.lean +++ b/Mathlib/Computability/TuringMachine.lean @@ -178,7 +178,6 @@ instance ListBlank.hasEmptyc {Γ} [Inhabited Γ] : EmptyCollection (ListBlank Γ /-- A modified version of `Quotient.liftOn'` specialized for `ListBlank`, with the stronger precondition `BlankExtends` instead of `BlankRel`. -/ --- Porting note: Removed `@[elab_as_elim]` protected abbrev ListBlank.liftOn {Γ} [Inhabited Γ] {α} (l : ListBlank Γ) (f : List Γ → α) (H : ∀ a b, BlankExtends a b → f a = f b) : α := l.liftOn' f <| by rintro a b (h | h) <;> [exact H _ _ h; exact (H _ _ h).symm] @@ -263,7 +262,7 @@ def ListBlank.nth {Γ} [Inhabited Γ] (l : ListBlank Γ) (n : ℕ) : Γ := by rw [List.getI_eq_default _ h] rcases le_or_lt _ n with h₂ | h₂ · rw [List.getI_eq_default _ h₂] - rw [List.getI_eq_get _ h₂, List.get_eq_getElem, List.getElem_append_right' h, + rw [List.getI_eq_get _ h₂, List.get_eq_getElem, List.getElem_append_right h, List.getElem_replicate] @[simp] diff --git a/Mathlib/Condensed/Discrete/LocallyConstant.lean b/Mathlib/Condensed/Discrete/LocallyConstant.lean index 384896122a812..ca028c4a70293 100644 --- a/Mathlib/Condensed/Discrete/LocallyConstant.lean +++ b/Mathlib/Condensed/Discrete/LocallyConstant.lean @@ -23,10 +23,10 @@ the functor of sheaves of locally constant maps described above. The hard part of this adjunction is to define the counit. Its components are defined as follows: -Let `S : CompHausLike P` and let `Y` be a finite-product preserving presheaf on `CompHausLike P`  +Let `S : CompHausLike P` and let `Y` be a finite-product preserving presheaf on `CompHausLike P` (e.g. a sheaf for the coherent topology). We need to define a map `LocallyConstant S Y(*) ⟶ Y(S)`. Given a locally constant map `f : S → Y(*)`, let `S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding -decomposition of `S` into the fibers. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ` and denote +decomposition of `S` into the fibers. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ` and denote by `gᵢ` the canonical map `Y(*) → Y(Sᵢ)`. Our map then takes `f` to the image of `(g₁(y₁), ⋯, gₙ(yₙ))` under the isomorphism `Y(S₁) × ⋯ × Y(Sₙ) ≅ Y(S₁ ⊔ ⋯ ⊔ Sₙ) = Y(S)`. @@ -34,14 +34,14 @@ Now we need to prove that the counit is natural in `S : CompHausLike P` and `Y : Sheaf (coherentTopology (CompHausLike P)) (Type _)`. There are two key lemmas in all naturality proofs in this file (both lemmas are in the `CompHausLike.LocallyConstant` namespace): -* `presheaf_ext`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, another presheaf +* `presheaf_ext`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, another presheaf `X`, and two elements `x y : X(S)`, to prove that `x = y` it suffices to prove that for every inclusion map `ιᵢ : Sᵢ ⟶ S`, `X(ιᵢ)(x) = X(ιᵢ)(y)`. - Here it is important that we set everything up in such a way that the `Sᵢ` are literally subtypes - of `S`.  + Here it is important that we set everything up in such a way that the `Sᵢ` are literally subtypes + of `S`. -* `incl_of_counitAppApp`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, we have - `Y(ιᵢ)(ε_{S, Y}(f)) = gᵢ(yᵢ)` where `ε` denotes the counit and the other notation is like above. +* `incl_of_counitAppApp`: given `S`, `Y` and `f : LocallyConstant S Y(*)` like above, we have + `Y(ιᵢ)(ε_{S, Y}(f)) = gᵢ(yᵢ)` where `ε` denotes the counit and the other notation is like above. ## Main definitions @@ -139,8 +139,8 @@ noncomputable def counitAppAppImage : (a : Fiber f) → Y.obj ⟨fiber f a⟩ := /-- The counit is defined as follows: given a locally constant map `f : S → Y(*)`, let -`S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding decomposition of `S` into the fibers. We need to provide an -element of `Y(S)`. It suffices to provide an element of `Y(Sᵢ)` for all `i`. Let `yᵢ ∈ Y(*)` denote +`S = S₁ ⊔ ⋯ ⊔ Sₙ` be the corresponding decomposition of `S` into the fibers. We need to provide an +element of `Y(S)`. It suffices to provide an element of `Y(Sᵢ)` for all `i`. Let `yᵢ ∈ Y(*)` denote the value of `f` on `Sᵢ`. Our desired element is the image of `yᵢ` under the canonical map `Y(*) → Y(Sᵢ)`. -/ @@ -178,7 +178,7 @@ variable {T : CompHausLike.{u} P} (g : T ⟶ S) /-- This is an auxiliary definition, the details do not matter. What's important is that this map exists -so that the lemma `incl_comap` works. +so that the lemma `incl_comap` works. -/ def componentHom (a : Fiber (f.comap g)) : fiber _ a ⟶ fiber _ (Fiber.mk f (g a.preimage)) where @@ -186,8 +186,7 @@ def componentHom (a : Fiber (f.comap g)) : simp only [Fiber.mk, Set.mem_preimage, Set.mem_singleton_iff] convert map_eq_image _ _ x exact map_preimage_eq_image_map _ _ a⟩ - continuous_toFun := by - exact Continuous.subtype_mk (Continuous.comp g.continuous continuous_subtype_val) _ + continuous_toFun := by exact Continuous.subtype_mk (g.continuous.comp continuous_subtype_val) _ -- term mode gives "unknown free variable" error. lemma incl_comap {S T : (CompHausLike P)ᵒᵖ} @@ -220,32 +219,31 @@ variable (P) (X : TopCat.{max u w}) [HasExplicitFiniteCoproducts.{0} P] [HasExplicitPullbacks P] (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) -/-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ -noncomputable def functorToPresheavesIsoTopCatToSheafCompHausLike (X : Type (max u w)) : - functorToPresheaves.{u, w}.obj X ≅ - ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).val := +/-- `locallyConstantIsoContinuousMap` is a natural isomorphism. -/ +noncomputable def functorToPresheavesIso (X : Type (max u w)) : + functorToPresheaves.{u, w}.obj X ≅ ((TopCat.discrete.obj X).toSheafCompHausLike P hs).val := NatIso.ofComponents (fun S ↦ locallyConstantIsoContinuousMap _ _) -/-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ +/-- `CompHausLike.LocallyConstant.functorToPresheaves` lands in sheaves. -/ @[simps] def functor : - have := CompHausLike.preregular hs + haveI := CompHausLike.preregular hs Type (max u w) ⥤ Sheaf (coherentTopology (CompHausLike.{u} P)) (Type (max u w)) where obj X := { val := functorToPresheaves.{u, w}.obj X cond := by - rw [Presheaf.isSheaf_of_iso_iff (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)] - exact ((topCatToSheafCompHausLike P hs).obj (TopCat.discrete.obj X)).cond } + rw [Presheaf.isSheaf_of_iso_iff (functorToPresheavesIso P hs X)] + exact ((TopCat.discrete.obj X).toSheafCompHausLike P hs).cond } map f := ⟨functorToPresheaves.{u, w}.map f⟩ /-- -`CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of +`CompHausLike.LocallyConstant.functor` is naturally isomorphic to the restriction of `topCatToSheafCompHausLike` to discrete topological spaces. -/ -noncomputable def functorIsoTopCatToSheafCompHausLike : +noncomputable def functorIso : functor.{u, w} P hs ≅ TopCat.discrete.{max w u} ⋙ topCatToSheafCompHausLike P hs := NatIso.ofComponents (fun X ↦ (fullyFaithfulSheafToPresheaf _ _).preimageIso - (functorToPresheavesIsoTopCatToSheafCompHausLike P hs X)) + (functorToPresheavesIso P hs X)) /-- The counit is natural in both `S : CompHausLike P` and `Y : Sheaf (coherentTopology (CompHausLike P)) (Type (max u w))` -/ @@ -289,7 +287,7 @@ noncomputable def counit [HasExplicitFiniteCoproducts.{u} P] : haveI := CompHaus exact (mem_iff_eq_image (g.val.app _ ∘ f) _ _).symm /-- -The unit of the adjunciton is given by mapping each element to the corresponding constant map. +The unit of the adjunciton is given by mapping each element to the corresponding constant map. -/ @[simps] def unit : 𝟭 _ ⟶ functor P hs ⋙ (sheafSections _ _).obj ⟨CompHausLike.of P PUnit.{u+1}⟩ where @@ -321,7 +319,7 @@ lemma adjunction_left_triangle [HasExplicitFiniteCoproducts.{u} P] rfl /-- -`CompHausLike.LocallyConstant.functor` is left adjoint to the forgetful functor. +`CompHausLike.LocallyConstant.functor` is left adjoint to the forgetful functor. -/ @[simps] noncomputable def adjunction [HasExplicitFiniteCoproducts.{u} P] : @@ -372,7 +370,7 @@ abbrev functor : Type (u+1) ⥤ CondensedSet.{u} := (hs := fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) /-- -`CondensedSet.LocallyConstant.functor` is isomorphic to `Condensed.discrete` +`CondensedSet.LocallyConstant.functor` is isomorphic to `Condensed.discrete` (by uniqueness of adjoints). -/ noncomputable def iso : functor ≅ discrete (Type (u+1)) := @@ -406,7 +404,7 @@ instance (S : LightProfinite.{u}) (p : S → Prop) : (inferInstance : SecondCountableTopology {s | p s})⟩⟩ /-- -`LightCondSet.LocallyConstant.functor` is isomorphic to `LightCondensed.discrete` +`LightCondSet.LocallyConstant.functor` is isomorphic to `LightCondensed.discrete` (by uniqueness of adjoints). -/ noncomputable def iso : functor ≅ LightCondensed.discrete (Type u) := diff --git a/Mathlib/Condensed/Discrete/Module.lean b/Mathlib/Condensed/Discrete/Module.lean new file mode 100644 index 0000000000000..5657c6d51579e --- /dev/null +++ b/Mathlib/Condensed/Discrete/Module.lean @@ -0,0 +1,281 @@ +/- +Copyright (c) 2024 Dagur Asgeirsson. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Dagur Asgeirsson +-/ +import Mathlib.CategoryTheory.Sites.ConstantSheaf +import Mathlib.Condensed.Discrete.LocallyConstant +import Mathlib.Condensed.Light.Module +import Mathlib.Condensed.Module +import Mathlib.Topology.LocallyConstant.Algebra +/-! + +# Discrete condensed `R`-modules + +This file provides the necessary API to prove that a condensed `R`-module is discrete if and only +if the underlying condensed set is (both for light condensed and condensed). + +That is, it defines the functor `CondensedMod.LocallyConstant.functor` which takes an `R`-module to +the condensed `R`-modules given by locally constant maps to it, and proves that this functor is +naturally isomorphic to the constant sheaf functor (and the analogues for light condensed modules). +-/ + +universe w u + +open CategoryTheory LocallyConstant CompHausLike Functor Category Functor Opposite + +attribute [local instance] ConcreteCategory.instFunLike + +variable {P : TopCat.{u} → Prop} + +namespace CompHausLike.LocallyConstantModule + +variable (R : Type (max u w)) [Ring R] + +/-- +The functor from the category of `R`-modules to presheaves on `CompHausLike P` given by locally +constant maps. +-/ +@[simps] +def functorToPresheaves : ModuleCat.{max u w} R ⥤ ((CompHausLike.{u} P)ᵒᵖ ⥤ ModuleCat R) where + obj X := { + obj := fun ⟨S⟩ ↦ ModuleCat.of R (LocallyConstant S X) + map := fun f ↦ comapₗ R f.unop } + map f := { app := fun S ↦ mapₗ R f } + +variable [HasExplicitFiniteCoproducts.{0} P] [HasExplicitPullbacks.{u} P] + (hs : ∀ ⦃X Y : CompHausLike P⦄ (f : X ⟶ Y), EffectiveEpi f → Function.Surjective f) + +/-- `CompHausLike.LocallyConstantModule.functorToPresheaves` lands in sheaves. -/ +@[simps] +def functor : haveI := CompHausLike.preregular hs + ModuleCat R ⥤ Sheaf (coherentTopology (CompHausLike.{u} P)) (ModuleCat R) where + obj X := { + val := (functorToPresheaves.{w, u} R).obj X + cond := by + have := CompHausLike.preregular hs + apply Presheaf.isSheaf_coherent_of_hasPullbacks_of_comp + (s := CategoryTheory.forget (ModuleCat R)) + exact ((CompHausLike.LocallyConstant.functor P hs).obj _).cond } + map f := ⟨(functorToPresheaves.{w, u} R).map f⟩ + +end CompHausLike.LocallyConstantModule + +namespace CondensedMod.LocallyConstant + +open Condensed + +variable (R : Type (u+1)) [Ring R] + +/-- `functorToPresheaves` in the case of `CompHaus`. -/ +abbrev functorToPresheaves : ModuleCat.{u+1} R ⥤ (CompHaus.{u}ᵒᵖ ⥤ ModuleCat R) := + CompHausLike.LocallyConstantModule.functorToPresheaves.{u+1, u} R + +/-- `functorToPresheaves` as a functor to condensed modules. -/ +abbrev functor : ModuleCat R ⥤ CondensedMod.{u} R := + CompHausLike.LocallyConstantModule.functor.{u+1, u} R + (fun _ _ _ ↦ ((CompHaus.effectiveEpi_tfae _).out 0 2).mp) + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteAux₁ (M : ModuleCat.{u+1} R) : + M ≅ (ModuleCat.of R (LocallyConstant (CompHaus.of PUnit.{u+1}) M)) where + hom := constₗ R + inv := evalₗ R PUnit.unit + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteAux₂ (M : ModuleCat R) : + (discrete _).obj M ≅ (discrete _).obj + (ModuleCat.of R (LocallyConstant (CompHaus.of PUnit.{u+1}) M)) := + (discrete _).mapIso (functorIsoDiscreteAux₁ R M) + +instance (M : ModuleCat R) : IsIso ((forget R).map + ((discreteUnderlyingAdj (ModuleCat R)).counit.app ((functor R).obj M))) := by + dsimp [Condensed.forget, discreteUnderlyingAdj] + rw [← constantSheafAdj_counit_w] + refine IsIso.comp_isIso' inferInstance ?_ + have : (constantSheaf (coherentTopology CompHaus) (Type (u + 1))).Faithful := + inferInstanceAs (discrete _).Faithful + have : (constantSheaf (coherentTopology CompHaus) (Type (u + 1))).Full := + inferInstanceAs (discrete _).Full + rw [← Sheaf.isConstant_iff_isIso_counit_app] + constructor + change _ ∈ (discrete _).essImage + rw [essImage_eq_of_natIso CondensedSet.LocallyConstant.iso.symm] + exact obj_mem_essImage CondensedSet.LocallyConstant.functor M + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteComponents (M : ModuleCat R) : + (discrete _).obj M ≅ (functor R).obj M := + have : (Condensed.forget R).ReflectsIsomorphisms := + inferInstanceAs (sheafCompose _ _).ReflectsIsomorphisms + have : IsIso ((discreteUnderlyingAdj (ModuleCat R)).counit.app ((functor R).obj M)) := + isIso_of_reflects_iso _ (Condensed.forget R) + functorIsoDiscreteAux₂ R M ≪≫ asIso ((discreteUnderlyingAdj _).counit.app ((functor R).obj M)) + +/-- +`CondensedMod.LocallyConstant.functor` is naturally isomorphic to the constant sheaf functor from +`R`-modules to condensed `R`-modules. + -/ +noncomputable def functorIsoDiscrete : functor R ≅ discrete _ := + NatIso.ofComponents (fun M ↦ (functorIsoDiscreteComponents R M).symm) fun f ↦ by + dsimp + rw [Iso.eq_inv_comp, ← Category.assoc, Iso.comp_inv_eq] + dsimp [functorIsoDiscreteComponents] + rw [assoc, ← Iso.eq_inv_comp, + ← (discreteUnderlyingAdj (ModuleCat R)).counit_naturality] + simp only [← assoc] + congr 1 + rw [← Iso.comp_inv_eq] + apply Sheaf.hom_ext + simp [functorIsoDiscreteAux₂, ← Functor.map_comp] + rfl + +/-- +`CondensedMod.LocallyConstant.functor` is left adjoint to the forgetful functor from condensed +`R`-modules to `R`-modules. +-/ +noncomputable def adjunction : functor R ⊣ underlying (ModuleCat R) := + Adjunction.ofNatIsoLeft (discreteUnderlyingAdj _) (functorIsoDiscrete R).symm + +/-- +`CondensedMod.LocallyConstant.functor` is fully faithful. +-/ +noncomputable def fullyFaithfulFunctor : (functor R).FullyFaithful := + (adjunction R).fullyFaithfulLOfCompIsoId + (NatIso.ofComponents fun M ↦ (functorIsoDiscreteAux₁ R _).symm) + +instance : (functor R).Faithful := (fullyFaithfulFunctor R).faithful + +instance : (functor R).Full := (fullyFaithfulFunctor R).full + +instance : (discrete (ModuleCat R)).Faithful := + Functor.Faithful.of_iso (functorIsoDiscrete R) + +instance : (constantSheaf (coherentTopology CompHaus) (ModuleCat R)).Faithful := + inferInstanceAs (discrete (ModuleCat R)).Faithful + +instance : (discrete (ModuleCat R)).Full := + Functor.Full.of_iso (functorIsoDiscrete R) + +instance : (constantSheaf (coherentTopology CompHaus) (ModuleCat R)).Full := + inferInstanceAs (discrete (ModuleCat R)).Full + +instance : (constantSheaf (coherentTopology CompHaus) (Type (u + 1))).Faithful := + inferInstanceAs (discrete (Type (u + 1))).Faithful + +instance : (constantSheaf (coherentTopology CompHaus) (Type (u + 1))).Full := + inferInstanceAs (discrete (Type (u + 1))).Full + +end CondensedMod.LocallyConstant + +namespace LightCondMod.LocallyConstant + +open LightCondensed + +variable (R : Type u) [Ring R] + +/-- `functorToPresheaves` in the case of `LightProfinite`. -/ +abbrev functorToPresheaves : ModuleCat.{u} R ⥤ (LightProfinite.{u}ᵒᵖ ⥤ ModuleCat R) := + CompHausLike.LocallyConstantModule.functorToPresheaves.{u, u} R + +/-- `functorToPresheaves` as a functor to light condensed modules. -/ +abbrev functor : ModuleCat R ⥤ LightCondMod.{u} R := + CompHausLike.LocallyConstantModule.functor.{u, u} R + (fun _ _ _ ↦ (LightProfinite.effectiveEpi_iff_surjective _).mp) + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteAux₁ (M : ModuleCat.{u} R) : + M ≅ (ModuleCat.of R (LocallyConstant (LightProfinite.of PUnit.{u+1}) M)) where + hom := constₗ R + inv := evalₗ R PUnit.unit + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteAux₂ (M : ModuleCat.{u} R) : + (discrete _).obj M ≅ (discrete _).obj + (ModuleCat.of R (LocallyConstant (LightProfinite.of PUnit.{u+1}) M)) := + (discrete _).mapIso (functorIsoDiscreteAux₁ R M) + +-- Not stating this explicitly causes timeouts below. +instance : HasSheafify (coherentTopology LightProfinite.{u}) (ModuleCat.{u} R) := + inferInstance + +instance (M : ModuleCat R) : + IsIso ((LightCondensed.forget R).map + ((discreteUnderlyingAdj (ModuleCat R)).counit.app + ((functor R).obj M))) := by + dsimp [LightCondensed.forget, discreteUnderlyingAdj] + rw [← constantSheafAdj_counit_w] + refine IsIso.comp_isIso' inferInstance ?_ + have : (constantSheaf (coherentTopology LightProfinite) (Type u)).Faithful := + inferInstanceAs (discrete _).Faithful + have : (constantSheaf (coherentTopology LightProfinite) (Type u)).Full := + inferInstanceAs (discrete _).Full + rw [← Sheaf.isConstant_iff_isIso_counit_app] + constructor + change _ ∈ (discrete _).essImage + rw [essImage_eq_of_natIso LightCondSet.LocallyConstant.iso.symm] + exact obj_mem_essImage LightCondSet.LocallyConstant.functor M + +/-- Auxiliary definition for `functorIsoDiscrete`. -/ +noncomputable def functorIsoDiscreteComponents (M : ModuleCat R) : + (discrete _).obj M ≅ (functor R).obj M := + have : (LightCondensed.forget R).ReflectsIsomorphisms := + inferInstanceAs (sheafCompose _ _).ReflectsIsomorphisms + have : IsIso ((discreteUnderlyingAdj (ModuleCat R)).counit.app ((functor R).obj M)) := + isIso_of_reflects_iso _ (LightCondensed.forget R) + functorIsoDiscreteAux₂ R M ≪≫ asIso ((discreteUnderlyingAdj _).counit.app ((functor R).obj M)) + +/-- +`LightCondMod.LocallyConstant.functor` is naturally isomorphic to the constant sheaf functor from +`R`-modules to light condensed `R`-modules. + -/ +noncomputable def functorIsoDiscrete : functor R ≅ discrete _ := + NatIso.ofComponents (fun M ↦ (functorIsoDiscreteComponents R M).symm) fun f ↦ by + dsimp + rw [Iso.eq_inv_comp, ← Category.assoc, Iso.comp_inv_eq] + dsimp [functorIsoDiscreteComponents] + rw [Category.assoc, ← Iso.eq_inv_comp, + ← (discreteUnderlyingAdj (ModuleCat R)).counit_naturality] + simp only [← assoc] + congr 1 + rw [← Iso.comp_inv_eq] + apply Sheaf.hom_ext + simp [functorIsoDiscreteAux₂, ← Functor.map_comp] + rfl + +/-- +`LightCondMod.LocallyConstant.functor` is left adjoint to the forgetful functor from light condensed +`R`-modules to `R`-modules. + -/ +noncomputable def adjunction : functor R ⊣ underlying (ModuleCat R) := + Adjunction.ofNatIsoLeft (discreteUnderlyingAdj _) (functorIsoDiscrete R).symm + +/-- +`LightCondMod.LocallyConstant.functor` is fully faithful. +-/ +noncomputable def fullyFaithfulFunctor : (functor R).FullyFaithful := + (adjunction R).fullyFaithfulLOfCompIsoId + (NatIso.ofComponents fun M ↦ (functorIsoDiscreteAux₁ R _).symm) + +instance : (functor R).Faithful := (fullyFaithfulFunctor R).faithful + +instance : (functor R).Full := (fullyFaithfulFunctor R).full + +instance : (discrete.{u} (ModuleCat R)).Faithful := Functor.Faithful.of_iso (functorIsoDiscrete R) + +instance : (constantSheaf (coherentTopology LightProfinite.{u}) (ModuleCat.{u} R)).Faithful := + inferInstanceAs (discrete.{u} (ModuleCat R)).Faithful + +instance : (discrete (ModuleCat.{u} R)).Full := + Functor.Full.of_iso (functorIsoDiscrete R) + +instance : (constantSheaf (coherentTopology LightProfinite.{u}) (ModuleCat.{u} R)).Full := + inferInstanceAs (discrete.{u} (ModuleCat.{u} R)).Full + +instance : (constantSheaf (coherentTopology LightProfinite) (Type u)).Faithful := + inferInstanceAs (discrete (Type u)).Faithful + +instance : (constantSheaf (coherentTopology LightProfinite) (Type u)).Full := + inferInstanceAs (discrete (Type u)).Full + +end LightCondMod.LocallyConstant diff --git a/Mathlib/Condensed/TopComparison.lean b/Mathlib/Condensed/TopComparison.lean index c8679d14fddbc..bcb10b87c8ea9 100644 --- a/Mathlib/Condensed/TopComparison.lean +++ b/Mathlib/Condensed/TopComparison.lean @@ -50,7 +50,7 @@ theorem factorsThrough_of_pullbackCondition {Z B : C} {π : Z ⟶ B} [HasPullbac have h₂ : ∀ y, G.map (pullback.snd _ _) ((PreservesPullback.iso G π π).inv y) = pullback.snd (G.map π) (G.map π) y := by simp only [← PreservesPullback.iso_inv_snd]; intro y; rfl - erw [h₁, h₂, TopCat.pullbackIsoProdSubtype_inv_fst_apply, + rw [h₁, h₂, TopCat.pullbackIsoProdSubtype_inv_fst_apply, TopCat.pullbackIsoProdSubtype_inv_snd_apply] at ha' simpa using ha' diff --git a/Mathlib/Control/Applicative.lean b/Mathlib/Control/Applicative.lean index 87acbfcaf5833..3b6bb33ac8951 100644 --- a/Mathlib/Control/Applicative.lean +++ b/Mathlib/Control/Applicative.lean @@ -5,6 +5,7 @@ Authors: Simon Hudon -/ import Mathlib.Algebra.Group.Defs import Mathlib.Control.Functor +import Mathlib.Control.Basic /-! # `applicative` instances @@ -28,7 +29,7 @@ variable {α β γ σ : Type u} theorem Applicative.map_seq_map (f : α → β → γ) (g : σ → β) (x : F α) (y : F σ) : f <$> x <*> g <$> y = ((· ∘ g) ∘ f) <$> x <*> y := by - simp [flip, functor_norm] + simp [flip, functor_norm, Function.comp_def] theorem Applicative.pure_seq_eq_map' (f : α → β) : ((pure f : F (α → β)) <*> ·) = (f <$> ·) := by ext; simp [functor_norm] diff --git a/Mathlib/Control/Basic.lean b/Mathlib/Control/Basic.lean index 0df3671f162c4..e6e6aa94abeee 100644 --- a/Mathlib/Control/Basic.lean +++ b/Mathlib/Control/Basic.lean @@ -18,12 +18,7 @@ variable {α β γ : Type u} section Functor -variable {f : Type u → Type v} [Functor f] [LawfulFunctor f] -@[functor_norm] -theorem Functor.map_map (m : α → β) (g : β → γ) (x : f α) : g <$> m <$> x = (g ∘ m) <$> x := - (comp_map _ _ _).symm --- order of implicits --- order of implicits +attribute [functor_norm] Functor.map_map end Functor @@ -67,10 +62,6 @@ section Monad variable {m : Type u → Type v} [Monad m] [LawfulMonad m] -theorem map_bind (x : m α) {g : α → m β} {f : β → γ} : - f <$> (x >>= g) = x >>= fun a => f <$> g a := by - rw [← bind_pure_comp, bind_assoc]; simp [bind_pure_comp] - theorem seq_bind_eq (x : m α) {g : β → m γ} {f : α → β} : f <$> x >>= g = x >>= g ∘ f := show bind (f <$> x) g = bind x (g ∘ f) by @@ -214,8 +205,6 @@ class CommApplicative (m : Type u → Type v) [Applicative m] extends LawfulAppl open Functor -variable {m} - theorem CommApplicative.commutative_map {m : Type u → Type v} [h : Applicative m] [CommApplicative m] {α β γ} (a : m α) (b : m β) {f : α → β → γ} : f <$> a <*> b = flip f <$> b <*> a := diff --git a/Mathlib/Control/Functor.lean b/Mathlib/Control/Functor.lean index 59ebe2553d456..305a88d2cc83f 100644 --- a/Mathlib/Control/Functor.lean +++ b/Mathlib/Control/Functor.lean @@ -3,7 +3,7 @@ Copyright (c) 2017 Simon Hudon. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Simon Hudon -/ -import Mathlib.Control.Basic +import Mathlib.Tactic.Attr.Register import Mathlib.Data.Set.Defs import Mathlib.Tactic.TypeStar import Batteries.Tactic.Lint @@ -181,7 +181,7 @@ protected theorem id_map : ∀ x : Comp F G α, Comp.map id x = x protected theorem comp_map (g' : α → β) (h : β → γ) : ∀ x : Comp F G α, Comp.map (h ∘ g') x = Comp.map h (Comp.map g' x) - | Comp.mk x => by simp [Comp.map, Comp.mk, Functor.map_comp_map, functor_norm] + | Comp.mk x => by simp [Comp.map, Comp.mk, Functor.map_comp_map, functor_norm, Function.comp_def] -- Porting note: `Comp.mk` wasn't needed in mathlib3 instance lawfulFunctor : LawfulFunctor (Comp F G) where diff --git a/Mathlib/Control/Lawful.lean b/Mathlib/Control/Lawful.lean index 769ec2655f4ec..f2cd84ab5da94 100644 --- a/Mathlib/Control/Lawful.lean +++ b/Mathlib/Control/Lawful.lean @@ -48,7 +48,7 @@ end StateT namespace ExceptT -variable {α β ε : Type u} {m : Type u → Type v} (x : ExceptT ε m α) +variable {α ε : Type u} {m : Type u → Type v} (x : ExceptT ε m α) -- Porting note: This is proven by proj reduction in Lean 3. @[simp] @@ -73,7 +73,6 @@ namespace ReaderT section -variable {ρ : Type u} variable {m : Type u → Type v} variable {α σ : Type u} diff --git a/Mathlib/Control/LawfulFix.lean b/Mathlib/Control/LawfulFix.lean index 485cc3ade329c..f22207cffe5c1 100644 --- a/Mathlib/Control/LawfulFix.lean +++ b/Mathlib/Control/LawfulFix.lean @@ -167,10 +167,9 @@ theorem fix_eq_ωSup_of_ωScottContinuous (hc : ωScottContinuous g) : Part.fix theorem fix_eq_of_ωScottContinuous (hc : ωScottContinuous g) : Part.fix g = g (Part.fix g) := by - rw [fix_eq_ωSup_of_ωScottContinuous, hc.map_ωSup] + rw [fix_eq_ωSup_of_ωScottContinuous hc, hc.map_ωSup] apply le_antisymm · apply ωSup_le_ωSup_of_le _ - exact hc intro i exists i intro x diff --git a/Mathlib/Control/Monad/Cont.lean b/Mathlib/Control/Monad/Cont.lean index 4a719782d7e74..29ed930cc7cb5 100644 --- a/Mathlib/Control/Monad/Cont.lean +++ b/Mathlib/Control/Monad/Cont.lean @@ -49,7 +49,7 @@ namespace ContT export MonadCont (Label goto) -variable {r : Type u} {m : Type u → Type v} {α β γ ω : Type w} +variable {r : Type u} {m : Type u → Type v} {α β : Type w} def run : ContT r m α → (α → m r) → m r := id diff --git a/Mathlib/Control/Monad/Writer.lean b/Mathlib/Control/Monad/Writer.lean index fcbf590189c9f..a9b71af0c73a6 100644 --- a/Mathlib/Control/Monad/Writer.lean +++ b/Mathlib/Control/Monad/Writer.lean @@ -57,7 +57,7 @@ protected def runThe (ω : Type u) (cmd : WriterT ω M α) : M (α × ω) := cmd @[ext] protected theorem ext {ω : Type u} (x x' : WriterT ω M α) (h : x.run = x'.run) : x = x' := h -variable {ω : Type u} {α β : Type u} [Monad M] +variable [Monad M] /-- Creates an instance of `Monad`, with explicitly given `empty` and `append` operations. diff --git a/Mathlib/Control/Traversable/Basic.lean b/Mathlib/Control/Traversable/Basic.lean index e9103c5c55aa4..eff2d5afd7056 100644 --- a/Mathlib/Control/Traversable/Basic.lean +++ b/Mathlib/Control/Traversable/Basic.lean @@ -6,6 +6,7 @@ Authors: Simon Hudon import Mathlib.Data.Option.Defs import Mathlib.Control.Functor import Batteries.Data.List.Basic +import Mathlib.Control.Basic /-! # Traversable type class @@ -60,8 +61,8 @@ universe u v w section ApplicativeTransformation -variable (F : Type u → Type v) [Applicative F] [LawfulApplicative F] -variable (G : Type u → Type w) [Applicative G] [LawfulApplicative G] +variable (F : Type u → Type v) [Applicative F] +variable (G : Type u → Type w) [Applicative G] /-- A transformation between applicative functors. It is a natural transformation such that `app` preserves the `Pure.pure` and @@ -203,8 +204,7 @@ export Traversable (traverse) section Functions variable {t : Type u → Type u} -variable {m : Type u → Type v} [Applicative m] -variable {α β : Type u} +variable {α : Type u} variable {f : Type u → Type u} [Applicative f] /-- A traversable functor commutes with all applicative functors. -/ @@ -249,8 +249,6 @@ instance : LawfulTraversable Id where section -variable {F : Type u → Type v} [Applicative F] - instance : Traversable Option := ⟨Option.traverse⟩ diff --git a/Mathlib/Control/Traversable/Equiv.lean b/Mathlib/Control/Traversable/Equiv.lean index fbd1a7fcc724e..db32b26b14bb2 100644 --- a/Mathlib/Control/Traversable/Equiv.lean +++ b/Mathlib/Control/Traversable/Equiv.lean @@ -53,7 +53,7 @@ protected theorem id_map {α : Type u} (x : t' α) : Equiv.map eqv id x = x := b protected theorem comp_map {α β γ : Type u} (g : α → β) (h : β → γ) (x : t' α) : Equiv.map eqv (h ∘ g) x = Equiv.map eqv h (Equiv.map eqv g x) := by - simpa [Equiv.map] using comp_map .. + simp [Equiv.map, Function.comp_def] protected theorem lawfulFunctor : @LawfulFunctor _ (Equiv.functor eqv) := -- Porting note: why is `_inst` required here? diff --git a/Mathlib/Control/Traversable/Instances.lean b/Mathlib/Control/Traversable/Instances.lean index 9e4afad602947..a91d6a6202f43 100644 --- a/Mathlib/Control/Traversable/Instances.lean +++ b/Mathlib/Control/Traversable/Instances.lean @@ -32,7 +32,7 @@ theorem Option.id_traverse {α} (x : Option α) : Option.traverse (pure : α → theorem Option.comp_traverse {α β γ} (f : β → F γ) (g : α → G β) (x : Option α) : Option.traverse (Comp.mk ∘ (f <$> ·) ∘ g) x = Comp.mk (Option.traverse f <$> Option.traverse g x) := by - cases x <;> simp! [functor_norm] <;> rfl + cases x <;> (simp! [functor_norm] <;> rfl) theorem Option.traverse_eq_map_id {α β} (f : α → β) (x : Option α) : Option.traverse ((pure : _ → Id _) ∘ f) x = (pure : _ → Id _) (f <$> x) := by cases x <;> rfl @@ -148,7 +148,7 @@ variable [LawfulApplicative G] protected theorem comp_traverse {α β γ : Type u} (f : β → F γ) (g : α → G β) (x : σ ⊕ α) : Sum.traverse (Comp.mk ∘ (f <$> ·) ∘ g) x = Comp.mk.{u} (Sum.traverse f <$> Sum.traverse g x) := by - cases x <;> simp! [Sum.traverse, map_id, functor_norm] <;> rfl + cases x <;> (simp! [Sum.traverse, map_id, functor_norm] <;> rfl) protected theorem traverse_eq_map_id {α β} (f : α → β) (x : σ ⊕ α) : Sum.traverse ((pure : _ → Id _) ∘ f) x = (pure : _ → Id _) (f <$> x) := by diff --git a/Mathlib/Control/Traversable/Lemmas.lean b/Mathlib/Control/Traversable/Lemmas.lean index 25ada54df0f22..7b98b4bf635c3 100644 --- a/Mathlib/Control/Traversable/Lemmas.lean +++ b/Mathlib/Control/Traversable/Lemmas.lean @@ -39,7 +39,6 @@ variable [Applicative F] [LawfulApplicative F] variable [Applicative G] [LawfulApplicative G] variable {α β γ : Type u} variable (g : α → F β) -variable (h : β → G γ) variable (f : β → γ) /-- The natural applicative transformation from the identity functor @@ -56,7 +55,7 @@ def PureTransformation : theorem pureTransformation_apply {α} (x : id α) : PureTransformation F x = pure x := rfl -variable {F G} (x : t β) +variable {F G} -- Porting note: need to specify `m/F/G := Id` because `id` no longer has a `Monad` instance theorem map_eq_traverse_id : map (f := t) f = traverse (m := Id) (pure ∘ f) := diff --git a/Mathlib/Control/ULift.lean b/Mathlib/Control/ULift.lean index f294e51cf20de..2482e0095fe06 100644 --- a/Mathlib/Control/ULift.lean +++ b/Mathlib/Control/ULift.lean @@ -78,7 +78,7 @@ end PLift namespace ULift -variable {α : Type u} {β : Type v} {f : α → β} +variable {α : Type u} {β : Type v} /-- Functorial action. -/ protected def map (f : α → β) (a : ULift.{u'} α) : ULift.{v'} β := ULift.up.{v'} (f a.down) diff --git a/Mathlib/Data/Array/ExtractLemmas.lean b/Mathlib/Data/Array/ExtractLemmas.lean index bc66fc0660fbc..b27b5245af41d 100644 --- a/Mathlib/Data/Array/ExtractLemmas.lean +++ b/Mathlib/Data/Array/ExtractLemmas.lean @@ -27,7 +27,7 @@ theorem extract_append_left {a b : Array α} {i j : Nat} (h : j ≤ a.size) : · simp only [size_extract, size_append] omega · intro h1 h2 h3 - rw [get_extract, get_append_left, get_extract] + rw [getElem_extract, getElem_append_left, getElem_extract] theorem extract_append_right {a b : Array α} {i j : Nat} (h : a.size ≤ i) : (a ++ b).extract i j = b.extract (i - a.size) (j - a.size) := by @@ -35,8 +35,8 @@ theorem extract_append_right {a b : Array α} {i j : Nat} (h : a.size ≤ i) : · rw [size_extract, size_extract, size_append] omega · intro k hi h2 - rw [get_extract, get_extract, - get_append_right (show size a ≤ i + k by omega)] + rw [getElem_extract, getElem_extract, + getElem_append_right (show size a ≤ i + k by omega)] congr omega @@ -50,6 +50,6 @@ theorem extract_extract {s1 e2 e1 s2 : Nat} {a : Array α} (h : s1 + e2 ≤ e1) · simp only [size_extract] omega · intro i h1 h2 - simp only [get_extract, Nat.add_assoc] + simp only [getElem_extract, Nat.add_assoc] end Array diff --git a/Mathlib/Data/Complex/Basic.lean b/Mathlib/Data/Complex/Basic.lean index 6483469eea3bc..bb39cc9638ee7 100644 --- a/Mathlib/Data/Complex/Basic.lean +++ b/Mathlib/Data/Complex/Basic.lean @@ -329,8 +329,7 @@ instance addCommGroup : AddCommGroup ℂ := intros; ext <;> simp [AddMonoid.nsmul_succ, add_mul, add_comm, smul_re, smul_im] zsmul_succ' := by - intros; ext <;> simp [SubNegMonoid.zsmul_succ', add_mul, add_comm, - smul_re, smul_im] + intros; ext <;> simp [add_mul, smul_re, smul_im] zsmul_neg' := by intros; ext <;> simp [zsmul_neg', add_mul, smul_re, smul_im] add_assoc := by intros; ext <;> simp [add_assoc] @@ -442,6 +441,15 @@ lemma re_ofNat (n : ℕ) [n.AtLeastTwo] : (no_index (OfNat.ofNat n) : ℂ).re = @[simp, norm_cast] lemma ratCast_re (q : ℚ) : (q : ℂ).re = q := rfl @[simp, norm_cast] lemma ratCast_im (q : ℚ) : (q : ℂ).im = 0 := rfl +lemma re_nsmul (n : ℕ) (z : ℂ) : (n • z).re = n • z.re := smul_re .. +lemma im_nsmul (n : ℕ) (z : ℂ) : (n • z).im = n • z.im := smul_im .. +lemma re_zsmul (n : ℤ) (z : ℂ) : (n • z).re = n • z.re := smul_re .. +lemma im_zsmul (n : ℤ) (z : ℂ) : (n • z).im = n • z.im := smul_im .. +@[simp] lemma re_nnqsmul (q : ℚ≥0) (z : ℂ) : (q • z).re = q • z.re := smul_re .. +@[simp] lemma im_nnqsmul (q : ℚ≥0) (z : ℂ) : (q • z).im = q • z.im := smul_im .. +@[simp] lemma re_qsmul (q : ℚ) (z : ℂ) : (q • z).re = q • z.re := smul_re .. +@[simp] lemma im_qsmul (q : ℚ) (z : ℂ) : (q • z).im = q • z.im := smul_im .. + @[deprecated (since := "2024-04-17")] alias rat_cast_im := ratCast_im @@ -628,6 +636,28 @@ def ofReal : ℝ →+* ℂ where theorem ofReal_eq_coe (r : ℝ) : ofReal r = r := rfl +variable {α : Type*} + +@[simp] lemma ofReal_comp_add (f g : α → ℝ) : ofReal' ∘ (f + g) = ofReal' ∘ f + ofReal' ∘ g := + map_comp_add ofReal .. + +@[simp] lemma ofReal_comp_sub (f g : α → ℝ) : ofReal' ∘ (f - g) = ofReal' ∘ f - ofReal' ∘ g := + map_comp_sub ofReal .. + +@[simp] lemma ofReal_comp_neg (f : α → ℝ) : ofReal' ∘ (-f) = -(ofReal' ∘ f) := map_comp_neg ofReal _ + +lemma ofReal_comp_nsmul (n : ℕ) (f : α → ℝ) : ofReal' ∘ (n • f) = n • (ofReal' ∘ f) := + map_comp_nsmul ofReal .. + +lemma ofReal_comp_zsmul (n : ℤ) (f : α → ℝ) : ofReal' ∘ (n • f) = n • (ofReal' ∘ f) := + map_comp_zsmul ofReal .. + +@[simp] lemma ofReal_comp_mul (f g : α → ℝ) : ofReal' ∘ (f * g) = ofReal' ∘ f * ofReal' ∘ g := + map_comp_mul ofReal .. + +@[simp] lemma ofReal_comp_pow (f : α → ℝ) (n : ℕ) : ofReal' ∘ (f ^ n) = (ofReal' ∘ f) ^ n := + map_comp_pow ofReal .. + @[simp] theorem I_sq : I ^ 2 = -1 := by rw [sq, I_mul_I] diff --git a/Mathlib/Data/Complex/BigOperators.lean b/Mathlib/Data/Complex/BigOperators.lean index 43c85d7750bfa..df65eec1fe310 100644 --- a/Mathlib/Data/Complex/BigOperators.lean +++ b/Mathlib/Data/Complex/BigOperators.lean @@ -3,14 +3,16 @@ Copyright (c) 2017 Kevin Buzzard. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kevin Buzzard, Mario Carneiro -/ -import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.BigOperators.Balance import Mathlib.Data.Complex.Basic /-! # Finite sums and products of complex numbers - -/ +open Fintype +open scoped BigOperators + namespace Complex variable {α : Type*} (s : Finset α) @@ -23,12 +25,45 @@ theorem ofReal_prod (f : α → ℝ) : ((∏ i ∈ s, f i : ℝ) : ℂ) = ∏ i theorem ofReal_sum (f : α → ℝ) : ((∑ i ∈ s, f i : ℝ) : ℂ) = ∑ i ∈ s, (f i : ℂ) := map_sum ofReal _ _ +@[simp, norm_cast] +lemma ofReal_expect (f : α → ℝ) : (𝔼 i ∈ s, f i : ℝ) = 𝔼 i ∈ s, (f i : ℂ) := + map_expect ofReal .. + +@[simp, norm_cast] +lemma ofReal_balance [Fintype α] (f : α → ℝ) (a : α) : + ((balance f a : ℝ) : ℂ) = balance ((↑) ∘ f) a := by simp [balance] + +@[simp] lemma ofReal_comp_balance {ι : Type*} [Fintype ι] (f : ι → ℝ) : + ofReal ∘ balance f = balance (ofReal ∘ f : ι → ℂ) := funext <| ofReal_balance _ + @[simp] theorem re_sum (f : α → ℂ) : (∑ i ∈ s, f i).re = ∑ i ∈ s, (f i).re := map_sum reAddGroupHom f s +@[simp] +lemma re_expect (f : α → ℂ) : (𝔼 i ∈ s, f i).re = 𝔼 i ∈ s, (f i).re := + map_expect (LinearMap.mk reAddGroupHom.toAddHom (by simp)) f s + +@[simp] +lemma re_balance [Fintype α] (f : α → ℂ) (a : α) : re (balance f a) = balance (re ∘ f) a := by + simp [balance] + +@[simp] lemma re_comp_balance {ι : Type*} [Fintype ι] (f : ι → ℂ) : + re ∘ balance f = balance (re ∘ f) := funext <| re_balance _ + @[simp] theorem im_sum (f : α → ℂ) : (∑ i ∈ s, f i).im = ∑ i ∈ s, (f i).im := map_sum imAddGroupHom f s +@[simp] +lemma im_expect (f : α → ℂ) : (𝔼 i ∈ s, f i).im = 𝔼 i ∈ s, (f i).im := + map_expect (LinearMap.mk imAddGroupHom.toAddHom (by simp)) f s + +@[simp] +lemma im_balance [Fintype α] (f : α → ℂ) (a : α) : im (balance f a) = balance (im ∘ f) a := by + simp [balance] + +@[simp] lemma im_comp_balance {ι : Type*} [Fintype ι] (f : ι → ℂ) : + im ∘ balance f = balance (im ∘ f) := funext <| im_balance _ + end Complex diff --git a/Mathlib/Data/Complex/Exponential.lean b/Mathlib/Data/Complex/Exponential.lean index c009cde85a7f2..e3fd8a0bac2f2 100644 --- a/Mathlib/Data/Complex/Exponential.lean +++ b/Mathlib/Data/Complex/Exponential.lean @@ -28,7 +28,7 @@ theorem isCauSeq_abs_exp (z : ℂ) : let ⟨n, hn⟩ := exists_nat_gt (abs z) have hn0 : (0 : ℝ) < n := lt_of_le_of_lt (abs.nonneg _) hn IsCauSeq.series_ratio_test n (abs z / n) (div_nonneg (abs.nonneg _) (le_of_lt hn0)) - (by rwa [div_lt_iff hn0, one_mul]) fun m hm => by + (by rwa [div_lt_iff₀ hn0, one_mul]) fun m hm => by rw [abs_abs, abs_abs, Nat.factorial_succ, pow_succ', mul_comm m.succ, Nat.cast_mul, ← div_div, mul_div_assoc, mul_div_right_comm, map_mul, map_div₀, abs_natCast] gcongr @@ -1110,7 +1110,7 @@ theorem exp_bound {x : ℂ} (hx : abs x ≤ 1) {n : ℕ} (hn : 0 < n) : simp_rw [map_mul, map_pow, map_div₀, abs_natCast] gcongr rw [abv_pow abs] - exact pow_le_one _ (abs.nonneg _) hx + exact pow_le_one₀ (abs.nonneg _) hx _ = abs x ^ n * ∑ m ∈ (range j).filter fun k => n ≤ k, (1 / m.factorial : ℝ) := by simp [abs_mul, abv_pow abs, abs_div, ← mul_sum] _ ≤ abs x ^ n * (n.succ * (n.factorial * n : ℝ)⁻¹) := by @@ -1334,9 +1334,9 @@ theorem cos_pos_of_le_one {x : ℝ} (hx : |x| ≤ 1) : 0 < cos x := (calc |x| ^ 4 * (5 / 96) + x ^ 2 / 2 ≤ 1 * (5 / 96) + 1 / 2 := by gcongr - · exact pow_le_one _ (abs_nonneg _) hx + · exact pow_le_one₀ (abs_nonneg _) hx · rw [sq, ← abs_mul_self, abs_mul] - exact mul_le_one hx (abs_nonneg _) hx + exact mul_le_one₀ hx (abs_nonneg _) hx _ < 1 := by norm_num) _ ≤ cos x := sub_le_comm.1 (abs_sub_le_iff.1 (cos_bound hx)).2 @@ -1395,10 +1395,11 @@ theorem exp_bound_div_one_sub_of_interval' {x : ℝ} (h1 : 0 < x) (h2 : x < 1) : -- Porting note: was `norm_num [Finset.sum] <;> nlinarith` -- This proof should be restored after the norm_num plugin for big operators is ported. -- (It may also need the positivity extensions in #3907.) - repeat erw [Finset.sum_range_succ] + erw [Finset.sum_range_succ] + repeat rw [Finset.sum_range_succ] norm_num [Nat.factorial] nlinarith - _ < 1 / (1 - x) := by rw [lt_div_iff] <;> nlinarith + _ < 1 / (1 - x) := by rw [lt_div_iff₀] <;> nlinarith theorem exp_bound_div_one_sub_of_interval {x : ℝ} (h1 : 0 ≤ x) (h2 : x < 1) : Real.exp x ≤ 1 / (1 - x) := by @@ -1412,7 +1413,7 @@ theorem add_one_lt_exp {x : ℝ} (hx : x ≠ 0) : x + 1 < Real.exp x := by obtain h' | h' := le_or_lt 1 (-x) · linarith [x.exp_pos] have hx' : 0 < x + 1 := by linarith - simpa [add_comm, exp_neg, inv_lt_inv (exp_pos _) hx'] + simpa [add_comm, exp_neg, inv_lt_inv₀ (exp_pos _) hx'] using exp_bound_div_one_sub_of_interval' (neg_pos.2 hx) h' theorem add_one_le_exp (x : ℝ) : x + 1 ≤ Real.exp x := by diff --git a/Mathlib/Data/Complex/ExponentialBounds.lean b/Mathlib/Data/Complex/ExponentialBounds.lean index cb4022b3c3fe8..9531022b50196 100644 --- a/Mathlib/Data/Complex/ExponentialBounds.lean +++ b/Mathlib/Data/Complex/ExponentialBounds.lean @@ -36,16 +36,14 @@ theorem exp_one_lt_d9 : exp 1 < 2.7182818286 := lt_of_le_of_lt (sub_le_iff_le_add.1 (abs_sub_le_iff.1 exp_one_near_10).1) (by norm_num) theorem exp_neg_one_gt_d9 : 0.36787944116 < exp (-1) := by - rw [exp_neg, lt_inv _ (exp_pos _)] + rw [exp_neg, lt_inv_comm₀ _ (exp_pos _)] · refine lt_of_le_of_lt (sub_le_iff_le_add.1 (abs_sub_le_iff.1 exp_one_near_10).1) ?_ norm_num · norm_num theorem exp_neg_one_lt_d9 : exp (-1) < 0.3678794412 := by - rw [exp_neg, inv_lt (exp_pos _)] - · refine lt_of_lt_of_le ?_ (sub_le_comm.1 (abs_sub_le_iff.1 exp_one_near_10).2) - norm_num - · norm_num + rw [exp_neg, inv_lt_comm₀ (exp_pos _) (by norm_num)] + exact lt_of_lt_of_le (by norm_num) (sub_le_comm.1 (abs_sub_le_iff.1 exp_one_near_10).2) theorem log_two_near_10 : |log 2 - 287209 / 414355| ≤ 1 / 10 ^ 10 := by suffices |log 2 - 287209 / 414355| ≤ 1 / 17179869184 + (1 / 10 ^ 10 - 1 / 2 ^ 34) by diff --git a/Mathlib/Data/Complex/FiniteDimensional.lean b/Mathlib/Data/Complex/FiniteDimensional.lean index 5fbde35674c53..f989ee2a1847c 100644 --- a/Mathlib/Data/Complex/FiniteDimensional.lean +++ b/Mathlib/Data/Complex/FiniteDimensional.lean @@ -15,12 +15,11 @@ This file contains the `FiniteDimensional ℝ ℂ` instance, as well as some res (`finrank` and `Module.rank`). -/ -open FiniteDimensional +open Module namespace Complex -instance : FiniteDimensional ℝ ℂ := - of_fintype_basis basisOneI +instance : FiniteDimensional ℝ ℂ := .of_fintype_basis basisOneI @[simp] theorem finrank_real_complex : finrank ℝ ℂ = 2 := by @@ -50,8 +49,8 @@ theorem rank_real_of_complex (E : Type*) [AddCommGroup E] [Module ℂ E] : simp only [Cardinal.lift_id'] theorem finrank_real_of_complex (E : Type*) [AddCommGroup E] [Module ℂ E] : - FiniteDimensional.finrank ℝ E = 2 * FiniteDimensional.finrank ℂ E := by - rw [← FiniteDimensional.finrank_mul_finrank ℝ ℂ E, Complex.finrank_real_complex] + Module.finrank ℝ E = 2 * Module.finrank ℂ E := by + rw [← Module.finrank_mul_finrank ℝ ℂ E, Complex.finrank_real_complex] section Rational diff --git a/Mathlib/Data/Countable/Basic.lean b/Mathlib/Data/Countable/Basic.lean index 9b80d33df3f88..89694dd120b07 100644 --- a/Mathlib/Data/Countable/Basic.lean +++ b/Mathlib/Data/Countable/Basic.lean @@ -66,7 +66,7 @@ instance Sum.uncountable_inr [Uncountable β] : Uncountable (α ⊕ β) := inr_injective.uncountable instance Option.instCountable [Countable α] : Countable (Option α) := - Countable.of_equiv _ (Equiv.optionEquivSumPUnit.{_, 0} α).symm + Countable.of_equiv _ (Equiv.optionEquivSumPUnit.{0, _} α).symm instance WithTop.instCountable [Countable α] : Countable (WithTop α) := Option.instCountable instance WithBot.instCountable [Countable α] : Countable (WithBot α) := Option.instCountable diff --git a/Mathlib/Data/DFinsupp/Order.lean b/Mathlib/Data/DFinsupp/Order.lean index db1c8bc2bdd5f..ebb4970f7a3ce 100644 --- a/Mathlib/Data/DFinsupp/Order.lean +++ b/Mathlib/Data/DFinsupp/Order.lean @@ -44,7 +44,14 @@ lemma le_def : f ≤ g ↔ ∀ i, f i ≤ g i := Iff.rfl def orderEmbeddingToFun : (Π₀ i, α i) ↪o ∀ i, α i where toFun := DFunLike.coe inj' := DFunLike.coe_injective - map_rel_iff' := by rfl + map_rel_iff' := + #adaptation_note + /-- + This proof used to be `rfl`, + but has been temporarily broken by https://github.com/leanprover/lean4/pull/5329. + It can hopefully be restored after https://github.com/leanprover/lean4/pull/5359 + -/ + Iff.rfl @[simp, norm_cast] lemma coe_orderEmbeddingToFun : ⇑(orderEmbeddingToFun (α := α)) = DFunLike.coe := rfl diff --git a/Mathlib/Data/DFinsupp/WellFounded.lean b/Mathlib/Data/DFinsupp/WellFounded.lean index 4262697dac419..082f7478b3b5e 100644 --- a/Mathlib/Data/DFinsupp/WellFounded.lean +++ b/Mathlib/Data/DFinsupp/WellFounded.lean @@ -215,7 +215,7 @@ protected theorem DFinsupp.wellFoundedLT [∀ i, Zero (α i)] [∀ i, Preorder ( simp (config := { unfoldPartialApp := true }) only [Function.swap] -/ simp only [Function.swap_def] exact IsWellFounded.wf - refine Subrelation.wf (fun h => ?_) <| InvImage.wf (mapRange (fun i ↦ e i) fun _ ↦ rfl) this + refine Subrelation.wf (fun h => ?_) <| InvImage.wf (mapRange e fun _ ↦ rfl) this have := IsStrictOrder.swap (@WellOrderingRel ι) obtain ⟨i, he, hl⟩ := lex_lt_of_lt_of_preorder (Function.swap WellOrderingRel) h exact ⟨i, fun j hj ↦ Quot.sound (he j hj), hl⟩⟩ diff --git a/Mathlib/Data/ENNReal/Basic.lean b/Mathlib/Data/ENNReal/Basic.lean index e44228f3991d3..11fe99146aa06 100644 --- a/Mathlib/Data/ENNReal/Basic.lean +++ b/Mathlib/Data/ENNReal/Basic.lean @@ -711,8 +711,3 @@ def evalENNRealOfNNReal : PositivityExt where eval {u α} _zα _pα e := do | _, _, _ => throwError "not ENNReal.ofNNReal" end Mathlib.Meta.Positivity - -@[deprecated (since := "2023-12-23")] protected alias -ENNReal.le_inv_smul_iff_of_pos := le_inv_smul_iff_of_pos -@[deprecated (since := "2023-12-23")] protected alias -ENNReal.inv_smul_le_iff_of_pos := inv_smul_le_iff_of_pos diff --git a/Mathlib/Data/ENNReal/Inv.lean b/Mathlib/Data/ENNReal/Inv.lean index d0e3217ac181c..19655b9e5fb17 100644 --- a/Mathlib/Data/ENNReal/Inv.lean +++ b/Mathlib/Data/ENNReal/Inv.lean @@ -438,9 +438,7 @@ protected theorem half_lt_self (hz : a ≠ 0) (ht : a ≠ ∞) : a / 2 < a := by protected theorem half_le_self : a / 2 ≤ a := le_add_self.trans_eq <| ENNReal.add_halves _ -theorem sub_half (h : a ≠ ∞) : a - a / 2 = a / 2 := by - lift a to ℝ≥0 using h - exact sub_eq_of_add_eq (mul_ne_top coe_ne_top <| by simp) (ENNReal.add_halves a) +theorem sub_half (h : a ≠ ∞) : a - a / 2 = a / 2 := ENNReal.sub_eq_of_eq_add' h a.add_halves.symm @[simp] theorem one_sub_inv_two : (1 : ℝ≥0∞) - 2⁻¹ = 2⁻¹ := by @@ -576,13 +574,13 @@ theorem Ioo_zero_top_eq_iUnion_Ico_zpow {y : ℝ≥0∞} (hy : 1 < y) (h'y : y theorem zpow_le_of_le {x : ℝ≥0∞} (hx : 1 ≤ x) {a b : ℤ} (h : a ≤ b) : x ^ a ≤ x ^ b := by induction' a with a a <;> induction' b with b b · simp only [Int.ofNat_eq_coe, zpow_natCast] - exact pow_le_pow_right hx (Int.le_of_ofNat_le_ofNat h) + exact pow_right_mono₀ hx (Int.le_of_ofNat_le_ofNat h) · apply absurd h (not_le_of_gt _) exact lt_of_lt_of_le (Int.negSucc_lt_zero _) (Int.ofNat_nonneg _) · simp only [zpow_negSucc, Int.ofNat_eq_coe, zpow_natCast] refine (ENNReal.inv_le_one.2 ?_).trans ?_ <;> exact one_le_pow_of_one_le' hx _ · simp only [zpow_negSucc, ENNReal.inv_le_inv] - apply pow_le_pow_right hx + apply pow_right_mono₀ hx simpa only [← Int.ofNat_le, neg_le_neg_iff, Int.ofNat_add, Int.ofNat_one, Int.negSucc_eq] using h @@ -603,5 +601,250 @@ protected theorem zpow_sub {x : ℝ≥0∞} (x_ne_zero : x ≠ 0) (x_ne_top : x x ^ (m - n) = (x ^ m) * (x ^ n)⁻¹ := by rw [sub_eq_add_neg, ENNReal.zpow_add x_ne_zero x_ne_top, ENNReal.zpow_neg x_ne_zero x_ne_top n] +variable {ι κ : Sort*} {f g : ι → ℝ≥0∞} {s : Set ℝ≥0∞} {a : ℝ≥0∞} + +@[simp] lemma iSup_eq_zero : ⨆ i, f i = 0 ↔ ∀ i, f i = 0 := iSup_eq_bot + +@[simp] lemma iSup_zero_eq_zero : ⨆ _ : ι, (0 : ℝ≥0∞) = 0 := by simp + +lemma iSup_natCast : ⨆ n : ℕ, (n : ℝ≥0∞) = ∞ := + (iSup_eq_top _).2 fun _b hb => ENNReal.exists_nat_gt (lt_top_iff_ne_top.1 hb) + +@[simp] lemma iSup_lt_eq_self (a : ℝ≥0∞) : ⨆ b, ⨆ _ : b < a, b = a := by + refine le_antisymm (iSup₂_le fun b hb ↦ hb.le) ?_ + refine le_of_forall_lt fun c hca ↦ ?_ + obtain ⟨d, hcd, hdb⟩ := exists_between hca + exact hcd.trans_le <| le_iSup₂_of_le d hdb le_rfl + +lemma isUnit_iff : IsUnit a ↔ a ≠ 0 ∧ a ≠ ∞ := by + refine ⟨fun ha ↦ ⟨ha.ne_zero, ?_⟩, + fun ha ↦ ⟨⟨a, a⁻¹, ENNReal.mul_inv_cancel ha.1 ha.2, ENNReal.inv_mul_cancel ha.1 ha.2⟩, rfl⟩⟩ + obtain ⟨u, rfl⟩ := ha + rintro hu + have := congr($hu * u⁻¹) + norm_cast at this + simp [mul_inv_cancel] at this + +/-- Left multiplication by a nonzero finite `a` as an order isomorphism. -/ +@[simps! toEquiv apply symm_apply] +def mulLeftOrderIso (a : ℝ≥0∞) (ha : IsUnit a) : ℝ≥0∞ ≃o ℝ≥0∞ where + toEquiv := ha.unit.mulLeft + map_rel_iff' := by simp [ENNReal.mul_le_mul_left, ha.ne_zero, (isUnit_iff.1 ha).2] + +/-- Right multiplication by a nonzero finite `a` as an order isomorphism. -/ +@[simps! toEquiv apply symm_apply] +def mulRightOrderIso (a : ℝ≥0∞) (ha : IsUnit a) : ℝ≥0∞ ≃o ℝ≥0∞ where + toEquiv := ha.unit.mulRight + map_rel_iff' := by simp [ENNReal.mul_le_mul_right, ha.ne_zero, (isUnit_iff.1 ha).2] + +lemma mul_iSup (a : ℝ≥0∞) (f : ι → ℝ≥0∞) : a * ⨆ i, f i = ⨆ i, a * f i := by + by_cases hf : ∀ i, f i = 0 + · simp [hf] + obtain rfl | ha₀ := eq_or_ne a 0 + · simp + obtain rfl | ha := eq_or_ne a ∞ + · obtain ⟨i, hi⟩ := not_forall.1 hf + simpa [iSup_eq_zero.not.2 hf, eq_comm (a := ⊤)] using le_iSup_of_le i (top_mul hi).ge + · exact (mulLeftOrderIso _ <| isUnit_iff.2 ⟨ha₀, ha⟩).map_iSup _ + +lemma iSup_mul (f : ι → ℝ≥0∞) (a : ℝ≥0∞) : (⨆ i, f i) * a = ⨆ i, f i * a := by + simp [mul_comm, mul_iSup] + +lemma mul_sSup {a : ℝ≥0∞} : a * sSup s = ⨆ b ∈ s, a * b := by + simp only [sSup_eq_iSup, mul_iSup] + +lemma sSup_mul {a : ℝ≥0∞} : sSup s * a = ⨆ b ∈ s, b * a := by + simp only [sSup_eq_iSup, iSup_mul] + +lemma iSup_div (f : ι → ℝ≥0∞) (a : ℝ≥0∞) : iSup f / a = ⨆ i, f i / a := iSup_mul .. +lemma sSup_div (s : Set ℝ≥0∞) (a : ℝ≥0∞) : sSup s / a = ⨆ b ∈ s, b / a := sSup_mul .. + +/-- Very general version for distributivity of multiplication over an infimum. + +See `ENNReal.mul_iInf_of_ne` for the special case assuming `a ≠ 0` and `a ≠ ∞`, and +`ENNReal.mul_iInf` for the special case assuming `Nonempty ι`. -/ +lemma mul_iInf' (hinfty : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) (h₀ : a = 0 → Nonempty ι) : + a * ⨅ i, f i = ⨅ i, a * f i := by + obtain rfl | ha₀ := eq_or_ne a 0 + · simp [h₀ rfl] + obtain rfl | ha := eq_or_ne a ∞ + · obtain ⟨i, hi⟩ | hf := em (∃ i, f i = 0) + · rw [(iInf_eq_bot _).2, (iInf_eq_bot _).2, bot_eq_zero, mul_zero] <;> + exact fun _ _↦ ⟨i, by simpa [hi]⟩ + · rw [top_mul (mt (hinfty rfl) hf), eq_comm, iInf_eq_top] + exact fun i ↦ top_mul fun hi ↦ hf ⟨i, hi⟩ + · exact (mulLeftOrderIso _ <| isUnit_iff.2 ⟨ha₀, ha⟩).map_iInf _ + +/-- Very general version for distributivity of multiplication over an infimum. + +See `ENNReal.iInf_mul_of_ne` for the special case assuming `a ≠ 0` and `a ≠ ∞`, and +`ENNReal.iInf_mul` for the special case assuming `Nonempty ι`. -/ +lemma iInf_mul' (hinfty : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) (h₀ : a = 0 → Nonempty ι) : + (⨅ i, f i) * a = ⨅ i, f i * a := by simpa only [mul_comm a] using mul_iInf' hinfty h₀ + +/-- If `a ≠ 0` and `a ≠ ∞`, then right multiplication by `a` maps infimum to infimum. + +See `ENNReal.mul_iInf'` for the general case, and `ENNReal.iInf_mul` for another special case that +assumes `Nonempty ι` but does not require `a ≠ 0`, and `ENNReal`. -/ +lemma mul_iInf_of_ne (ha₀ : a ≠ 0) (ha : a ≠ ∞) : a * ⨅ i, f i = ⨅ i, a * f i := + mul_iInf' (by simp [ha]) (by simp [ha₀]) + +/-- If `a ≠ 0` and `a ≠ ∞`, then right multiplication by `a` maps infimum to infimum. + +See `ENNReal.iInf_mul'` for the general case, and `ENNReal.iInf_mul` for another special case that +assumes `Nonempty ι` but does not require `a ≠ 0`. -/ +lemma iInf_mul_of_ne (ha₀ : a ≠ 0) (ha : a ≠ ∞) : (⨅ i, f i) * a = ⨅ i, f i * a := + iInf_mul' (by simp [ha]) (by simp [ha₀]) + +/-- See `ENNReal.mul_iInf'` for the general case, and `ENNReal.mul_iInf_of_ne` for another special +case that assumes `a ≠ 0` but does not require `Nonempty ι`. -/ +lemma mul_iInf [Nonempty ι] (hinfty : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) : + a * ⨅ i, f i = ⨅ i, a * f i := mul_iInf' hinfty fun _ ↦ ‹Nonempty ι› + +/-- See `ENNReal.iInf_mul'` for the general case, and `ENNReal.iInf_mul_of_ne` for another special +case that assumes `a ≠ 0` but does not require `Nonempty ι`. -/ +lemma iInf_mul [Nonempty ι] (hinfty : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) : + (⨅ i, f i) * a = ⨅ i, f i * a := iInf_mul' hinfty fun _ ↦ ‹Nonempty ι› + +/-- Very general version for distributivity of division over an infimum. + +See `ENNReal.iInf_div_of_ne` for the special case assuming `a ≠ 0` and `a ≠ ∞`, and +`ENNReal.iInf_div` for the special case assuming `Nonempty ι`. -/ +lemma iInf_div' (hinfty : a = 0 → ⨅ i, f i = 0 → ∃ i, f i = 0) (h₀ : a = ∞ → Nonempty ι) : + (⨅ i, f i) / a = ⨅ i, f i / a := iInf_mul' (by simpa) (by simpa) + +/-- If `a ≠ 0` and `a ≠ ∞`, then division by `a` maps infimum to infimum. + +See `ENNReal.iInf_div'` for the general case, and `ENNReal.iInf_div` for another special case that +assumes `Nonempty ι` but does not require `a ≠ ∞`. -/ +lemma iInf_div_of_ne (ha₀ : a ≠ 0) (ha : a ≠ ∞) : (⨅ i, f i) / a = ⨅ i, f i / a := + iInf_div' (by simp [ha₀]) (by simp [ha]) + +/-- See `ENNReal.iInf_div'` for the general case, and `ENNReal.iInf_div_of_ne` for another special +case that assumes `a ≠ ∞` but does not require `Nonempty ι`. -/ +lemma iInf_div [Nonempty ι] (hinfty : a = 0 → ⨅ i, f i = 0 → ∃ i, f i = 0) : + (⨅ i, f i) / a = ⨅ i, f i / a := iInf_div' hinfty fun _ ↦ ‹Nonempty ι› + +lemma inv_iInf (f : ι → ℝ≥0∞) : (⨅ i, f i)⁻¹ = ⨆ i, (f i)⁻¹ := OrderIso.invENNReal.map_iInf _ +lemma inv_iSup (f : ι → ℝ≥0∞) : (⨆ i, f i)⁻¹ = ⨅ i, (f i)⁻¹ := OrderIso.invENNReal.map_iSup _ + +lemma inv_sInf (s : Set ℝ≥0∞) : (sInf s)⁻¹ = ⨆ a ∈ s, a⁻¹ := by simp [sInf_eq_iInf, inv_iInf] +lemma inv_sSup (s : Set ℝ≥0∞) : (sSup s)⁻¹ = ⨅ a ∈ s, a⁻¹ := by simp [sSup_eq_iSup, inv_iSup] + +lemma add_iSup [Nonempty ι] (f : ι → ℝ≥0∞) : a + ⨆ i, f i = ⨆ i, a + f i := by + obtain rfl | ha := eq_or_ne a ∞ + · simp + refine le_antisymm ?_ <| iSup_le fun i ↦ add_le_add_left (le_iSup ..) _ + refine add_le_of_le_tsub_left_of_le (le_iSup_of_le (Classical.arbitrary _) le_self_add) ?_ + exact iSup_le fun i ↦ ENNReal.le_sub_of_add_le_left ha <| le_iSup (a + f ·) i + +lemma iSup_add [Nonempty ι] (f : ι → ℝ≥0∞) : (⨆ i, f i) + a = ⨆ i, f i + a := by + simp [add_comm, add_iSup] + +lemma add_biSup' {p : ι → Prop} (h : ∃ i, p i) (f : ι → ℝ≥0∞) : + a + ⨆ i, ⨆ _ : p i, f i = ⨆ i, ⨆ _ : p i, a + f i := by + haveI : Nonempty {i // p i} := nonempty_subtype.2 h + simp only [iSup_subtype', add_iSup] + +lemma biSup_add' {p : ι → Prop} (h : ∃ i, p i) (f : ι → ℝ≥0∞) : + (⨆ i, ⨆ _ : p i, f i) + a = ⨆ i, ⨆ _ : p i, f i + a := by simp only [add_comm, add_biSup' h] + +lemma add_biSup {ι : Type*} {s : Set ι} (hs : s.Nonempty) (f : ι → ℝ≥0∞) : + a + ⨆ i ∈ s, f i = ⨆ i ∈ s, a + f i := add_biSup' hs _ + +lemma biSup_add {ι : Type*} {s : Set ι} (hs : s.Nonempty) (f : ι → ℝ≥0∞) : + (⨆ i ∈ s, f i) + a = ⨆ i ∈ s, f i + a := biSup_add' hs _ + +lemma add_sSup (hs : s.Nonempty) : a + sSup s = ⨆ b ∈ s, a + b := by + rw [sSup_eq_iSup, add_biSup hs] + +lemma sSup_add (hs : s.Nonempty) : sSup s + a = ⨆ b ∈ s, b + a := by + rw [sSup_eq_iSup, biSup_add hs] + +lemma iSup_add_iSup_le [Nonempty ι] [Nonempty κ] {g : κ → ℝ≥0∞} (h : ∀ i j, f i + g j ≤ a) : + iSup f + iSup g ≤ a := by simp_rw [iSup_add, add_iSup]; exact iSup₂_le h + +lemma biSup_add_biSup_le' {p : ι → Prop} {q : κ → Prop} (hp : ∃ i, p i) (hq : ∃ j, q j) + {g : κ → ℝ≥0∞} (h : ∀ i, p i → ∀ j, q j → f i + g j ≤ a) : + (⨆ i, ⨆ _ : p i, f i) + ⨆ j, ⨆ _ : q j, g j ≤ a := by + simp_rw [biSup_add' hp, add_biSup' hq] + exact iSup₂_le fun i hi => iSup₂_le (h i hi) + +lemma biSup_add_biSup_le {ι κ : Type*} {s : Set ι} {t : Set κ} (hs : s.Nonempty) (ht : t.Nonempty) + {f : ι → ℝ≥0∞} {g : κ → ℝ≥0∞} {a : ℝ≥0∞} (h : ∀ i ∈ s, ∀ j ∈ t, f i + g j ≤ a) : + (⨆ i ∈ s, f i) + ⨆ j ∈ t, g j ≤ a := biSup_add_biSup_le' hs ht h + +lemma iSup_add_iSup (h : ∀ i j, ∃ k, f i + g j ≤ f k + g k) : iSup f + iSup g = ⨆ i, f i + g i := by + cases isEmpty_or_nonempty ι + · simp only [iSup_of_empty, bot_eq_zero, zero_add] + · refine le_antisymm ?_ (iSup_le fun a => add_le_add (le_iSup _ _) (le_iSup _ _)) + refine iSup_add_iSup_le fun i j => ?_ + rcases h i j with ⟨k, hk⟩ + exact le_iSup_of_le k hk + +lemma iSup_add_iSup_of_monotone {ι : Type*} [Preorder ι] [IsDirected ι (· ≤ ·)] {f g : ι → ℝ≥0∞} + (hf : Monotone f) (hg : Monotone g) : iSup f + iSup g = ⨆ a, f a + g a := + iSup_add_iSup fun i j ↦ (exists_ge_ge i j).imp fun _k ⟨hi, hj⟩ ↦ by gcongr <;> apply_rules + +lemma finsetSum_iSup {α ι : Type*} {s : Finset α} {f : α → ι → ℝ≥0∞} + (hf : ∀ i j, ∃ k, ∀ a, f a i ≤ f a k ∧ f a j ≤ f a k) : + ∑ a ∈ s, ⨆ i, f a i = ⨆ i, ∑ a ∈ s, f a i := by + induction' s using Finset.cons_induction with a s ha ihs + · simp + simp_rw [Finset.sum_cons, ihs] + refine iSup_add_iSup fun i j ↦ (hf i j).imp fun k hk ↦ ?_ + gcongr + exacts [(hk a).1, (hk _).2] + +lemma finsetSum_iSup_of_monotone {α ι : Type*} [Preorder ι] [IsDirected ι (· ≤ ·)] {s : Finset α} + {f : α → ι → ℝ≥0∞} (hf : ∀ a, Monotone (f a)) : (∑ a ∈ s, iSup (f a)) = ⨆ n, ∑ a ∈ s, f a n := + finsetSum_iSup fun i j ↦ (exists_ge_ge i j).imp fun _k ⟨hi, hj⟩ a ↦ ⟨hf a hi, hf a hj⟩ + +@[deprecated (since := "2024-07-14")] +alias finset_sum_iSup_nat := finsetSum_iSup_of_monotone + +lemma le_iInf_mul_iInf {g : κ → ℝ≥0∞} (hf : ∃ i, f i ≠ ∞) (hg : ∃ j, g j ≠ ∞) + (ha : ∀ i j, a ≤ f i * g j) : a ≤ (⨅ i, f i) * ⨅ j, g j := by + rw [← iInf_ne_top_subtype] + have := nonempty_subtype.2 hf + have := hg.nonempty + replace hg : ⨅ j, g j ≠ ∞ := by simpa using hg + rw [iInf_mul fun h ↦ (hg h).elim, le_iInf_iff] + rintro ⟨i, hi⟩ + simpa [mul_iInf fun h ↦ (hi h).elim] using ha i + +lemma iInf_mul_iInf {f g : ι → ℝ≥0∞} (hf : ∃ i, f i ≠ ∞) (hg : ∃ j, g j ≠ ∞) + (h : ∀ i j, ∃ k, f k * g k ≤ f i * g j) : (⨅ i, f i) * ⨅ i, g i = ⨅ i, f i * g i := by + refine le_antisymm (le_iInf fun i ↦ mul_le_mul' (iInf_le ..) (iInf_le ..)) + (le_iInf_mul_iInf hf hg fun i j ↦ ?_) + obtain ⟨k, hk⟩ := h i j + exact iInf_le_of_le k hk + +lemma smul_iSup {R} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (f : ι → ℝ≥0∞) (c : R) : + c • ⨆ i, f i = ⨆ i, c • f i := by + simp only [← smul_one_mul c (f _), ← smul_one_mul c (iSup _), ENNReal.mul_iSup] + +lemma smul_sSup {R} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (s : Set ℝ≥0∞) (c : R) : + c • sSup s = ⨆ a ∈ s, c • a := by + simp_rw [← smul_one_mul c (sSup s), ENNReal.mul_sSup, smul_one_mul] + +lemma sub_iSup [Nonempty ι] (ha : a ≠ ∞) : a - ⨆ i, f i = ⨅ i, a - f i := by + obtain ⟨i, hi⟩ | h := em (∃ i, a < f i) + · rw [tsub_eq_zero_iff_le.2 <| le_iSup_of_le _ hi.le, (iInf_eq_bot _).2, bot_eq_zero] + exact fun x hx ↦ ⟨i, by simpa [hi.le]⟩ + simp_rw [not_exists, not_lt] at h + refine le_antisymm (le_iInf fun i ↦ tsub_le_tsub_left (le_iSup ..) _) <| + ENNReal.le_sub_of_add_le_left (ne_top_of_le_ne_top ha <| iSup_le h) <| + add_le_of_le_tsub_right_of_le (iInf_le_of_le (Classical.arbitrary _) tsub_le_self) <| + iSup_le fun i ↦ ?_ + rw [← sub_sub_cancel ha (h _)] + exact tsub_le_tsub_left (iInf_le (a - f ·) i) _ + +-- TODO: Prove the two one-side versions +lemma exists_lt_add_of_lt_add {x y z : ℝ≥0∞} (h : x < y + z) (hy : y ≠ 0) (hz : z ≠ 0) : + ∃ y' < y, ∃ z' < z, x < y' + z' := by + contrapose! h; + simpa using biSup_add_biSup_le' (by exact ⟨0, hy.bot_lt⟩) (by exact ⟨0, hz.bot_lt⟩) h + end Inv end ENNReal diff --git a/Mathlib/Data/ENNReal/Operations.lean b/Mathlib/Data/ENNReal/Operations.lean index 9f0b1dbbbddc3..473c3d6c65d78 100644 --- a/Mathlib/Data/ENNReal/Operations.lean +++ b/Mathlib/Data/ENNReal/Operations.lean @@ -256,6 +256,7 @@ section Cancel -- Porting note (#11215): TODO: generalize to `WithTop` /-- An element `a` is `AddLECancellable` if `a + b ≤ a + c` implies `b ≤ c` for all `b` and `c`. This is true in `ℝ≥0∞` for all elements except `∞`. -/ +@[simp] theorem addLECancellable_iff_ne {a : ℝ≥0∞} : AddLECancellable a ↔ a ≠ ∞ := by constructor · rintro h rfl @@ -294,11 +295,13 @@ theorem sub_eq_sInf {a b : ℝ≥0∞} : a - b = sInf { d | a ≤ d + b } := le_antisymm (le_sInf fun _ h => tsub_le_iff_right.mpr h) <| sInf_le <| mem_setOf.2 le_tsub_add /-- This is a special case of `WithTop.coe_sub` in the `ENNReal` namespace -/ -@[simp] theorem coe_sub : (↑(r - p) : ℝ≥0∞) = ↑r - ↑p := WithTop.coe_sub +@[simp, norm_cast] theorem coe_sub : (↑(r - p) : ℝ≥0∞) = ↑r - ↑p := WithTop.coe_sub /-- This is a special case of `WithTop.top_sub_coe` in the `ENNReal` namespace -/ @[simp] theorem top_sub_coe : ∞ - ↑r = ∞ := WithTop.top_sub_coe +@[simp] lemma top_sub (ha : a ≠ ∞) : ∞ - a = ∞ := by lift a to ℝ≥0 using ha; exact top_sub_coe + /-- This is a special case of `WithTop.sub_top` in the `ENNReal` namespace -/ theorem sub_top : a - ∞ = 0 := WithTop.sub_top @@ -314,15 +317,37 @@ theorem natCast_sub (m n : ℕ) : ↑(m - n) = (m - n : ℝ≥0∞) := by @[deprecated (since := "2024-04-17")] alias nat_cast_sub := natCast_sub +/-- See `ENNReal.sub_eq_of_eq_add'` for a version assuming that `a = c + b` itself is finite rather +than `b`. -/ protected theorem sub_eq_of_eq_add (hb : b ≠ ∞) : a = c + b → a - b = c := (cancel_of_ne hb).tsub_eq_of_eq_add +/-- Weaker version of `ENNReal.sub_eq_of_eq_add` assuming that `a = c + b` itself is finite rather +han `b`. -/ +protected lemma sub_eq_of_eq_add' (ha : a ≠ ∞) : a = c + b → a - b = c := + (cancel_of_ne ha).tsub_eq_of_eq_add' + +/-- See `ENNReal.eq_sub_of_add_eq'` for a version assuming that `b = a + c` itself is finite rather +than `c`. -/ protected theorem eq_sub_of_add_eq (hc : c ≠ ∞) : a + c = b → a = b - c := (cancel_of_ne hc).eq_tsub_of_add_eq +/-- Weaker version of `ENNReal.eq_sub_of_add_eq` assuming that `b = a + c` itself is finite rather +than `c`. -/ +protected lemma eq_sub_of_add_eq' (hb : b ≠ ∞) : a + c = b → a = b - c := + (cancel_of_ne hb).eq_tsub_of_add_eq' + +/-- See `ENNReal.sub_eq_of_eq_add_rev'` for a version assuming that `a = b + c` itself is finite +rather than `b`. -/ protected theorem sub_eq_of_eq_add_rev (hb : b ≠ ∞) : a = b + c → a - b = c := (cancel_of_ne hb).tsub_eq_of_eq_add_rev +/-- Weaker version of `ENNReal.sub_eq_of_eq_add_rev` assuming that `a = b + c` itself is finite +rather than `b`. -/ +protected lemma sub_eq_of_eq_add_rev' (ha : a ≠ ∞) : a = b + c → a - b = c := + (cancel_of_ne ha).tsub_eq_of_eq_add_rev' + +@[deprecated ENNReal.sub_eq_of_eq_add (since := "2024-09-30")] theorem sub_eq_of_add_eq (hb : b ≠ ∞) (hc : a + b = c) : c - b = a := ENNReal.sub_eq_of_eq_add hb hc.symm @@ -338,7 +363,7 @@ protected theorem sub_add_eq_add_sub (hab : b ≤ a) (b_ne_top : b ≠ ∞) : a - b + c = a + c - b := by by_cases c_top : c = ∞ · simpa [c_top] using ENNReal.eq_sub_of_add_eq b_ne_top rfl - refine (sub_eq_of_add_eq b_ne_top ?_).symm + refine ENNReal.eq_sub_of_add_eq b_ne_top ?_ simp only [add_assoc, add_comm c b] simpa only [← add_assoc] using (add_left_inj c_top).mpr <| tsub_add_cancel_of_le hab diff --git a/Mathlib/Data/ENNReal/Real.lean b/Mathlib/Data/ENNReal/Real.lean index 4b6df926ef130..e9cc940e48612 100644 --- a/Mathlib/Data/ENNReal/Real.lean +++ b/Mathlib/Data/ENNReal/Real.lean @@ -235,7 +235,7 @@ lemma ofNat_le_ofReal {n : ℕ} [n.AtLeastTwo] {p : ℝ} : no_index (OfNat.ofNat n) ≤ ENNReal.ofReal p ↔ OfNat.ofNat n ≤ p := natCast_le_ofReal (NeZero.ne n) -@[simp] +@[simp, norm_cast] lemma ofReal_le_natCast {r : ℝ} {n : ℕ} : ENNReal.ofReal r ≤ n ↔ r ≤ n := coe_le_coe.trans Real.toNNReal_le_natCast @@ -508,6 +508,19 @@ theorem toReal_sSup (s : Set ℝ≥0∞) (hf : ∀ r ∈ s, r ≠ ∞) : (sSup s).toReal = sSup (ENNReal.toReal '' s) := by simp only [ENNReal.toReal, toNNReal_sSup s hf, NNReal.coe_sSup, Set.image_image] +@[simp] lemma ofReal_iInf [Nonempty ι] (f : ι → ℝ) : + ENNReal.ofReal (⨅ i, f i) = ⨅ i, ENNReal.ofReal (f i) := by + obtain ⟨i, hi⟩ | h := em (∃ i, f i ≤ 0) + · rw [(iInf_eq_bot _).2 fun _ _ ↦ ⟨i, by simpa [ofReal_of_nonpos hi]⟩] + simp [Real.iInf_nonpos' ⟨i, hi⟩] + replace h i : 0 ≤ f i := le_of_not_le fun hi ↦ h ⟨i, hi⟩ + refine eq_of_forall_le_iff fun a ↦ ?_ + obtain rfl | ha := eq_or_ne a ∞ + · simp + rw [le_iInf_iff, le_ofReal_iff_toReal_le ha, le_ciInf_iff ⟨0, by simpa [mem_lowerBounds]⟩] + · exact forall_congr' fun i ↦ (le_ofReal_iff_toReal_le ha (h _)).symm + · exact Real.iInf_nonneg h + theorem iInf_add : iInf f + a = ⨅ i, f i + a := le_antisymm (le_iInf fun _ => add_le_add (iInf_le _ _) <| le_rfl) (tsub_le_iff_right.1 <| le_iInf fun _ => tsub_le_iff_right.2 <| iInf_le _ _) @@ -545,51 +558,12 @@ theorem iInf_sum {α : Type*} {f : ι → α → ℝ≥0∞} {s : Finset α} [No rw [Finset.forall_mem_cons] at hk exact add_le_add hk.1.1 (Finset.sum_le_sum fun a ha => (hk.2 a ha).2) -/-- If `x ≠ 0` and `x ≠ ∞`, then right multiplication by `x` maps infimum to infimum. -See also `ENNReal.iInf_mul` that assumes `[Nonempty ι]` but does not require `x ≠ 0`. -/ -theorem iInf_mul_of_ne {ι} {f : ι → ℝ≥0∞} {x : ℝ≥0∞} (h0 : x ≠ 0) (h : x ≠ ∞) : - iInf f * x = ⨅ i, f i * x := - le_antisymm mul_right_mono.map_iInf_le - ((ENNReal.div_le_iff_le_mul (Or.inl h0) <| Or.inl h).mp <| - le_iInf fun _ => (ENNReal.div_le_iff_le_mul (Or.inl h0) <| Or.inl h).mpr <| iInf_le _ _) - -/-- If `x ≠ ∞`, then right multiplication by `x` maps infimum over a nonempty type to infimum. See -also `ENNReal.iInf_mul_of_ne` that assumes `x ≠ 0` but does not require `[Nonempty ι]`. -/ -theorem iInf_mul {ι} [Nonempty ι] {f : ι → ℝ≥0∞} {x : ℝ≥0∞} (h : x ≠ ∞) : - iInf f * x = ⨅ i, f i * x := by - by_cases h0 : x = 0 - · simp only [h0, mul_zero, iInf_const] - · exact iInf_mul_of_ne h0 h - -/-- If `x ≠ ∞`, then left multiplication by `x` maps infimum over a nonempty type to infimum. See -also `ENNReal.mul_iInf_of_ne` that assumes `x ≠ 0` but does not require `[Nonempty ι]`. -/ -theorem mul_iInf {ι} [Nonempty ι] {f : ι → ℝ≥0∞} {x : ℝ≥0∞} (h : x ≠ ∞) : - x * iInf f = ⨅ i, x * f i := by simpa only [mul_comm] using iInf_mul h - -/-- If `x ≠ 0` and `x ≠ ∞`, then left multiplication by `x` maps infimum to infimum. -See also `ENNReal.mul_iInf` that assumes `[Nonempty ι]` but does not require `x ≠ 0`. -/ -theorem mul_iInf_of_ne {ι} {f : ι → ℝ≥0∞} {x : ℝ≥0∞} (h0 : x ≠ 0) (h : x ≠ ∞) : - x * iInf f = ⨅ i, x * f i := by simpa only [mul_comm] using iInf_mul_of_ne h0 h - -/-! `supr_mul`, `mul_supr` and variants are in `Topology.Instances.ENNReal`. -/ - end iInf section iSup - -@[simp] -theorem iSup_eq_zero {ι : Sort*} {f : ι → ℝ≥0∞} : ⨆ i, f i = 0 ↔ ∀ i, f i = 0 := - iSup_eq_bot - -@[simp] -theorem iSup_zero_eq_zero {ι : Sort*} : ⨆ _ : ι, (0 : ℝ≥0∞) = 0 := by simp - theorem sup_eq_zero {a b : ℝ≥0∞} : a ⊔ b = 0 ↔ a = 0 ∧ b = 0 := sup_eq_bot_iff -theorem iSup_natCast : ⨆ n : ℕ, (n : ℝ≥0∞) = ∞ := - (iSup_eq_top _).2 fun _b hb => ENNReal.exists_nat_gt (lt_top_iff_ne_top.1 hb) - @[deprecated (since := "2024-04-05")] alias iSup_coe_nat := iSup_natCast end iSup diff --git a/Mathlib/Data/ENat/Basic.lean b/Mathlib/Data/ENat/Basic.lean index 1ff8e427f3cb9..3486a11a1cef2 100644 --- a/Mathlib/Data/ENat/Basic.lean +++ b/Mathlib/Data/ENat/Basic.lean @@ -259,4 +259,26 @@ theorem nat_induction {P : ℕ∞ → Prop} (a : ℕ∞) (h0 : P 0) (hsuc : ∀ · exact htop A · exact A _ +lemma add_one_nat_le_withTop_of_lt {m : ℕ} {n : WithTop ℕ∞} (h : m < n) : (m + 1 : ℕ) ≤ n := by + match n with + | ⊤ => exact le_top + | (⊤ : ℕ∞) => exact WithTop.coe_le_coe.2 (OrderTop.le_top _) + | (n : ℕ) => simpa only [Nat.cast_le, ge_iff_le, Nat.cast_lt] using h + +@[simp] lemma coe_top_add_one : ((⊤ : ℕ∞) : WithTop ℕ∞) + 1 = (⊤ : ℕ∞) := rfl + +@[simp] lemma add_one_eq_coe_top_iff (n : WithTop ℕ∞) : + n + 1 = (⊤ : ℕ∞) ↔ n = (⊤ : ℕ∞) := by + match n with + | ⊤ => exact Iff.rfl + | (⊤ : ℕ∞) => exact Iff.rfl + | (n : ℕ) => norm_cast; simp only [coe_ne_top, iff_false, ne_eq] + +@[simp] lemma nat_ne_coe_top (n : ℕ) : (n : WithTop ℕ∞) ≠ (⊤ : ℕ∞) := ne_of_beq_false rfl + +lemma one_le_iff_ne_zero_withTop {n : WithTop ℕ∞} : + 1 ≤ n ↔ n ≠ 0 := + ⟨fun h ↦ (zero_lt_one.trans_le h).ne', + fun h ↦ add_one_nat_le_withTop_of_lt (pos_iff_ne_zero.mpr h)⟩ + end ENat diff --git a/Mathlib/Data/Fin/Basic.lean b/Mathlib/Data/Fin/Basic.lean index 7763f1a2b0f45..edc71f8ff4d06 100644 --- a/Mathlib/Data/Fin/Basic.lean +++ b/Mathlib/Data/Fin/Basic.lean @@ -5,9 +5,11 @@ Authors: Robert Y. Lewis, Keeley Hoek -/ import Mathlib.Algebra.NeZero import Mathlib.Data.Nat.Defs +import Mathlib.Data.Int.DivMod import Mathlib.Logic.Embedding.Basic import Mathlib.Logic.Equiv.Set import Mathlib.Tactic.Common +import Mathlib.Tactic.Attr.Register /-! # The finite type with `n` elements @@ -190,6 +192,7 @@ protected theorem heq_ext_iff {k l : ℕ} (h : k = l) {i : Fin k} {j : Fin l} : end coe + section Order /-! @@ -332,6 +335,58 @@ theorem one_lt_last [NeZero n] : 1 < last (n + 1) := by end Order +/-! ### Coercions to `ℤ` and the `fin_omega` tactic. -/ + +open Int + +theorem coe_int_sub_eq_ite {n : Nat} (u v : Fin n) : + ((u - v : Fin n) : Int) = if v ≤ u then (u - v : Int) else (u - v : Int) + n := by + rw [Fin.sub_def] + split + · rw [ofNat_emod, Int.emod_eq_sub_self_emod, Int.emod_eq_of_lt] <;> omega + · rw [ofNat_emod, Int.emod_eq_of_lt] <;> omega + +theorem coe_int_sub_eq_mod {n : Nat} (u v : Fin n) : + ((u - v : Fin n) : Int) = ((u : Int) - (v : Int)) % n := by + rw [coe_int_sub_eq_ite] + split + · rw [Int.emod_eq_of_lt] <;> omega + · rw [Int.emod_eq_add_self_emod, Int.emod_eq_of_lt] <;> omega + +theorem coe_int_add_eq_ite {n : Nat} (u v : Fin n) : + ((u + v : Fin n) : Int) = if (u + v : ℕ) < n then (u + v : Int) else (u + v : Int) - n := by + rw [Fin.add_def] + split + · rw [ofNat_emod, Int.emod_eq_of_lt] <;> omega + · rw [ofNat_emod, Int.emod_eq_sub_self_emod, Int.emod_eq_of_lt] <;> omega + +theorem coe_int_add_eq_mod {n : Nat} (u v : Fin n) : + ((u + v : Fin n) : Int) = ((u : Int) + (v : Int)) % n := by + rw [coe_int_add_eq_ite] + split + · rw [Int.emod_eq_of_lt] <;> omega + · rw [Int.emod_eq_sub_self_emod, Int.emod_eq_of_lt] <;> omega + +-- Write `a + b` as `if (a + b : ℕ) < n then (a + b : ℤ) else (a + b : ℤ) - n` and +-- similarly `a - b` as `if (b : ℕ) ≤ a then (a - b : ℤ) else (a - b : ℤ) + n`. +attribute [fin_omega] coe_int_sub_eq_ite coe_int_add_eq_ite + +-- Rewrite inequalities in `Fin` to inequalities in `ℕ` +attribute [fin_omega] Fin.lt_iff_val_lt_val Fin.le_iff_val_le_val + +-- Rewrite `1 : Fin (n + 2)` to `1 : ℤ` +attribute [fin_omega] val_one + +/-- +Preprocessor for `omega` to handle inequalities in `Fin`. +Note that this involves a lot of case splitting, so may be slow. +-/ +-- Further adjustment to the simp set can probably make this more powerful. +-- Please experiment and PR updates! +macro "fin_omega" : tactic => `(tactic| + { try simp only [fin_omega, ← Int.ofNat_lt, ← Int.ofNat_le] at * + omega }) + section Add /-! @@ -359,16 +414,6 @@ section Monoid protected theorem add_zero [NeZero n] (k : Fin n) : k + 0 = k := by simp only [add_def, val_zero', Nat.add_zero, mod_eq_of_lt (is_lt k)] --- Porting note (#10618): removing `simp`, `simp` can prove it with AddCommMonoid instance -protected theorem zero_add [NeZero n] (k : Fin n) : 0 + k = k := by - simp [Fin.ext_iff, add_def, mod_eq_of_lt (is_lt k)] - -instance {a : ℕ} [NeZero n] : OfNat (Fin n) a where - ofNat := Fin.ofNat' a n.pos_of_neZero - -instance inhabited (n : ℕ) [NeZero n] : Inhabited (Fin n) := - ⟨0⟩ - instance inhabitedFinOneAdd (n : ℕ) : Inhabited (Fin (1 + n)) := haveI : NeZero (1 + n) := by rw [Nat.add_comm]; infer_instance inferInstance @@ -379,8 +424,8 @@ theorem default_eq_zero (n : ℕ) [NeZero n] : (default : Fin n) = 0 := section from_ad_hoc -@[simp] lemma ofNat'_zero {h : 0 < n} [NeZero n] : (Fin.ofNat' 0 h : Fin n) = 0 := rfl -@[simp] lemma ofNat'_one {h : 0 < n} [NeZero n] : (Fin.ofNat' 1 h : Fin n) = 1 := rfl +@[simp] lemma ofNat'_zero [NeZero n] : (Fin.ofNat' n 0) = 0 := rfl +@[simp] lemma ofNat'_one [NeZero n] : (Fin.ofNat' n 1) = 1 := rfl end from_ad_hoc @@ -461,13 +506,6 @@ lemma natCast_strictMono (hbn : b ≤ n) (hab : a < b) : (a : Fin (n + 1)) < b : end OfNatCoe -@[simp] -theorem one_eq_zero_iff [NeZero n] : (1 : Fin n) = 0 ↔ n = 1 := by - obtain _ | _ | n := n <;> simp [Fin.ext_iff] - -@[simp] -theorem zero_eq_one_iff [NeZero n] : (0 : Fin n) = 1 ↔ n = 1 := by rw [eq_comm, one_eq_zero_iff] - end Add section Succ @@ -523,10 +561,6 @@ This one instead uses a `NeZero n` typeclass hypothesis. theorem le_zero_iff' {n : ℕ} [NeZero n] {k : Fin n} : k ≤ 0 ↔ k = 0 := ⟨fun h => Fin.ext <| by rw [Nat.eq_zero_of_le_zero h]; rfl, by rintro rfl; exact Nat.le_refl _⟩ --- Move to Batteries? -@[simp] theorem cast_refl {n : Nat} (h : n = n) : - Fin.cast h = id := rfl - -- TODO: Move to Batteries @[simp] lemma castLE_inj {hmn : m ≤ n} {a b : Fin m} : castLE hmn a = castLE hmn b ↔ a = b := by simp [Fin.ext_iff] @@ -646,13 +680,14 @@ def castSuccEmb : Fin n ↪ Fin (n + 1) := castAddEmb _ @[simp, norm_cast] lemma coe_castSuccEmb : (castSuccEmb : Fin n → Fin (n + 1)) = Fin.castSucc := rfl -@[simp] -theorem castSucc_le_castSucc_iff {a b : Fin n} : castSucc a ≤ castSucc b ↔ a ≤ b := Iff.rfl -@[simp] -theorem succ_le_castSucc_iff {a b : Fin n} : succ a ≤ castSucc b ↔ a < b := by +theorem castSucc_le_succ {n} (i : Fin n) : i.castSucc ≤ i.succ := Nat.le_succ i + +@[simp] theorem castSucc_le_castSucc_iff {a b : Fin n} : castSucc a ≤ castSucc b ↔ a ≤ b := .rfl + +@[simp] theorem succ_le_castSucc_iff {a b : Fin n} : succ a ≤ castSucc b ↔ a < b := by rw [le_castSucc_iff, succ_lt_succ_iff] -@[simp] -theorem castSucc_lt_succ_iff {a b : Fin n} : castSucc a < succ b ↔ a ≤ b := by + +@[simp] theorem castSucc_lt_succ_iff {a b : Fin n} : 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} @@ -720,7 +755,7 @@ theorem castSucc_ne_zero_of_lt {p i : Fin n} (h : p < i) : castSucc i ≠ 0 := b exact ((zero_le _).trans_lt h).ne' 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 + not_iff_not.mpr <| succ_eq_last_succ theorem succ_ne_last_of_lt {p i : Fin n} (h : i < p) : succ i ≠ last n := by cases n @@ -783,7 +818,7 @@ theorem le_pred_iff {j : Fin n} {i : Fin (n + 1)} (hi : i ≠ 0) : j ≤ pred i 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) : + (ha' := castSucc_ne_zero_iff.mpr ha) : (a.pred ha).castSucc = (castSucc a).pred ha' := rfl theorem castSucc_pred_add_one_eq {a : Fin (n + 1)} (ha : a ≠ 0) : @@ -1436,12 +1471,11 @@ theorem eq_zero (n : Fin 1) : n = 0 := Subsingleton.elim _ _ instance uniqueFinOne : Unique (Fin 1) where uniq _ := Subsingleton.elim _ _ -@[simp] +@[deprecated val_eq_zero (since := "2024-09-18")] theorem coe_fin_one (a : Fin 1) : (a : ℕ) = 0 := by simp [Subsingleton.elim a 0] -lemma eq_one_of_neq_zero (i : Fin 2) (hi : i ≠ 0) : i = 1 := - fin_two_eq_of_eq_zero_iff - (by simpa only [one_eq_zero_iff, succ.injEq, iff_false, reduceCtorEq] using hi) +lemma eq_one_of_neq_zero (i : Fin 2) (hi : i ≠ 0) : i = 1 := by + fin_omega @[simp] theorem coe_neg_one : ↑(-1 : Fin (n + 1)) = n := by @@ -1454,15 +1488,7 @@ theorem last_sub (i : Fin (n + 1)) : last n - i = Fin.rev i := Fin.ext <| by rw [coe_sub_iff_le.2 i.le_last, val_last, val_rev, Nat.succ_sub_succ_eq_sub] theorem add_one_le_of_lt {n : ℕ} {a b : Fin (n + 1)} (h : a < b) : a + 1 ≤ b := by - cases' a with a ha - cases' b with b hb - cases n - · simp only [Nat.zero_add, Nat.lt_one_iff] at ha hb - simp [ha, hb] - simp only [le_iff_val_le_val, val_add, lt_iff_val_lt_val, val_mk, val_one] at h ⊢ - rwa [Nat.mod_eq_of_lt, Nat.succ_le_iff] - rw [Nat.succ_lt_succ_iff] - exact h.trans_le (Nat.le_of_lt_succ hb) + cases n <;> fin_omega theorem exists_eq_add_of_le {n : ℕ} {a b : Fin n} (h : a ≤ b) : ∃ k ≤ b, b = a + k := by obtain ⟨k, hk⟩ : ∃ k : ℕ, (b : ℕ) = a + k := Nat.exists_eq_add_of_le h @@ -1473,15 +1499,10 @@ theorem exists_eq_add_of_le {n : ℕ} {a b : Fin n} (h : a ≤ b) : ∃ k ≤ b, theorem exists_eq_add_of_lt {n : ℕ} {a b : Fin (n + 1)} (h : a < b) : ∃ k < b, k + 1 ≤ b ∧ b = a + k + 1 := by cases n - · cases' a with a ha - cases' b with b hb - simp only [Nat.zero_add, Nat.lt_one_iff] at ha hb - simp [ha, hb] at h + · omega obtain ⟨k, hk⟩ : ∃ k : ℕ, (b : ℕ) = a + k + 1 := Nat.exists_eq_add_of_lt h have hkb : k < b := by omega - refine ⟨⟨k, hkb.trans b.is_lt⟩, hkb, ?_, ?_⟩ - · rw [Fin.le_iff_val_le_val, Fin.val_add_one] - split_ifs <;> simp [Nat.succ_le_iff, hkb] + refine ⟨⟨k, hkb.trans b.is_lt⟩, hkb, by fin_omega, ?_⟩ simp [Fin.ext_iff, Fin.val_add, ← hk, Nat.mod_eq_of_lt b.is_lt] lemma pos_of_ne_zero {n : ℕ} {a : Fin (n + 1)} (h : a ≠ 0) : @@ -1489,19 +1510,21 @@ lemma pos_of_ne_zero {n : ℕ} {a : Fin (n + 1)} (h : a ≠ 0) : Nat.pos_of_ne_zero (val_ne_of_ne h) lemma sub_succ_le_sub_of_le {n : ℕ} {u v : Fin (n + 2)} (h : u < v) : v - (u + 1) < v - u := by - have h' : u + 1 ≤ v := add_one_le_of_lt h - apply lt_def.mpr - simp only [sub_val_of_le h', sub_val_of_le (Fin.le_of_lt h)] - refine Nat.sub_lt_sub_left h (lt_def.mp ?_) - exact lt_add_one_iff.mpr (Fin.lt_of_lt_of_le h v.le_last) + fin_omega end AddGroup @[simp] -theorem coe_ofNat_eq_mod (m n : ℕ) [NeZero m] : +theorem coe_natCast_eq_mod (m n : ℕ) [NeZero m] : ((n : Fin m) : ℕ) = n % m := rfl +-- See note [no_index around OfNat.ofNat] +@[simp] +theorem coe_ofNat_eq_mod (m n : ℕ) [NeZero m] : + ((no_index OfNat.ofNat n : Fin m) : ℕ) = OfNat.ofNat n % m := + rfl + section Mul /-! diff --git a/Mathlib/Data/Fin/Tuple/Basic.lean b/Mathlib/Data/Fin/Tuple/Basic.lean index 215b414097e5f..c89677f2b5dae 100644 --- a/Mathlib/Data/Fin/Tuple/Basic.lean +++ b/Mathlib/Data/Fin/Tuple/Basic.lean @@ -93,13 +93,13 @@ example (α : Fin 0 → Sort u) : Unique (∀ i : Fin 0, α i) := by infer_insta theorem tuple0_le {α : Fin 0 → Type*} [∀ i, Preorder (α i)] (f g : ∀ i, α i) : f ≤ g := finZeroElim -variable {α : Fin (n + 1) → Type u} (x : α 0) (q : ∀ i, α i) (p : ∀ i : Fin n, α i.succ) (i : Fin n) +variable {α : Fin (n + 1) → Sort u} (x : α 0) (q : ∀ i, α i) (p : ∀ i : Fin n, α i.succ) (i : Fin n) (y : α i.succ) (z : α 0) /-- The tail of an `n+1` tuple, i.e., its last `n` entries. -/ def tail (q : ∀ i, α i) : ∀ i : Fin n, α i.succ := fun i ↦ q i.succ -theorem tail_def {n : ℕ} {α : Fin (n + 1) → Type*} {q : ∀ i, α i} : +theorem tail_def {n : ℕ} {α : Fin (n + 1) → Sort*} {q : ∀ i, α i} : (tail fun k : Fin (n + 1) ↦ q k) = fun k : Fin n ↦ q k.succ := rfl @@ -117,7 +117,7 @@ theorem cons_succ : cons x p i.succ = p i := by simp [cons] theorem cons_zero : cons x p 0 = x := by simp [cons] @[simp] -theorem cons_one {α : Fin (n + 2) → Type*} (x : α 0) (p : ∀ i : Fin n.succ, α i.succ) : +theorem cons_one {α : Fin (n + 2) → Sort*} (x : α 0) (p : ∀ i : Fin n.succ, α i.succ) : cons x p 1 = p 0 := by rw [← cons_succ x p]; rfl @@ -192,7 +192,7 @@ theorem consCases_cons {P : (∀ i : Fin n.succ, α i) → Sort v} (h : ∀ x₀ /-- Recurse on a tuple by splitting into `Fin.elim0` and `Fin.cons`. -/ @[elab_as_elim] -def consInduction {α : Type*} {P : ∀ {n : ℕ}, (Fin n → α) → Sort v} (h0 : P Fin.elim0) +def consInduction {α : Sort*} {P : ∀ {n : ℕ}, (Fin n → α) → Sort v} (h0 : P Fin.elim0) (h : ∀ {n} (x₀) (x : Fin n → α), P x → P (Fin.cons x₀ x)) : ∀ {n : ℕ} (x : Fin n → α), P x | 0, x => by convert h0 | n + 1, x => consCases (fun x₀ x ↦ h _ _ <| consInduction h0 h _) x @@ -254,7 +254,7 @@ theorem tail_update_succ : tail (update q i.succ y) = update (tail q) i y := by simp [tail] · simp [tail, (Fin.succ_injective n).ne h, h] -theorem comp_cons {α : Type*} {β : Type*} (g : α → β) (y : α) (q : Fin n → α) : +theorem comp_cons {α : Sort*} {β : Sort*} (g : α → β) (y : α) (q : Fin n → α) : g ∘ cons y q = cons (g y) (g ∘ q) := by ext j by_cases h : j = 0 @@ -264,11 +264,15 @@ theorem comp_cons {α : Type*} {β : Type*} (g : α → β) (y : α) (q : Fin n have : j'.succ = j := succ_pred j h rw [← this, cons_succ, comp_apply, comp_apply, cons_succ] -theorem comp_tail {α : Type*} {β : Type*} (g : α → β) (q : Fin n.succ → α) : +theorem comp_tail {α : Sort*} {β : Sort*} (g : α → β) (q : Fin n.succ → α) : g ∘ tail q = tail (g ∘ q) := by ext j simp [tail] +section Preorder + +variable {α : Fin (n + 1) → Type*} + theorem le_cons [∀ i, Preorder (α i)] {x : α 0} {q : ∀ i, α i} {p : ∀ i : Fin n, α i.succ} : q ≤ cons x p ↔ q 0 ≤ x ∧ tail q ≤ p := forall_fin_succ.trans <| and_congr Iff.rfl <| forall_congr' fun j ↦ by simp [tail] @@ -281,33 +285,37 @@ theorem cons_le_cons [∀ i, Preorder (α i)] {x₀ y₀ : α 0} {x y : ∀ i : cons x₀ x ≤ cons y₀ y ↔ x₀ ≤ y₀ ∧ x ≤ y := forall_fin_succ.trans <| and_congr_right' <| by simp only [cons_succ, Pi.le_def] +end Preorder + theorem range_fin_succ {α} (f : Fin (n + 1) → α) : Set.range f = insert (f 0) (Set.range (Fin.tail f)) := Set.ext fun _ ↦ exists_fin_succ.trans <| eq_comm.or Iff.rfl @[simp] -theorem range_cons {α : Type*} {n : ℕ} (x : α) (b : Fin n → α) : +theorem range_cons {α} {n : ℕ} (x : α) (b : Fin n → α) : Set.range (Fin.cons x b : Fin n.succ → α) = insert x (Set.range b) := by rw [range_fin_succ, cons_zero, tail_cons] section Append +variable {α : Sort*} + /-- Append a tuple of length `m` to a tuple of length `n` to get a tuple of length `m + n`. This is a non-dependent version of `Fin.add_cases`. -/ -def append {α : Type*} (a : Fin m → α) (b : Fin n → α) : Fin (m + n) → α := +def append (a : Fin m → α) (b : Fin n → α) : Fin (m + n) → α := @Fin.addCases _ _ (fun _ => α) a b @[simp] -theorem append_left {α : Type*} (u : Fin m → α) (v : Fin n → α) (i : Fin m) : +theorem append_left (u : Fin m → α) (v : Fin n → α) (i : Fin m) : append u v (Fin.castAdd n i) = u i := addCases_left _ @[simp] -theorem append_right {α : Type*} (u : Fin m → α) (v : Fin n → α) (i : Fin n) : +theorem append_right (u : Fin m → α) (v : Fin n → α) (i : Fin n) : append u v (natAdd m i) = v i := addCases_right _ -theorem append_right_nil {α : Type*} (u : Fin m → α) (v : Fin n → α) (hv : n = 0) : +theorem append_right_nil (u : Fin m → α) (v : Fin n → α) (hv : n = 0) : append u v = u ∘ Fin.cast (by rw [hv, Nat.add_zero]) := by refine funext (Fin.addCases (fun l => ?_) fun r => ?_) · rw [append_left, Function.comp_apply] @@ -316,11 +324,11 @@ theorem append_right_nil {α : Type*} (u : Fin m → α) (v : Fin n → α) (hv · exact (Fin.cast hv r).elim0 @[simp] -theorem append_elim0 {α : Type*} (u : Fin m → α) : +theorem append_elim0 (u : Fin m → α) : append u Fin.elim0 = u ∘ Fin.cast (Nat.add_zero _) := append_right_nil _ _ rfl -theorem append_left_nil {α : Type*} (u : Fin m → α) (v : Fin n → α) (hu : m = 0) : +theorem append_left_nil (u : Fin m → α) (v : Fin n → α) (hu : m = 0) : append u v = v ∘ Fin.cast (by rw [hu, Nat.zero_add]) := by refine funext (Fin.addCases (fun l => ?_) fun r => ?_) · exact (Fin.cast hu l).elim0 @@ -329,11 +337,11 @@ theorem append_left_nil {α : Type*} (u : Fin m → α) (v : Fin n → α) (hu : simp [hu] @[simp] -theorem elim0_append {α : Type*} (v : Fin n → α) : +theorem elim0_append (v : Fin n → α) : append Fin.elim0 v = v ∘ Fin.cast (Nat.zero_add _) := append_left_nil _ _ rfl -theorem append_assoc {p : ℕ} {α : Type*} (a : Fin m → α) (b : Fin n → α) (c : Fin p → α) : +theorem append_assoc {p : ℕ} (a : Fin m → α) (b : Fin n → α) (c : Fin p → α) : append (append a b) c = append a (append b c) ∘ Fin.cast (Nat.add_assoc ..) := by ext i rw [Function.comp_apply] @@ -348,7 +356,7 @@ theorem append_assoc {p : ℕ} {α : Type*} (a : Fin m → α) (b : Fin n → α simp [← natAdd_natAdd] /-- Appending a one-tuple to the left is the same as `Fin.cons`. -/ -theorem append_left_eq_cons {α : Type*} {n : ℕ} (x₀ : Fin 1 → α) (x : Fin n → α) : +theorem append_left_eq_cons {n : ℕ} (x₀ : Fin 1 → α) (x : Fin n → α) : Fin.append x₀ x = Fin.cons (x₀ 0) x ∘ Fin.cast (Nat.add_comm ..) := by ext i refine Fin.addCases ?_ ?_ i <;> clear i @@ -360,21 +368,21 @@ theorem append_left_eq_cons {α : Type*} {n : ℕ} (x₀ : Fin 1 → α) (x : Fi exact Fin.cons_succ _ _ _ /-- `Fin.cons` is the same as appending a one-tuple to the left. -/ -theorem cons_eq_append {α : Type*} (x : α) (xs : Fin n → α) : +theorem cons_eq_append (x : α) (xs : Fin n → α) : cons x xs = append (cons x Fin.elim0) xs ∘ Fin.cast (Nat.add_comm ..) := by funext i; simp [append_left_eq_cons] -@[simp] lemma append_cast_left {n m} {α : Type*} (xs : Fin n → α) (ys : Fin m → α) (n' : ℕ) +@[simp] lemma append_cast_left {n m} (xs : Fin n → α) (ys : Fin m → α) (n' : ℕ) (h : n' = n) : Fin.append (xs ∘ Fin.cast h) ys = Fin.append xs ys ∘ (Fin.cast <| by rw [h]) := by subst h; simp -@[simp] lemma append_cast_right {n m} {α : Type*} (xs : Fin n → α) (ys : Fin m → α) (m' : ℕ) +@[simp] lemma append_cast_right {n m} (xs : Fin n → α) (ys : Fin m → α) (m' : ℕ) (h : m' = m) : Fin.append xs (ys ∘ Fin.cast h) = Fin.append xs ys ∘ (Fin.cast <| by rw [h]) := by subst h; simp -lemma append_rev {m n} {α : Type*} (xs : Fin m → α) (ys : Fin n → α) (i : Fin (m + n)) : +lemma append_rev {m n} (xs : Fin m → α) (ys : Fin n → α) (i : Fin (m + n)) : append xs ys (rev i) = append (ys ∘ rev) (xs ∘ rev) (cast (Nat.add_comm ..) i) := by rcases rev_surjective i with ⟨i, rfl⟩ rw [rev_rev] @@ -382,7 +390,7 @@ lemma append_rev {m n} {α : Type*} (xs : Fin m → α) (ys : Fin n → α) (i : · simp [rev_castAdd] · simp [cast_rev, rev_addNat] -lemma append_comp_rev {m n} {α : Type*} (xs : Fin m → α) (ys : Fin n → α) : +lemma append_comp_rev {m n} (xs : Fin m → α) (ys : Fin n → α) : append xs ys ∘ rev = append (ys ∘ rev) (xs ∘ rev) ∘ cast (Nat.add_comm ..) := funext <| append_rev xs ys @@ -390,31 +398,33 @@ end Append section Repeat +variable {α : Sort*} + /-- Repeat `a` `m` times. For example `Fin.repeat 2 ![0, 3, 7] = ![0, 3, 7, 0, 3, 7]`. -/ -- Porting note: removed @[simp] -def «repeat» {α : Type*} (m : ℕ) (a : Fin n → α) : Fin (m * n) → α +def «repeat» (m : ℕ) (a : Fin n → α) : Fin (m * n) → α | i => a i.modNat -- Porting note: added (leanprover/lean4#2042) @[simp] -theorem repeat_apply {α : Type*} (a : Fin n → α) (i : Fin (m * n)) : +theorem repeat_apply (a : Fin n → α) (i : Fin (m * n)) : Fin.repeat m a i = a i.modNat := rfl @[simp] -theorem repeat_zero {α : Type*} (a : Fin n → α) : +theorem repeat_zero (a : Fin n → α) : Fin.repeat 0 a = Fin.elim0 ∘ cast (Nat.zero_mul _) := funext fun x => (cast (Nat.zero_mul _) x).elim0 @[simp] -theorem repeat_one {α : Type*} (a : Fin n → α) : Fin.repeat 1 a = a ∘ cast (Nat.one_mul _) := by +theorem repeat_one (a : Fin n → α) : Fin.repeat 1 a = a ∘ cast (Nat.one_mul _) := by generalize_proofs h apply funext rw [(Fin.rightInverse_cast h.symm).surjective.forall] intro i simp [modNat, Nat.mod_eq_of_lt i.is_lt] -theorem repeat_succ {α : Type*} (a : Fin n → α) (m : ℕ) : +theorem repeat_succ (a : Fin n → α) (m : ℕ) : Fin.repeat m.succ a = append a (Fin.repeat m a) ∘ cast ((Nat.succ_mul _ _).trans (Nat.add_comm ..)) := by generalize_proofs h @@ -425,7 +435,7 @@ theorem repeat_succ {α : Type*} (a : Fin n → α) (m : ℕ) : · simp [modNat] @[simp] -theorem repeat_add {α : Type*} (a : Fin n → α) (m₁ m₂ : ℕ) : Fin.repeat (m₁ + m₂) a = +theorem repeat_add (a : Fin n → α) (m₁ m₂ : ℕ) : Fin.repeat (m₁ + m₂) a = append (Fin.repeat m₁ a) (Fin.repeat m₂ a) ∘ cast (Nat.add_mul ..) := by generalize_proofs h apply funext @@ -434,11 +444,11 @@ theorem repeat_add {α : Type*} (a : Fin n → α) (m₁ m₂ : ℕ) : Fin.repea · simp [modNat, Nat.mod_eq_of_lt l.is_lt] · simp [modNat, Nat.add_mod] -theorem repeat_rev {α : Type*} (a : Fin n → α) (k : Fin (m * n)) : +theorem repeat_rev (a : Fin n → α) (k : Fin (m * n)) : Fin.repeat m a k.rev = Fin.repeat m (a ∘ Fin.rev) k := congr_arg a k.modNat_rev -theorem repeat_comp_rev {α} (a : Fin n → α) : +theorem repeat_comp_rev (a : Fin n → α) : Fin.repeat m a ∘ Fin.rev = Fin.repeat m (a ∘ Fin.rev) := funext <| repeat_rev a @@ -456,14 +466,14 @@ several places. -/ -- Porting note: `i.castSucc` does not work like it did in Lean 3; -- `(castSucc i)` must be used. -variable {α : Fin (n + 1) → Type u} (x : α (last n)) (q : ∀ i, α i) +variable {α : Fin (n + 1) → Sort*} (x : α (last n)) (q : ∀ i, α i) (p : ∀ i : Fin n, α (castSucc i)) (i : Fin n) (y : α (castSucc i)) (z : α (last n)) /-- The beginning of an `n+1` tuple, i.e., its first `n` entries -/ def init (q : ∀ i, α i) (i : Fin n) : α (castSucc i) := q (castSucc i) -theorem init_def {n : ℕ} {α : Fin (n + 1) → Type*} {q : ∀ i, α i} : +theorem init_def {q : ∀ i, α i} : (init fun k : Fin (n + 1) ↦ q k) = fun k : Fin n ↦ q (castSucc k) := rfl @@ -485,21 +495,21 @@ theorem snoc_castSucc : snoc p x (castSucc i) = p i := by convert cast_eq rfl (p i) @[simp] -theorem snoc_comp_castSucc {n : ℕ} {α : Sort _} {a : α} {f : Fin n → α} : +theorem snoc_comp_castSucc {α : Sort*} {a : α} {f : Fin n → α} : (snoc f a : Fin (n + 1) → α) ∘ castSucc = f := funext fun i ↦ by rw [Function.comp_apply, snoc_castSucc] @[simp] theorem snoc_last : snoc p x (last n) = x := by simp [snoc] -lemma snoc_zero {α : Type*} (p : Fin 0 → α) (x : α) : +lemma snoc_zero {α : Sort*} (p : Fin 0 → α) (x : α) : Fin.snoc p x = fun _ ↦ x := by ext y have : Subsingleton (Fin (0 + 1)) := Fin.subsingleton_one simp only [Subsingleton.elim y (Fin.last 0), snoc_last] @[simp] -theorem snoc_comp_nat_add {n m : ℕ} {α : Sort _} (f : Fin (m + n) → α) (a : α) : +theorem snoc_comp_nat_add {n m : ℕ} {α : Sort*} (f : Fin (m + n) → α) (a : α) : (snoc f a : Fin _ → α) ∘ (natAdd m : Fin (n + 1) → Fin (m + n + 1)) = snoc (f ∘ natAdd m) a := by ext i @@ -510,13 +520,13 @@ theorem snoc_comp_nat_add {n m : ℕ} {α : Sort _} (f : Fin (m + n) → α) (a rw [natAdd_castSucc, snoc_castSucc] @[simp] -theorem snoc_cast_add {α : Fin (n + m + 1) → Type*} (f : ∀ i : Fin (n + m), α (castSucc i)) +theorem snoc_cast_add {α : Fin (n + m + 1) → Sort*} (f : ∀ i : Fin (n + m), α (castSucc i)) (a : α (last (n + m))) (i : Fin n) : (snoc f a) (castAdd (m + 1) i) = f (castAdd m i) := dif_pos _ -- Porting note: Had to `unfold comp` @[simp] -theorem snoc_comp_cast_add {n m : ℕ} {α : Sort _} (f : Fin (n + m) → α) (a : α) : +theorem snoc_comp_cast_add {n m : ℕ} {α : Sort*} (f : Fin (n + m) → α) (a : α) : (snoc f a : Fin _ → α) ∘ castAdd (m + 1) = f ∘ castAdd m := funext (by unfold comp; exact snoc_cast_add _ _) @@ -587,14 +597,14 @@ theorem init_update_castSucc : init (update q (castSucc i) y) = update (init q) /-- `tail` and `init` commute. We state this lemma in a non-dependent setting, as otherwise it would involve a cast to convince Lean that the two types are equal, making it harder to use. -/ -theorem tail_init_eq_init_tail {β : Type*} (q : Fin (n + 2) → β) : +theorem tail_init_eq_init_tail {β : Sort*} (q : Fin (n + 2) → β) : tail (init q) = init (tail q) := by ext i simp [tail, init, castSucc_fin_succ] /-- `cons` and `snoc` commute. We state this lemma in a non-dependent setting, as otherwise it would involve a cast to convince Lean that the two types are equal, making it harder to use. -/ -theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) : +theorem cons_snoc_eq_snoc_cons {β : Sort*} (a : β) (q : Fin n → β) (b : β) : @cons n.succ (fun _ ↦ β) a (snoc q b) = snoc (cons a q) b := by ext i by_cases h : i = 0 @@ -612,7 +622,7 @@ theorem cons_snoc_eq_snoc_cons {β : Type*} (a : β) (q : Fin n → β) (b : β) rw [eq_last_of_not_lt h', succ_last] simp -theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) (y : α) : +theorem comp_snoc {α : Sort*} {β : Sort*} (g : α → β) (q : Fin n → α) (y : α) : g ∘ snoc q y = snoc (g ∘ q) (g y) := by ext j by_cases h : j.val < n @@ -621,7 +631,7 @@ theorem comp_snoc {α : Type*} {β : Type*} (g : α → β) (q : Fin n → α) ( simp /-- Appending a one-tuple to the right is the same as `Fin.snoc`. -/ -theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) : +theorem append_right_eq_snoc {α : Sort*} {n : ℕ} (x : Fin n → α) (x₀ : Fin 1 → α) : Fin.append x x₀ = Fin.snoc x (x₀ 0) := by ext i refine Fin.addCases ?_ ?_ i <;> clear i @@ -633,21 +643,21 @@ theorem append_right_eq_snoc {α : Type*} {n : ℕ} (x : Fin n → α) (x₀ : F exact (@snoc_last _ (fun _ => α) _ _).symm /-- `Fin.snoc` is the same as appending a one-tuple -/ -theorem snoc_eq_append {α : Type*} (xs : Fin n → α) (x : α) : +theorem snoc_eq_append {α : Sort*} (xs : Fin n → α) (x : α) : snoc xs x = append xs (cons x Fin.elim0) := (append_right_eq_snoc xs (cons x Fin.elim0)).symm -theorem append_left_snoc {n m} {α : Type*} (xs : Fin n → α) (x : α) (ys : Fin m → α) : +theorem append_left_snoc {n m} {α : Sort*} (xs : Fin n → α) (x : α) (ys : Fin m → α) : Fin.append (Fin.snoc xs x) ys = Fin.append xs (Fin.cons x ys) ∘ Fin.cast (Nat.succ_add_eq_add_succ ..) := by rw [snoc_eq_append, append_assoc, append_left_eq_cons, append_cast_right]; rfl -theorem append_right_cons {n m} {α : Type*} (xs : Fin n → α) (y : α) (ys : Fin m → α) : +theorem append_right_cons {n m} {α : Sort*} (xs : Fin n → α) (y : α) (ys : Fin m → α) : Fin.append xs (Fin.cons y ys) = Fin.append (Fin.snoc xs y) ys ∘ Fin.cast (Nat.succ_add_eq_add_succ ..).symm := by rw [append_left_snoc]; rfl -theorem append_cons {α} (a : α) (as : Fin n → α) (bs : Fin m → α) : +theorem append_cons {α : Sort*} (a : α) (as : Fin n → α) (bs : Fin m → α) : Fin.append (cons a as) bs = cons a (Fin.append as bs) ∘ (Fin.cast <| Nat.add_right_comm n 1 m) := by funext i @@ -661,7 +671,7 @@ theorem append_cons {α} (a : α) (as : Fin n → α) (bs : Fin m → α) : · have : ¬i < n := Nat.not_le.mpr <| Nat.lt_succ.mp <| Nat.not_le.mp h simp [addCases, this] -theorem append_snoc {α} (as : Fin n → α) (bs : Fin m → α) (b : α) : +theorem append_snoc {α : Sort*} (as : Fin n → α) (bs : Fin m → α) (b : α) : Fin.append as (snoc bs b) = snoc (Fin.append as bs) b := by funext i rcases i with ⟨i, isLt⟩ @@ -675,7 +685,7 @@ theorem append_snoc {α} (as : Fin n → α) (bs : Fin m → α) (b : α) : · have := Nat.sub_lt_left_of_lt_add (Nat.not_lt.mp lt_n) lt_add contradiction -theorem comp_init {α : Type*} {β : Type*} (g : α → β) (q : Fin n.succ → α) : +theorem comp_init {α : Sort*} {β : Sort*} (g : α → β) (q : Fin n.succ → α) : g ∘ init q = init (g ∘ q) := by ext j simp [init] @@ -695,7 +705,7 @@ def snocCases {P : (∀ i : Fin n.succ, α i) → Sort*} /-- Recurse on a tuple by splitting into `Fin.elim0` and `Fin.snoc`. -/ @[elab_as_elim] -def snocInduction {α : Type*} +def snocInduction {α : Sort*} {P : ∀ {n : ℕ}, (Fin n → α) → Sort*} (h0 : P Fin.elim0) (h : ∀ {n} (x : Fin n → α) (x₀), P x → P (Fin.snoc x x₀)) : ∀ {n : ℕ} (x : Fin n → α), P x @@ -706,7 +716,7 @@ end TupleRight section InsertNth -variable {α : Fin (n + 1) → Type u} {β : Type v} +variable {α : Fin (n + 1) → Sort*} {β : Sort*} /- Porting note: Lean told me `(fun x x_1 ↦ α x)` was an invalid motive, but disabling automatic insertion and specifying that motive seems to work. -/ @@ -778,13 +788,13 @@ theorem insertNth_apply_succAbove (i : Fin (n + 1)) (x : α i) (p : ∀ j, α (i generalize hk : castPred ((succAbove i) j) H₁ = k rw [castPred_succAbove _ _ hlt] at hk; cases hk intro; rfl - · generalize_proofs H₁ H₂; revert H₂ + · generalize_proofs H₀ H₁ H₂; revert H₂ generalize hk : pred (succAbove i j) H₁ = k - erw [pred_succAbove _ _ (Fin.not_lt.1 hlt)] at hk; cases hk + rw [pred_succAbove _ _ (Fin.not_lt.1 hlt)] at hk; cases hk intro; rfl @[simp] -theorem succAbove_cases_eq_insertNth : @succAboveCases.{u + 1} = @insertNth.{u} := +theorem succAbove_cases_eq_insertNth : @succAboveCases = @insertNth := rfl @[simp] lemma removeNth_insertNth (p : Fin (n + 1)) (a : α p) (f : ∀ i, α (succAbove p i)) : @@ -854,7 +864,7 @@ theorem insertNth_last (x : α (last n)) (p : ∀ j : Fin n, α ((last n).succAb theorem insertNth_last' (x : β) (p : Fin n → β) : @insertNth _ (fun _ ↦ β) (last n) x p = snoc p x := by simp [insertNth_last] -lemma insertNth_rev {α : Type*} (i : Fin (n + 1)) (a : α) (f : Fin n → α) (j : Fin (n + 1)) : +lemma insertNth_rev {α : Sort*} (i : Fin (n + 1)) (a : α) (f : Fin n → α) (j : Fin (n + 1)) : insertNth (α := fun _ ↦ α) i a f (rev j) = insertNth (α := fun _ ↦ α) i.rev a (f ∘ rev) j := by induction j using Fin.succAboveCases · exact rev i @@ -888,8 +898,9 @@ theorem insertNth_binop (op : ∀ j, α j → α j → α j) (i : Fin (n + 1)) ( op j (i.insertNth x p j) (i.insertNth y q j) := insertNth_eq_iff.2 <| by unfold removeNth; simp -section -variable [∀ i, Preorder (α i)] +section Preorder + +variable {α : Fin (n + 1) → Type*} [∀ i, Preorder (α i)] theorem insertNth_le_iff {i : Fin (n + 1)} {x : α i} {p : ∀ j, α (i.succAbove j)} {q : ∀ j, α j} : i.insertNth x p ≤ q ↔ x ≤ q i ∧ p ≤ fun j ↦ q (i.succAbove j) := by @@ -899,7 +910,7 @@ theorem le_insertNth_iff {i : Fin (n + 1)} {x : α i} {p : ∀ j, α (i.succAbov q ≤ i.insertNth x p ↔ q i ≤ x ∧ (fun j ↦ q (i.succAbove j)) ≤ p := by simp [Pi.le_def, forall_iff_succAbove i] -end +end Preorder open Set @@ -915,7 +926,7 @@ lemma insertNth_self_removeNth (p : Fin (n + 1)) (f : ∀ j, α j) : /-- Separates an `n+1`-tuple, returning a selected index and then the rest of the tuple. Functional form of `Equiv.piFinSuccAbove`. -/ @[deprecated removeNth (since := "2024-06-19")] -def extractNth (i : Fin (n + 1)) (f : (∀ j, α j)) : +def extractNth {α : Fin (n + 1) → Type*} (i : Fin (n + 1)) (f : (∀ j, α j)) : α i × ∀ j, α (i.succAbove j) := (f i, removeNth i f) @@ -1029,7 +1040,7 @@ end Find section ContractNth -variable {α : Type*} +variable {α : Sort*} /-- Sends `(g₀, ..., gₙ)` to `(g₀, ..., op gⱼ gⱼ₊₁, ..., gₙ)`. -/ def contractNth (j : Fin (n + 1)) (op : α → α → α) (g : Fin (n + 1) → α) (k : Fin n) : α := diff --git a/Mathlib/Data/Fin/Tuple/Finset.lean b/Mathlib/Data/Fin/Tuple/Finset.lean index 5d845ab373afb..d376279817e25 100644 --- a/Mathlib/Data/Fin/Tuple/Finset.lean +++ b/Mathlib/Data/Fin/Tuple/Finset.lean @@ -3,34 +3,87 @@ 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.Finset.Prod import Mathlib.Data.Fintype.Pi +import Mathlib.Logic.Equiv.Fin /-! # Fin-indexed tuples of finsets -/ -open Fintype +open Fin Fintype namespace Fin -variable {n : ℕ} {α : Fin (n + 1) → Type*} +variable {n : ℕ} {α : Fin (n + 1) → Type*} {f : ∀ i, α i} {s : ∀ i, Finset (α i)} {p : Fin (n + 1)} + +open Fintype + +lemma mem_piFinset_iff_zero_tail : + f ∈ Fintype.piFinset s ↔ f 0 ∈ s 0 ∧ tail f ∈ piFinset (tail s) := by + simp only [Fintype.mem_piFinset, forall_fin_succ, tail] -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_iff_succ, tail] +lemma mem_piFinset_iff_last_init : + f ∈ piFinset s ↔ f (last n) ∈ s (last n) ∧ init f ∈ piFinset (init s) := by + simp only [Fintype.mem_piFinset, forall_fin_succ', init, and_comm] -lemma mem_piFinset_succ' {x : ∀ i, α i} {s : ∀ i, Finset (α i)} : - x ∈ piFinset s ↔ x (last n) ∈ s (last n) ∧ init x ∈ piFinset (init s) := by - simp only [mem_piFinset, forall_iff_castSucc, init] +lemma mem_piFinset_iff_pivot_removeNth (p : Fin (n + 1)) : + f ∈ piFinset s ↔ f p ∈ s p ∧ removeNth p f ∈ piFinset (removeNth p s) := by + simp only [Fintype.mem_piFinset, forall_iff_succAbove p, removeNth] -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] +@[deprecated (since := "2024-09-20")] alias mem_piFinset_succ := mem_piFinset_iff_zero_tail +@[deprecated (since := "2024-09-20")] alias mem_piFinset_succ' := mem_piFinset_iff_last_init -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ₙ ∈ sₙ ∧ x ∈ piFinset s := by - simp_rw [mem_piFinset_succ', init_snoc, snoc_last] +lemma cons_mem_piFinset_cons {x_zero : α 0} {x_tail : (i : Fin n) → α i.succ} + {s_zero : Finset (α 0)} {s_tail : (i : Fin n) → Finset (α i.succ)} : + cons x_zero x_tail ∈ piFinset (cons s_zero s_tail) ↔ + x_zero ∈ s_zero ∧ x_tail ∈ piFinset s_tail := by + simp_rw [mem_piFinset_iff_zero_tail, cons_zero, tail_cons] + +lemma snoc_mem_piFinset_snoc {x_last : α (last n)} {x_init : (i : Fin n) → α i.castSucc} + {s_last : Finset (α (last n))} {s_init : (i : Fin n) → Finset (α i.castSucc)} : + snoc x_init x_last ∈ piFinset (snoc s_init s_last) ↔ + x_last ∈ s_last ∧ x_init ∈ piFinset s_init := by + simp_rw [mem_piFinset_iff_last_init, init_snoc, snoc_last] + +lemma insertNth_mem_piFinset_insertNth {x_pivot : α p} {x_remove : ∀ i, α (succAbove p i)} + {s_pivot : Finset (α p)} {s_remove : ∀ i, Finset (α (succAbove p i))} : + insertNth p x_pivot x_remove ∈ piFinset (insertNth p s_pivot s_remove) ↔ + x_pivot ∈ s_pivot ∧ x_remove ∈ piFinset s_remove := by + simp [mem_piFinset_iff_pivot_removeNth p] end Fin + +namespace Finset +variable {n : ℕ} {α : Fin (n + 1) → Type*} {p : Fin (n + 1)} (S : ∀ i, Finset (α i)) + +lemma map_consEquiv_filter_piFinset (P : (∀ i, α (succ i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| tail r).map (consEquiv α).symm.toEmbedding = + S 0 ×ˢ (piFinset fun x ↦ S <| succ x).filter P := by + unfold tail; ext; simp [Fin.forall_iff_succ, and_assoc] + +lemma map_snocEquiv_filter_piFinset (P : (∀ i, α (castSucc i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| init r).map (snocEquiv α).symm.toEmbedding = + S (last _) ×ˢ (piFinset <| init S).filter P := by + unfold init; ext; simp [Fin.forall_iff_castSucc, and_assoc] + +lemma map_insertNthEquiv_filter_piFinset (P : (∀ i, α (p.succAbove i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| p.removeNth r).map (p.insertNthEquiv α).symm.toEmbedding = + S p ×ˢ (piFinset <| p.removeNth S).filter P := by + unfold removeNth; ext; simp [Fin.forall_iff_succAbove p, and_assoc] + +lemma card_consEquiv_filter_piFinset (P : (∀ i, α (succ i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| tail r).card = + (S 0).card * ((piFinset fun x ↦ S <| succ x).filter P).card := by + rw [← card_product, ← map_consEquiv_filter_piFinset, card_map] + +lemma card_snocEquiv_filter_piFinset (P : (∀ i, α (castSucc i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| init r).card = + (S (last _)).card * ((piFinset <| init S).filter P).card := by + rw [← card_product, ← map_snocEquiv_filter_piFinset, card_map] + +lemma card_insertNthEquiv_filter_piFinset (P : (∀ i, α (p.succAbove i)) → Prop) [DecidablePred P] : + ((piFinset S).filter fun r ↦ P <| p.removeNth r).card = + (S p).card * ((piFinset <| p.removeNth S).filter P).card := by + rw [← card_product, ← map_insertNthEquiv_filter_piFinset, card_map] + +end Finset diff --git a/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean b/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean index 7f72be2b670cb..7f311baa1744c 100644 --- a/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean +++ b/Mathlib/Data/Fin/Tuple/NatAntidiagonal.lean @@ -123,7 +123,7 @@ theorem antidiagonalTuple_one (n : ℕ) : antidiagonalTuple 1 n = [![n]] := by Nat.sub_self, List.bind_append, List.bind_singleton, List.bind_map] conv_rhs => rw [← List.nil_append [![n]]] congr 1 - simp_rw [List.bind_eq_nil, List.mem_range, List.map_eq_nil] + simp_rw [List.bind_eq_nil_iff, List.mem_range, List.map_eq_nil_iff] intro x hx obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt hx rw [add_assoc, add_tsub_cancel_left, antidiagonalTuple_zero_succ] diff --git a/Mathlib/Data/FinEnum.lean b/Mathlib/Data/FinEnum.lean index bfb3c8e6783ba..c2d94fcfa23ad 100644 --- a/Mathlib/Data/FinEnum.lean +++ b/Mathlib/Data/FinEnum.lean @@ -107,41 +107,19 @@ def Finset.enum [DecidableEq α] : List α → List (Finset α) | [] => [∅] | x :: xs => do let r ← Finset.enum xs - [r, {x} ∪ r] + [r, insert x r] @[simp] theorem Finset.mem_enum [DecidableEq α] (s : Finset α) (xs : List α) : s ∈ Finset.enum xs ↔ ∀ x ∈ s, x ∈ xs := by - induction' xs with xs_hd generalizing s <;> simp [*, Finset.enum] - · simp [Finset.eq_empty_iff_forall_not_mem] - · constructor - · rintro ⟨a, h, h'⟩ x hx - cases' h' with _ h' a b - · right - apply h - subst a - exact hx - · simp only [h', mem_union, mem_singleton] at hx ⊢ - cases' hx with hx hx' - · exact Or.inl hx - · exact Or.inr (h _ hx') - · intro h - exists s \ ({xs_hd} : Finset α) - simp only [and_imp, mem_sdiff, mem_singleton] - simp only [or_iff_not_imp_left] at h - exists h - by_cases h : xs_hd ∈ s - · have : {xs_hd} ⊆ s := by - simp only [HasSubset.Subset, *, forall_eq, mem_singleton] - simp only [union_sdiff_of_subset this, or_true, Finset.union_sdiff_of_subset, - eq_self_iff_true] - · left - symm - simp only [sdiff_eq_self] - intro a - simp only [and_imp, mem_inter, mem_singleton] - rintro h₀ rfl - exact (h h₀).elim + induction xs generalizing s with + | nil => simp [enum, eq_empty_iff_forall_not_mem] + | cons x xs ih => + simp only [enum, List.bind_eq_bind, List.mem_bind, List.mem_cons, List.mem_singleton, + List.not_mem_nil, or_false, ih] + refine ⟨by aesop, fun hs => ⟨s.erase x, ?_⟩⟩ + simp only [or_iff_not_imp_left] at hs + simp (config := { contextual := true }) [eq_comm (a := s), or_iff_not_imp_left, hs] instance Finset.finEnum [FinEnum α] : FinEnum (Finset α) := ofList (Finset.enum (toList α)) (by intro; simp) diff --git a/Mathlib/Data/Finmap.lean b/Mathlib/Data/Finmap.lean index 770bb27ffee01..c4d3fe1b9820d 100644 --- a/Mathlib/Data/Finmap.lean +++ b/Mathlib/Data/Finmap.lean @@ -88,7 +88,6 @@ lemma nodup_entries (f : Finmap β) : f.entries.Nodup := f.nodupKeys.nodup /-! ### Lifting from AList -/ /-- Lift a permutation-respecting function on `AList` to `Finmap`. -/ --- @[elab_as_elim] Porting note: we can't add `elab_as_elim` attr in this type def liftOn {γ} (s : Finmap β) (f : AList β → γ) (H : ∀ a b : AList β, a.entries ~ b.entries → f a = f b) : γ := by refine @@ -108,7 +107,6 @@ theorem liftOn_toFinmap {γ} (s : AList β) (f : AList β → γ) (H) : liftOn rfl /-- Lift a permutation-respecting function on 2 `AList`s to 2 `Finmap`s. -/ --- @[elab_as_elim] Porting note: we can't add `elab_as_elim` attr in this type def liftOn₂ {γ} (s₁ s₂ : Finmap β) (f : AList β → AList β → γ) (H : ∀ a₁ b₁ a₂ b₂ : AList β, a₁.entries ~ a₂.entries → b₁.entries ~ b₂.entries → f a₁ b₁ = f a₂ b₂) : γ := diff --git a/Mathlib/Data/Finset/Basic.lean b/Mathlib/Data/Finset/Basic.lean index 86d298bb40842..e86ab424aa5fb 100644 --- a/Mathlib/Data/Finset/Basic.lean +++ b/Mathlib/Data/Finset/Basic.lean @@ -125,7 +125,7 @@ assert_not_exists CompleteLattice assert_not_exists OrderedCommMonoid -open Multiset Subtype Nat Function +open Multiset Subtype Function universe u @@ -807,6 +807,11 @@ theorem ssubset_iff_exists_cons_subset : s ⊂ t ↔ ∃ (a : _) (h : a ∉ s), obtain ⟨a, hs, ht⟩ := not_subset.1 h.2 exact ⟨a, ht, cons_subset.2 ⟨hs, h.subset⟩⟩ +theorem cons_swap (hb : b ∉ s) (ha : a ∉ s.cons b hb) : + (s.cons b hb).cons a ha = (s.cons a fun h ↦ ha (mem_cons.mpr (.inr h))).cons b fun h ↦ + ha (mem_cons.mpr (.inl ((mem_cons.mp h).elim symm (fun h ↦ False.elim (hb h))))) := + eq_of_veq <| Multiset.cons_swap a b s.val + end Cons /-! ### disjoint -/ @@ -1916,7 +1921,7 @@ theorem union_sdiff_self (s t : Finset α) : (s ∪ t) \ t = s \ t := -- TODO: Do we want to delete this lemma and `Finset.disjUnion_singleton`, -- or instead add `Finset.union_singleton`/`Finset.singleton_union`? -theorem sdiff_singleton_eq_erase (a : α) (s : Finset α) : s \ singleton a = erase s a := by +theorem sdiff_singleton_eq_erase (a : α) (s : Finset α) : s \ {a} = erase s a := by ext rw [mem_erase, mem_sdiff, mem_singleton, and_comm] @@ -1972,9 +1977,9 @@ theorem erase_union_of_mem (ha : a ∈ t) (s : Finset α) : s.erase a ∪ t = s theorem union_erase_of_mem (ha : a ∈ s) (t : Finset α) : s ∪ t.erase a = s ∪ t := by rw [← insert_erase (mem_union_left t ha), erase_union_distrib, ← insert_union, insert_erase ha] -@[simp] -theorem sdiff_singleton_eq_self (ha : a ∉ s) : s \ {a} = s := - sdiff_eq_self_iff_disjoint.2 <| by simp [ha] +@[simp, deprecated erase_eq_of_not_mem (since := "2024-10-01")] +theorem sdiff_singleton_eq_self (ha : a ∉ s) : s \ {a} = s := by + rw [← erase_eq, erase_eq_of_not_mem ha] theorem Nontrivial.sdiff_singleton_nonempty {c : α} {s : Finset α} (hS : s.Nontrivial) : (s \ {c}).Nonempty := by @@ -2038,6 +2043,8 @@ theorem disjoint_sdiff_inter (s t : Finset α) : Disjoint (s \ t) (s ∩ t) := theorem sdiff_eq_self_iff_disjoint : s \ t = s ↔ Disjoint s t := sdiff_eq_self_iff_disjoint' +@[deprecated (since := "2024-10-01")] alias sdiff_eq_self := sdiff_eq_self_iff_disjoint + theorem sdiff_eq_self_of_disjoint (h : Disjoint s t) : s \ t = s := sdiff_eq_self_iff_disjoint.2 h @@ -2315,7 +2322,7 @@ theorem filter_singleton (a : α) : filter p {a} = if p a then {a} else ∅ := b split_ifs with h <;> by_cases h' : x = a <;> simp [h, h'] theorem filter_cons_of_pos (a : α) (s : Finset α) (ha : a ∉ s) (hp : p a) : - filter p (cons a s ha) = cons a (filter p s) (mem_filter.not.mpr <| mt And.left ha) := + filter p (cons a s ha) = cons a (filter p s) ((mem_of_mem_filter _).mt ha) := eq_of_veq <| Multiset.filter_cons_of_pos s.val hp theorem filter_cons_of_neg (a : α) (s : Finset α) (ha : a ∉ s) (hp : ¬p a) : @@ -2344,6 +2351,8 @@ theorem disjoint_filter_filter_neg (s t : Finset α) (p : α → Prop) Disjoint (s.filter p) (t.filter fun a => ¬p a) := disjoint_filter_filter' s t disjoint_compl_right +@[deprecated (since := "2024-10-01")] alias filter_inter_filter_neg_eq := disjoint_filter_filter_neg + theorem filter_disj_union (s : Finset α) (t : Finset α) (h : Disjoint s t) : filter p (disjUnion s t h) = (filter p s).disjUnion (filter p t) (disjoint_filter_filter h) := eq_of_veq <| Multiset.filter_add _ _ _ @@ -2357,15 +2366,10 @@ lemma _root_.Set.pairwiseDisjoint_filter [DecidableEq β] (f : α → β) (s : S 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) - (by - split_ifs - · rw [disjoint_singleton_left] - exact mem_filter.not.mpr <| mt And.left ha - · exact disjoint_empty_left _) := by + if p a then cons a (filter p s) ((mem_of_mem_filter _).mt ha) else filter p s := by split_ifs with h - · rw [filter_cons_of_pos _ _ _ ha h, singleton_disjUnion] - · rw [filter_cons_of_neg _ _ _ ha h, empty_disjUnion] + · rw [filter_cons_of_pos _ _ _ ha h] + · rw [filter_cons_of_neg _ _ _ ha h] section variable [DecidableEq α] @@ -2418,9 +2422,6 @@ lemma filter_and_not (s : Finset α) (p q : α → Prop) [DecidablePred p] [Deci theorem sdiff_eq_filter (s₁ s₂ : Finset α) : s₁ \ s₂ = filter (· ∉ s₂) s₁ := ext fun _ => by simp [mem_sdiff, mem_filter] -theorem sdiff_eq_self (s₁ s₂ : Finset α) : s₁ \ s₂ = s₁ ↔ s₁ ∩ s₂ ⊆ ∅ := by - simp [Subset.antisymm_iff, disjoint_iff_inter_eq_empty] - theorem subset_union_elim {s : Finset α} {t₁ t₂ : Set α} (h : ↑s ⊆ t₁ ∪ t₂) : ∃ s₁ s₂ : Finset α, s₁ ∪ s₂ = s ∧ ↑s₁ ⊆ t₁ ∧ ↑s₂ ⊆ t₂ \ t₁ := by classical @@ -2489,10 +2490,6 @@ theorem filter_ne [DecidableEq β] (s : Finset β) (b : β) : theorem filter_ne' [DecidableEq β] (s : Finset β) (b : β) : (s.filter fun a => a ≠ b) = s.erase b := _root_.trans (filter_congr fun _ _ => by simp_rw [@ne_comm _ b]) (filter_ne s b) -theorem filter_inter_filter_neg_eq (s t : Finset α) : - (s.filter p ∩ t.filter fun a => ¬p a) = ∅ := by - simpa using (disjoint_filter_filter_neg s t p).eq_bot - theorem filter_union_filter_of_codisjoint (s : Finset α) (h : Codisjoint p q) : s.filter p ∪ s.filter q = s := (filter_or _ _ _).symm.trans <| filter_true_of_mem fun x _ => h.top_le x trivial @@ -2518,6 +2515,8 @@ end Filter section Range +open Nat + variable {n m l : ℕ} /-- `range n` is the set of natural numbers less than `n`. -/ @@ -2918,6 +2917,11 @@ theorem toList_toFinset [DecidableEq α] (s : Finset α) : s.toList.toFinset = s ext simp +theorem _root_.List.toFinset_toList [DecidableEq α] {s : List α} (hs : s.Nodup) : + s.toFinset.toList.Perm s := by + apply List.perm_of_nodup_nodup_toFinset_eq (nodup_toList _) hs + rw [toList_toFinset] + @[simp] theorem toList_eq_singleton_iff {a : α} {s : Finset α} : s.toList = [a] ↔ s = {a} := by rw [toList, Multiset.toList_eq_singleton_iff, val_eq_singleton_iff] @@ -3094,4 +3098,4 @@ def proveFinsetNonempty {u : Level} {α : Q(Type u)} (s : Q(Finset $α)) : end Mathlib.Meta -set_option linter.style.longFile 3100 +set_option linter.style.longFile 3200 diff --git a/Mathlib/Data/Finset/Card.lean b/Mathlib/Data/Finset/Card.lean index 1ec1dc95a10f2..6cd9aef810c64 100644 --- a/Mathlib/Data/Finset/Card.lean +++ b/Mathlib/Data/Finset/Card.lean @@ -831,6 +831,4 @@ theorem lt_wf {α} : WellFounded (@LT.lt (Finset α) _) := card_lt_card hxy Subrelation.wf H <| InvImage.wf _ <| (Nat.lt_wfRel).2 -@[deprecated (since := "2023-12-27")] alias card_le_of_subset := card_le_card - end Finset diff --git a/Mathlib/Data/Finset/Density.lean b/Mathlib/Data/Finset/Density.lean index 43125f7fcc4f3..002513c40e808 100644 --- a/Mathlib/Data/Finset/Density.lean +++ b/Mathlib/Data/Finset/Density.lean @@ -110,23 +110,23 @@ lemma dens_image [Fintype β] [DecidableEq β] {f : α → β} (hf : Bijective f (s.image f).dens = s.dens := by simpa [map_eq_image, -dens_map_equiv] using dens_map_equiv (.ofBijective f hf) -lemma card_mul_dens (s : Finset α) : Fintype.card α * s.dens = s.card := by +@[simp] lemma card_mul_dens (s : Finset α) : Fintype.card α * s.dens = s.card := by cases isEmpty_or_nonempty α · simp [Subsingleton.elim s ∅] rw [dens, mul_div_cancel₀] exact mod_cast Fintype.card_ne_zero -lemma dens_mul_card (s : Finset α) : s.dens * Fintype.card α = s.card := by +@[simp] lemma dens_mul_card (s : Finset α) : s.dens * Fintype.card α = s.card := by rw [mul_comm, card_mul_dens] section Semifield variable [Semifield 𝕜] [CharZero 𝕜] -lemma natCast_card_mul_nnratCast_dens (s : Finset α) : (Fintype.card α * s.dens : 𝕜) = s.card := - mod_cast s.card_mul_dens +@[simp] lemma natCast_card_mul_nnratCast_dens (s : Finset α) : + (Fintype.card α * s.dens : 𝕜) = s.card := mod_cast s.card_mul_dens -lemma nnratCast_dens_mul_natCast_card (s : Finset α) : s.dens * Fintype.card α = s.card := - mod_cast s.dens_mul_card +@[simp] lemma nnratCast_dens_mul_natCast_card (s : Finset α) : + (s.dens * Fintype.card α : 𝕜) = s.card := mod_cast s.dens_mul_card @[norm_cast] lemma nnratCast_dens (s : Finset α) : (s.dens : 𝕜) = s.card / Fintype.card α := by simp [dens] diff --git a/Mathlib/Data/Finset/Functor.lean b/Mathlib/Data/Finset/Functor.lean index 4319e4a6b1b3a..1359446c44d7e 100644 --- a/Mathlib/Data/Finset/Functor.lean +++ b/Mathlib/Data/Finset/Functor.lean @@ -198,11 +198,16 @@ theorem map_comp_coe (h : α → β) : Functor.map h ∘ Multiset.toFinset = Multiset.toFinset ∘ Functor.map h := funext fun _ => image_toFinset +@[simp] +theorem map_comp_coe_apply (h : α → β) (s : Multiset α) : + s.toFinset.image h = (h <$> s).toFinset := + congrFun (map_comp_coe h) s + theorem map_traverse (g : α → G β) (h : β → γ) (s : Finset α) : Functor.map h <$> traverse g s = traverse (Functor.map h ∘ g) s := by unfold traverse - simp only [map_comp_coe, functor_norm] - rw [LawfulFunctor.comp_map, Multiset.map_traverse] + simp only [Functor.map_map, fmap_def, map_comp_coe_apply, Multiset.fmap_def, ← + Multiset.map_traverse] end Traversable diff --git a/Mathlib/Data/Finset/Image.lean b/Mathlib/Data/Finset/Image.lean index a571c2e8b4f10..88939058da20c 100644 --- a/Mathlib/Data/Finset/Image.lean +++ b/Mathlib/Data/Finset/Image.lean @@ -697,9 +697,23 @@ theorem fin_mono {n} : Monotone (Finset.fin n) := fun s t h x => by simpa using theorem fin_map {n} {s : Finset ℕ} : (s.fin n).map Fin.valEmbedding = s.filter (· < n) := by simp [Finset.fin, Finset.map_map] +/-- +If a finset `t` is a subset of the image of another finset `s` under `f`, then it is equal to the +image of a subset of `s`. + +For the version where `s` is a set, see `subset_set_image_iff`. +-/ +theorem subset_image_iff [DecidableEq β] {s : Finset α} {t : Finset β} {f : α → β} : + t ⊆ s.image f ↔ ∃ s' : Finset α, s' ⊆ s ∧ s'.image f = t := by + refine ⟨fun ht => ?_, fun ⟨s', hs', h⟩ => h ▸ image_subset_image hs'⟩ + refine ⟨s.filter (f · ∈ t), filter_subset _ _, le_antisymm (by simp [image_subset_iff]) ?_⟩ + intro x hx + specialize ht hx + aesop + /-- 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 : α → β} : +theorem subset_set_image_iff [DecidableEq β] {s : Set α} {t : Finset β} {f : α → β} : ↑t ⊆ f '' s ↔ ∃ s' : Finset α, ↑s' ⊆ s ∧ s'.image f = t := by constructor; swap · rintro ⟨t, ht, rfl⟩ @@ -757,9 +771,3 @@ theorem finsetCongr_toEmbedding (e : α ≃ β) : rfl end Equiv - -namespace Finset - -@[deprecated (since := "2023-12-27")] alias image_filter := filter_image - -end Finset diff --git a/Mathlib/Data/Finset/Lattice.lean b/Mathlib/Data/Finset/Lattice.lean index 3efa17777c830..b41a111701bda 100644 --- a/Mathlib/Data/Finset/Lattice.lean +++ b/Mathlib/Data/Finset/Lattice.lean @@ -5,17 +5,22 @@ Authors: Mario Carneiro -/ import Mathlib.Algebra.Order.Monoid.Unbundled.Pow import Mathlib.Data.Finset.Fold -import Mathlib.Data.Finset.Option import Mathlib.Data.Finset.Pi import Mathlib.Data.Finset.Prod import Mathlib.Data.Multiset.Lattice import Mathlib.Data.Set.Lattice import Mathlib.Order.Hom.Lattice -import Mathlib.Order.Minimal import Mathlib.Order.Nat /-! # Lattice operations on finsets + +This file is concerned with folding binary lattice operations over finsets. + +For the special case of maximum and minimum of a finset, see Max.lean. + +See also SetLattice.lean, which is instead concerned with how big lattice or set operations behave +when indexed by a finset. -/ assert_not_exists OrderedCommMonoid @@ -1152,529 +1157,6 @@ theorem exists_mem_eq_inf [OrderTop α] (s : Finset ι) (h : s.Nonempty) (f : ι end LinearOrder -/-! ### max and min of finite sets -/ - - -section MaxMin - -variable [LinearOrder α] - -/-- Let `s` be a finset in a linear order. Then `s.max` is the maximum of `s` if `s` is not empty, -and `⊥` otherwise. It belongs to `WithBot α`. If you want to get an element of `α`, see -`s.max'`. -/ -protected def max (s : Finset α) : WithBot α := - sup s (↑) - -theorem max_eq_sup_coe {s : Finset α} : s.max = s.sup (↑) := - rfl - -theorem max_eq_sup_withBot (s : Finset α) : s.max = sup s (↑) := - rfl - -@[simp] -theorem max_empty : (∅ : Finset α).max = ⊥ := - rfl - -@[simp] -theorem max_insert {a : α} {s : Finset α} : (insert a s).max = max ↑a s.max := - fold_insert_idem - -@[simp] -theorem max_singleton {a : α} : Finset.max {a} = (a : WithBot α) := by - rw [← insert_emptyc_eq] - exact max_insert - -theorem max_of_mem {s : Finset α} {a : α} (h : a ∈ s) : ∃ b : α, s.max = b := by - obtain ⟨b, h, _⟩ := le_sup (α := WithBot α) h _ rfl - exact ⟨b, h⟩ - -theorem max_of_nonempty {s : Finset α} (h : s.Nonempty) : ∃ a : α, s.max = a := - let ⟨_, h⟩ := h - max_of_mem h - -theorem max_eq_bot {s : Finset α} : s.max = ⊥ ↔ s = ∅ := - ⟨fun h ↦ s.eq_empty_or_nonempty.elim id fun H ↦ by - obtain ⟨a, ha⟩ := max_of_nonempty H - rw [h] at ha; cases ha; , -- the `;` is needed since the `cases` syntax allows `cases a, b` - fun h ↦ h.symm ▸ max_empty⟩ - -theorem mem_of_max {s : Finset α} : ∀ {a : α}, s.max = a → a ∈ s := by - induction' s using Finset.induction_on with b s _ ih - · intro _ H; cases H - · intro a h - by_cases p : b = a - · induction p - exact mem_insert_self b s - · cases' max_choice (↑b) s.max with q q <;> rw [max_insert, q] at h - · cases h - cases p rfl - · exact mem_insert_of_mem (ih h) - -theorem le_max {a : α} {s : Finset α} (as : a ∈ s) : ↑a ≤ s.max := - le_sup as - -theorem not_mem_of_max_lt_coe {a : α} {s : Finset α} (h : s.max < a) : a ∉ s := - mt le_max h.not_le - -theorem le_max_of_eq {s : Finset α} {a b : α} (h₁ : a ∈ s) (h₂ : s.max = b) : a ≤ b := - WithBot.coe_le_coe.mp <| (le_max h₁).trans h₂.le - -theorem not_mem_of_max_lt {s : Finset α} {a b : α} (h₁ : b < a) (h₂ : s.max = ↑b) : a ∉ s := - Finset.not_mem_of_max_lt_coe <| h₂.trans_lt <| WithBot.coe_lt_coe.mpr h₁ - -@[gcongr] -theorem max_mono {s t : Finset α} (st : s ⊆ t) : s.max ≤ t.max := - sup_mono st - -protected theorem max_le {M : WithBot α} {s : Finset α} (st : ∀ a ∈ s, (a : WithBot α) ≤ M) : - s.max ≤ M := - Finset.sup_le st - -@[simp] -protected lemma max_le_iff {m : WithBot α} {s : Finset α} : s.max ≤ m ↔ ∀ a ∈ s, a ≤ m := - Finset.sup_le_iff - -@[simp] -protected lemma max_eq_top [OrderTop α] {s : Finset α} : s.max = ⊤ ↔ ⊤ ∈ s := - Finset.sup_eq_top_iff.trans <| by simp - -/-- Let `s` be a finset in a linear order. Then `s.min` is the minimum of `s` if `s` is not empty, -and `⊤` otherwise. It belongs to `WithTop α`. If you want to get an element of `α`, see -`s.min'`. -/ -protected def min (s : Finset α) : WithTop α := - inf s (↑) - -theorem min_eq_inf_withTop (s : Finset α) : s.min = inf s (↑) := - rfl - -@[simp] -theorem min_empty : (∅ : Finset α).min = ⊤ := - rfl - -@[simp] -theorem min_insert {a : α} {s : Finset α} : (insert a s).min = min (↑a) s.min := - fold_insert_idem - -@[simp] -theorem min_singleton {a : α} : Finset.min {a} = (a : WithTop α) := by - rw [← insert_emptyc_eq] - exact min_insert - -theorem min_of_mem {s : Finset α} {a : α} (h : a ∈ s) : ∃ b : α, s.min = b := by - obtain ⟨b, h, _⟩ := inf_le (α := WithTop α) h _ rfl - exact ⟨b, h⟩ - -theorem min_of_nonempty {s : Finset α} (h : s.Nonempty) : ∃ a : α, s.min = a := - let ⟨_, h⟩ := h - min_of_mem h - -@[simp] -theorem min_eq_top {s : Finset α} : s.min = ⊤ ↔ s = ∅ := by - simp [Finset.min, eq_empty_iff_forall_not_mem] - -theorem mem_of_min {s : Finset α} : ∀ {a : α}, s.min = a → a ∈ s := - @mem_of_max αᵒᵈ _ s - -theorem min_le {a : α} {s : Finset α} (as : a ∈ s) : s.min ≤ a := - inf_le as - -theorem not_mem_of_coe_lt_min {a : α} {s : Finset α} (h : ↑a < s.min) : a ∉ s := - mt min_le h.not_le - -theorem min_le_of_eq {s : Finset α} {a b : α} (h₁ : b ∈ s) (h₂ : s.min = a) : a ≤ b := - WithTop.coe_le_coe.mp <| h₂.ge.trans (min_le h₁) - -theorem not_mem_of_lt_min {s : Finset α} {a b : α} (h₁ : a < b) (h₂ : s.min = ↑b) : a ∉ s := - Finset.not_mem_of_coe_lt_min <| (WithTop.coe_lt_coe.mpr h₁).trans_eq h₂.symm - -@[gcongr] -theorem min_mono {s t : Finset α} (st : s ⊆ t) : t.min ≤ s.min := - inf_mono st - -protected theorem le_min {m : WithTop α} {s : Finset α} (st : ∀ a : α, a ∈ s → m ≤ a) : m ≤ s.min := - Finset.le_inf st - -@[simp] -protected theorem le_min_iff {m : WithTop α} {s : Finset α} : m ≤ s.min ↔ ∀ a ∈ s, m ≤ a := - Finset.le_inf_iff - -@[simp] -protected theorem min_eq_bot [OrderBot α] {s : Finset α} : s.min = ⊥ ↔ ⊥ ∈ s := - Finset.max_eq_top (α := αᵒᵈ) - -/-- Given a nonempty finset `s` in a linear order `α`, then `s.min' H` is its minimum, as an -element of `α`, where `H` is a proof of nonemptiness. Without this assumption, use instead `s.min`, -taking values in `WithTop α`. -/ -def min' (s : Finset α) (H : s.Nonempty) : α := - inf' s H id - -/-- Given a nonempty finset `s` in a linear order `α`, then `s.max' H` is its maximum, as an -element of `α`, where `H` is a proof of nonemptiness. Without this assumption, use instead `s.max`, -taking values in `WithBot α`. -/ -def max' (s : Finset α) (H : s.Nonempty) : α := - sup' s H id - -variable (s : Finset α) (H : s.Nonempty) {x : α} - -theorem min'_mem : s.min' H ∈ s := - mem_of_min <| by simp only [Finset.min, min', id_eq, coe_inf']; rfl - -theorem min'_le (x) (H2 : x ∈ s) : s.min' ⟨x, H2⟩ ≤ x := - min_le_of_eq H2 (WithTop.coe_untop _ _).symm - -theorem le_min' (x) (H2 : ∀ y ∈ s, x ≤ y) : x ≤ s.min' H := - H2 _ <| min'_mem _ _ - -theorem isLeast_min' : IsLeast (↑s) (s.min' H) := - ⟨min'_mem _ _, min'_le _⟩ - -@[simp] -theorem le_min'_iff {x} : x ≤ s.min' H ↔ ∀ y ∈ s, x ≤ y := - le_isGLB_iff (isLeast_min' s H).isGLB - -/-- `{a}.min' _` is `a`. -/ -@[simp] -theorem min'_singleton (a : α) : ({a} : Finset α).min' (singleton_nonempty _) = a := by simp [min'] - -theorem max'_mem : s.max' H ∈ s := - mem_of_max <| by simp only [max', Finset.max, id_eq, coe_sup']; rfl - -theorem le_max' (x) (H2 : x ∈ s) : x ≤ s.max' ⟨x, H2⟩ := - le_max_of_eq H2 (WithBot.coe_unbot _ _).symm - -theorem max'_le (x) (H2 : ∀ y ∈ s, y ≤ x) : s.max' H ≤ x := - H2 _ <| max'_mem _ _ - -theorem isGreatest_max' : IsGreatest (↑s) (s.max' H) := - ⟨max'_mem _ _, le_max' _⟩ - -@[simp] -theorem max'_le_iff {x} : s.max' H ≤ x ↔ ∀ y ∈ s, y ≤ x := - isLUB_le_iff (isGreatest_max' s H).isLUB - -@[simp] -theorem max'_lt_iff {x} : s.max' H < x ↔ ∀ y ∈ s, y < x := - ⟨fun Hlt y hy => (s.le_max' y hy).trans_lt Hlt, fun H => H _ <| s.max'_mem _⟩ - -@[simp] -theorem lt_min'_iff : x < s.min' H ↔ ∀ y ∈ s, x < y := - @max'_lt_iff αᵒᵈ _ _ H _ - -theorem max'_eq_sup' : s.max' H = s.sup' H id := rfl - -theorem min'_eq_inf' : s.min' H = s.inf' H id := rfl - -/-- `{a}.max' _` is `a`. -/ -@[simp] -theorem max'_singleton (a : α) : ({a} : Finset α).max' (singleton_nonempty _) = a := by simp [max'] - -theorem min'_lt_max' {i j} (H1 : i ∈ s) (H2 : j ∈ s) (H3 : i ≠ j) : - s.min' ⟨i, H1⟩ < s.max' ⟨i, H1⟩ := - isGLB_lt_isLUB_of_ne (s.isLeast_min' _).isGLB (s.isGreatest_max' _).isLUB H1 H2 H3 - -/-- If there's more than 1 element, the min' is less than the max'. An alternate version of -`min'_lt_max'` which is sometimes more convenient. --/ -theorem min'_lt_max'_of_card (h₂ : 1 < card s) : - s.min' (Finset.card_pos.1 <| by omega) < s.max' (Finset.card_pos.1 <| by omega) := by - rcases one_lt_card.1 h₂ with ⟨a, ha, b, hb, hab⟩ - exact s.min'_lt_max' ha hb hab - -theorem map_ofDual_min (s : Finset αᵒᵈ) : s.min.map ofDual = (s.image ofDual).max := by - rw [max_eq_sup_withBot, sup_image] - exact congr_fun Option.map_id _ - -theorem map_ofDual_max (s : Finset αᵒᵈ) : s.max.map ofDual = (s.image ofDual).min := by - rw [min_eq_inf_withTop, inf_image] - exact congr_fun Option.map_id _ - -theorem map_toDual_min (s : Finset α) : s.min.map toDual = (s.image toDual).max := by - rw [max_eq_sup_withBot, sup_image] - exact congr_fun Option.map_id _ - -theorem map_toDual_max (s : Finset α) : s.max.map toDual = (s.image toDual).min := by - rw [min_eq_inf_withTop, inf_image] - exact congr_fun Option.map_id _ - --- Porting note: new proofs without `convert` for the next four theorems. - -theorem ofDual_min' {s : Finset αᵒᵈ} (hs : s.Nonempty) : - ofDual (min' s hs) = max' (s.image ofDual) (hs.image _) := by - rw [← WithBot.coe_eq_coe] - simp only [min'_eq_inf', id_eq, ofDual_inf', Function.comp_apply, coe_sup', max'_eq_sup', - sup_image] - rfl - -theorem ofDual_max' {s : Finset αᵒᵈ} (hs : s.Nonempty) : - ofDual (max' s hs) = min' (s.image ofDual) (hs.image _) := by - rw [← WithTop.coe_eq_coe] - simp only [max'_eq_sup', id_eq, ofDual_sup', Function.comp_apply, coe_inf', min'_eq_inf', - inf_image] - rfl - -theorem toDual_min' {s : Finset α} (hs : s.Nonempty) : - toDual (min' s hs) = max' (s.image toDual) (hs.image _) := by - rw [← WithBot.coe_eq_coe] - simp only [min'_eq_inf', id_eq, toDual_inf', Function.comp_apply, coe_sup', max'_eq_sup', - sup_image] - rfl - -theorem toDual_max' {s : Finset α} (hs : s.Nonempty) : - toDual (max' s hs) = min' (s.image toDual) (hs.image _) := by - rw [← WithTop.coe_eq_coe] - simp only [max'_eq_sup', id_eq, toDual_sup', Function.comp_apply, coe_inf', min'_eq_inf', - inf_image] - rfl - -theorem max'_subset {s t : Finset α} (H : s.Nonempty) (hst : s ⊆ t) : - s.max' H ≤ t.max' (H.mono hst) := - le_max' _ _ (hst (s.max'_mem H)) - -theorem min'_subset {s t : Finset α} (H : s.Nonempty) (hst : s ⊆ t) : - t.min' (H.mono hst) ≤ s.min' H := - min'_le _ _ (hst (s.min'_mem H)) - -theorem max'_insert (a : α) (s : Finset α) (H : s.Nonempty) : - (insert a s).max' (s.insert_nonempty a) = max (s.max' H) a := - (isGreatest_max' _ _).unique <| by - rw [coe_insert, max_comm] - exact (isGreatest_max' _ _).insert _ - -theorem min'_insert (a : α) (s : Finset α) (H : s.Nonempty) : - (insert a s).min' (s.insert_nonempty a) = min (s.min' H) a := - (isLeast_min' _ _).unique <| by - rw [coe_insert, min_comm] - exact (isLeast_min' _ _).insert _ - -theorem lt_max'_of_mem_erase_max' [DecidableEq α] {a : α} (ha : a ∈ s.erase (s.max' H)) : - a < s.max' H := - lt_of_le_of_ne (le_max' _ _ (mem_of_mem_erase ha)) <| ne_of_mem_of_not_mem ha <| not_mem_erase _ _ - -theorem min'_lt_of_mem_erase_min' [DecidableEq α] {a : α} (ha : a ∈ s.erase (s.min' H)) : - s.min' H < a := - @lt_max'_of_mem_erase_max' αᵒᵈ _ s H _ a ha - -/-- 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' h.of_image) := by - simp only [max', sup'_image] - exact .symm <| comp_sup'_eq_sup'_comp _ _ fun _ _ ↦ hf.map_max - -/-- 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' h.of_image) := by - simp only [min', inf'_image] - exact .symm <| comp_inf'_eq_inf'_comp _ _ fun _ _ ↦ hf.map_min - -/-- 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 - -theorem coe_min' {s : Finset α} (hs : s.Nonempty) : ↑(s.min' hs) = s.min := - coe_inf' hs id - -theorem max_mem_image_coe {s : Finset α} (hs : s.Nonempty) : - s.max ∈ (s.image (↑) : Finset (WithBot α)) := - mem_image.2 ⟨max' s hs, max'_mem _ _, coe_max' hs⟩ - -theorem min_mem_image_coe {s : Finset α} (hs : s.Nonempty) : - s.min ∈ (s.image (↑) : Finset (WithTop α)) := - mem_image.2 ⟨min' s hs, min'_mem _ _, coe_min' hs⟩ - -theorem max_mem_insert_bot_image_coe (s : Finset α) : - s.max ∈ (insert ⊥ (s.image (↑)) : Finset (WithBot α)) := - mem_insert.2 <| s.eq_empty_or_nonempty.imp max_eq_bot.2 max_mem_image_coe - -theorem min_mem_insert_top_image_coe (s : Finset α) : - s.min ∈ (insert ⊤ (s.image (↑)) : Finset (WithTop α)) := - mem_insert.2 <| s.eq_empty_or_nonempty.imp min_eq_top.2 min_mem_image_coe - -theorem max'_erase_ne_self {s : Finset α} (s0 : (s.erase x).Nonempty) : (s.erase x).max' s0 ≠ x := - ne_of_mem_erase (max'_mem _ s0) - -theorem min'_erase_ne_self {s : Finset α} (s0 : (s.erase x).Nonempty) : (s.erase x).min' s0 ≠ x := - ne_of_mem_erase (min'_mem _ s0) - -theorem max_erase_ne_self {s : Finset α} : (s.erase x).max ≠ x := by - by_cases s0 : (s.erase x).Nonempty - · refine ne_of_eq_of_ne (coe_max' s0).symm ?_ - exact WithBot.coe_eq_coe.not.mpr (max'_erase_ne_self _) - · rw [not_nonempty_iff_eq_empty.mp s0, max_empty] - exact WithBot.bot_ne_coe - -theorem min_erase_ne_self {s : Finset α} : (s.erase x).min ≠ x := by - -- Porting note: old proof `convert @max_erase_ne_self αᵒᵈ _ _ _` - convert @max_erase_ne_self αᵒᵈ _ (toDual x) (s.map toDual.toEmbedding) using 1 - apply congr_arg -- Porting note: forces unfolding to see `Finset.min` is `Finset.max` - congr! - ext; simp only [mem_map_equiv]; exact Iff.rfl - -theorem exists_next_right {x : α} {s : Finset α} (h : ∃ y ∈ s, x < y) : - ∃ y ∈ s, x < y ∧ ∀ z ∈ s, x < z → y ≤ z := - have Hne : (s.filter (x < ·)).Nonempty := h.imp fun y hy => mem_filter.2 (by simpa) - have aux := mem_filter.1 (min'_mem _ Hne) - ⟨min' _ Hne, aux.1, by simp, fun z hzs hz => min'_le _ _ <| mem_filter.2 ⟨hzs, by simpa⟩⟩ - -theorem exists_next_left {x : α} {s : Finset α} (h : ∃ y ∈ s, y < x) : - ∃ y ∈ s, y < x ∧ ∀ z ∈ s, z < x → z ≤ y := - @exists_next_right αᵒᵈ _ x s h - -/-- If finsets `s` and `t` are interleaved, then `Finset.card s ≤ Finset.card t + 1`. -/ -theorem card_le_of_interleaved {s t : Finset α} - (h : ∀ᵉ (x ∈ s) (y ∈ s), - x < y → (∀ z ∈ s, z ∉ Set.Ioo x y) → ∃ z ∈ t, x < z ∧ z < y) : - s.card ≤ t.card + 1 := by - replace h : ∀ᵉ (x ∈ s) (y ∈ s), x < y → ∃ z ∈ t, x < z ∧ z < y := by - intro x hx y hy hxy - rcases exists_next_right ⟨y, hy, hxy⟩ with ⟨a, has, hxa, ha⟩ - rcases h x hx a has hxa fun z hzs hz => hz.2.not_le <| ha _ hzs hz.1 with ⟨b, hbt, hxb, hba⟩ - exact ⟨b, hbt, hxb, hba.trans_le <| ha _ hy hxy⟩ - set f : α → WithTop α := fun x => (t.filter fun y => x < y).min - have f_mono : StrictMonoOn f s := by - intro x hx y hy hxy - rcases h x hx y hy hxy with ⟨a, hat, hxa, hay⟩ - calc - f x ≤ a := min_le (mem_filter.2 ⟨hat, by simpa⟩) - _ < f y := - (Finset.lt_inf_iff <| WithTop.coe_lt_top a).2 fun b hb => - WithTop.coe_lt_coe.2 <| hay.trans (by simpa using (mem_filter.1 hb).2) - - calc - s.card = (s.image f).card := (card_image_of_injOn f_mono.injOn).symm - _ ≤ (insert ⊤ (t.image (↑)) : Finset (WithTop α)).card := - card_mono <| image_subset_iff.2 fun x _ => - insert_subset_insert _ (image_subset_image <| filter_subset _ _) - (min_mem_insert_top_image_coe _) - _ ≤ t.card + 1 := (card_insert_le _ _).trans (Nat.add_le_add_right card_image_le _) - -/-- If finsets `s` and `t` are interleaved, then `Finset.card s ≤ Finset.card (t \ s) + 1`. -/ -theorem card_le_diff_of_interleaved {s t : Finset α} - (h : - ∀ᵉ (x ∈ s) (y ∈ s), - x < y → (∀ z ∈ s, z ∉ Set.Ioo x y) → ∃ z ∈ t, x < z ∧ z < y) : - s.card ≤ (t \ s).card + 1 := - card_le_of_interleaved fun x hx y hy hxy hs => - let ⟨z, hzt, hxz, hzy⟩ := h x hx y hy hxy hs - ⟨z, mem_sdiff.2 ⟨hzt, fun hzs => hs z hzs ⟨hxz, hzy⟩⟩, hxz, hzy⟩ - -/-- Induction principle for `Finset`s in a linearly ordered type: a predicate is true on all -`s : Finset α` provided that: - -* it is true on the empty `Finset`, -* for every `s : Finset α` and an element `a` strictly greater than all elements of `s`, `p s` - implies `p (insert a s)`. -/ -@[elab_as_elim] -theorem induction_on_max [DecidableEq α] {p : Finset α → Prop} (s : Finset α) (h0 : p ∅) - (step : ∀ a s, (∀ x ∈ s, x < a) → p s → p (insert a s)) : p s := by - induction' s using Finset.strongInductionOn with s ihs - rcases s.eq_empty_or_nonempty with (rfl | hne) - · exact h0 - · have H : s.max' hne ∈ s := max'_mem s hne - rw [← insert_erase H] - exact step _ _ (fun x => s.lt_max'_of_mem_erase_max' hne) (ihs _ <| erase_ssubset H) - -/-- Induction principle for `Finset`s in a linearly ordered type: a predicate is true on all -`s : Finset α` provided that: - -* it is true on the empty `Finset`, -* for every `s : Finset α` and an element `a` strictly less than all elements of `s`, `p s` - implies `p (insert a s)`. -/ -@[elab_as_elim] -theorem induction_on_min [DecidableEq α] {p : Finset α → Prop} (s : Finset α) (h0 : p ∅) - (step : ∀ a s, (∀ x ∈ s, a < x) → p s → p (insert a s)) : p s := - @induction_on_max αᵒᵈ _ _ _ s h0 step - -end MaxMin - -section MaxMinInductionValue - -variable [LinearOrder α] [LinearOrder β] - -/-- Induction principle for `Finset`s in any type from which a given function `f` maps to a linearly -ordered type : a predicate is true on all `s : Finset α` provided that: - -* it is true on the empty `Finset`, -* for every `s : Finset α` and an element `a` such that for elements of `s` denoted by `x` we have - `f x ≤ f a`, `p s` implies `p (insert a s)`. -/ -@[elab_as_elim] -theorem induction_on_max_value [DecidableEq ι] (f : ι → α) {p : Finset ι → Prop} (s : Finset ι) - (h0 : p ∅) (step : ∀ a s, a ∉ s → (∀ x ∈ s, f x ≤ f a) → p s → p (insert a s)) : p s := by - induction' s using Finset.strongInductionOn with s ihs - rcases (s.image f).eq_empty_or_nonempty with (hne | hne) - · simp only [image_eq_empty] at hne - simp only [hne, h0] - · have H : (s.image f).max' hne ∈ s.image f := max'_mem (s.image f) hne - simp only [mem_image, exists_prop] at H - rcases H with ⟨a, has, hfa⟩ - rw [← insert_erase has] - refine step _ _ (not_mem_erase a s) (fun x hx => ?_) (ihs _ <| erase_ssubset has) - rw [hfa] - exact le_max' _ _ (mem_image_of_mem _ <| mem_of_mem_erase hx) - -/-- Induction principle for `Finset`s in any type from which a given function `f` maps to a linearly -ordered type : a predicate is true on all `s : Finset α` provided that: - -* it is true on the empty `Finset`, -* for every `s : Finset α` and an element `a` such that for elements of `s` denoted by `x` we have - `f a ≤ f x`, `p s` implies `p (insert a s)`. -/ -@[elab_as_elim] -theorem induction_on_min_value [DecidableEq ι] (f : ι → α) {p : Finset ι → Prop} (s : Finset ι) - (h0 : p ∅) (step : ∀ a s, a ∉ s → (∀ x ∈ s, f a ≤ f x) → p s → p (insert a s)) : p s := - @induction_on_max_value αᵒᵈ ι _ _ _ _ s h0 step - -end MaxMinInductionValue - -section ExistsMaxMin - -variable [LinearOrder α] - -theorem exists_max_image (s : Finset β) (f : β → α) (h : s.Nonempty) : - ∃ x ∈ s, ∀ x' ∈ s, f x' ≤ f x := by - cases' max_of_nonempty (h.image f) with y hy - rcases mem_image.mp (mem_of_max hy) with ⟨x, hx, rfl⟩ - exact ⟨x, hx, fun x' hx' => le_max_of_eq (mem_image_of_mem f hx') hy⟩ - -theorem exists_min_image (s : Finset β) (f : β → α) (h : s.Nonempty) : - ∃ x ∈ s, ∀ x' ∈ s, f x ≤ f x' := - @exists_max_image αᵒᵈ β _ s f h - -end ExistsMaxMin - -theorem isGLB_iff_isLeast [LinearOrder α] (i : α) (s : Finset α) (hs : s.Nonempty) : - IsGLB (s : Set α) i ↔ IsLeast (↑s) i := by - refine ⟨fun his => ?_, IsLeast.isGLB⟩ - suffices i = min' s hs by - rw [this] - exact isLeast_min' s hs - rw [IsGLB, IsGreatest, mem_lowerBounds, mem_upperBounds] at his - exact le_antisymm (his.1 (Finset.min' s hs) (Finset.min'_mem s hs)) (his.2 _ (Finset.min'_le s)) - -theorem isLUB_iff_isGreatest [LinearOrder α] (i : α) (s : Finset α) (hs : s.Nonempty) : - IsLUB (s : Set α) i ↔ IsGreatest (↑s) i := - @isGLB_iff_isLeast αᵒᵈ _ i s hs - -theorem isGLB_mem [LinearOrder α] {i : α} (s : Finset α) (his : IsGLB (s : Set α) i) - (hs : s.Nonempty) : i ∈ s := by - rw [← mem_coe] - exact ((isGLB_iff_isLeast i s hs).mp his).1 - -theorem isLUB_mem [LinearOrder α] {i : α} (s : Finset α) (his : IsLUB (s : Set α) i) - (hs : s.Nonempty) : i ∈ s := - @isGLB_mem αᵒᵈ _ i s his hs - end Finset namespace Multiset @@ -1723,230 +1205,3 @@ theorem sup_singleton' [DecidableEq α] (s : Finset α) : s.sup singleton = s := (s.sup_singleton'' _).trans image_id end Finset - -section Lattice - -variable {ι' : Sort*} [CompleteLattice α] - -/-- Supremum of `s i`, `i : ι`, is equal to the supremum over `t : Finset ι` of suprema -`⨆ i ∈ t, s i`. This version assumes `ι` is a `Type*`. See `iSup_eq_iSup_finset'` for a version -that works for `ι : Sort*`. -/ -theorem iSup_eq_iSup_finset (s : ι → α) : ⨆ i, s i = ⨆ t : Finset ι, ⨆ i ∈ t, s i := by - classical - refine le_antisymm ?_ ?_ - · exact iSup_le fun b => le_iSup_of_le {b} <| le_iSup_of_le b <| le_iSup_of_le (by simp) <| le_rfl - · exact iSup_le fun t => iSup_le fun b => iSup_le fun _ => le_iSup _ _ - -/-- Supremum of `s i`, `i : ι`, is equal to the supremum over `t : Finset ι` of suprema -`⨆ i ∈ t, s i`. This version works for `ι : Sort*`. See `iSup_eq_iSup_finset` for a version -that assumes `ι : Type*` but has no `PLift`s. -/ -theorem iSup_eq_iSup_finset' (s : ι' → α) : - ⨆ i, s i = ⨆ t : Finset (PLift ι'), ⨆ i ∈ t, s (PLift.down i) := by - rw [← iSup_eq_iSup_finset, ← Equiv.plift.surjective.iSup_comp]; rfl - -/-- Infimum of `s i`, `i : ι`, is equal to the infimum over `t : Finset ι` of infima -`⨅ i ∈ t, s i`. This version assumes `ι` is a `Type*`. See `iInf_eq_iInf_finset'` for a version -that works for `ι : Sort*`. -/ -theorem iInf_eq_iInf_finset (s : ι → α) : ⨅ i, s i = ⨅ (t : Finset ι) (i ∈ t), s i := - @iSup_eq_iSup_finset αᵒᵈ _ _ _ - -/-- Infimum of `s i`, `i : ι`, is equal to the infimum over `t : Finset ι` of infima -`⨅ i ∈ t, s i`. This version works for `ι : Sort*`. See `iInf_eq_iInf_finset` for a version -that assumes `ι : Type*` but has no `PLift`s. -/ -theorem iInf_eq_iInf_finset' (s : ι' → α) : - ⨅ i, s i = ⨅ t : Finset (PLift ι'), ⨅ i ∈ t, s (PLift.down i) := - @iSup_eq_iSup_finset' αᵒᵈ _ _ _ - -end Lattice - -namespace Set - -variable {ι' : Sort*} - -/-- Union of an indexed family of sets `s : ι → Set α` is equal to the union of the unions -of finite subfamilies. This version assumes `ι : Type*`. See also `iUnion_eq_iUnion_finset'` for -a version that works for `ι : Sort*`. -/ -theorem iUnion_eq_iUnion_finset (s : ι → Set α) : ⋃ i, s i = ⋃ t : Finset ι, ⋃ i ∈ t, s i := - iSup_eq_iSup_finset s - -/-- Union of an indexed family of sets `s : ι → Set α` is equal to the union of the unions -of finite subfamilies. This version works for `ι : Sort*`. See also `iUnion_eq_iUnion_finset` for -a version that assumes `ι : Type*` but avoids `PLift`s in the right hand side. -/ -theorem iUnion_eq_iUnion_finset' (s : ι' → Set α) : - ⋃ i, s i = ⋃ t : Finset (PLift ι'), ⋃ i ∈ t, s (PLift.down i) := - iSup_eq_iSup_finset' s - -/-- Intersection of an indexed family of sets `s : ι → Set α` is equal to the intersection of the -intersections of finite subfamilies. This version assumes `ι : Type*`. See also -`iInter_eq_iInter_finset'` for a version that works for `ι : Sort*`. -/ -theorem iInter_eq_iInter_finset (s : ι → Set α) : ⋂ i, s i = ⋂ t : Finset ι, ⋂ i ∈ t, s i := - iInf_eq_iInf_finset s - -/-- Intersection of an indexed family of sets `s : ι → Set α` is equal to the intersection of the -intersections of finite subfamilies. This version works for `ι : Sort*`. See also -`iInter_eq_iInter_finset` for a version that assumes `ι : Type*` but avoids `PLift`s in the right -hand side. -/ -theorem iInter_eq_iInter_finset' (s : ι' → Set α) : - ⋂ i, s i = ⋂ t : Finset (PLift ι'), ⋂ i ∈ t, s (PLift.down i) := - iInf_eq_iInf_finset' s - -end Set - -namespace Finset - -section minimal - -variable [DecidableEq α] {P : Finset α → Prop} {s : Finset α} - -theorem maximal_iff_forall_insert (hP : ∀ ⦃s t⦄, P t → s ⊆ t → P s) : - Maximal P s ↔ P s ∧ ∀ x ∉ s, ¬ P (insert x s) := by - simp only [Maximal, and_congr_right_iff] - exact fun _ ↦ ⟨fun h x hxs hx ↦ hxs <| h hx (subset_insert _ _) (mem_insert_self x s), - fun h t ht hst x hxt ↦ by_contra fun hxs ↦ h x hxs (hP ht (insert_subset hxt hst))⟩ - -theorem minimal_iff_forall_diff_singleton (hP : ∀ ⦃s t⦄, P t → t ⊆ s → P s) : - Minimal P s ↔ P s ∧ ∀ x ∈ s, ¬ P (s.erase x) where - mp h := ⟨h.prop, fun x hxs hx ↦ by simpa using h.le_of_le hx (erase_subset _ _) hxs⟩ - mpr h := ⟨h.1, fun t ht hts x hxs ↦ by_contra fun hxt ↦ - h.2 x hxs <| hP ht (subset_erase.2 ⟨hts, hxt⟩)⟩ - -end minimal - -/-! ### Interaction with big lattice/set operations -/ - -section Lattice - -theorem iSup_coe [SupSet β] (f : α → β) (s : Finset α) : ⨆ x ∈ (↑s : Set α), f x = ⨆ x ∈ s, f x := - rfl - -theorem iInf_coe [InfSet β] (f : α → β) (s : Finset α) : ⨅ x ∈ (↑s : Set α), f x = ⨅ x ∈ s, f x := - rfl - -variable [CompleteLattice β] - -theorem iSup_singleton (a : α) (s : α → β) : ⨆ x ∈ ({a} : Finset α), s x = s a := by simp - -theorem iInf_singleton (a : α) (s : α → β) : ⨅ x ∈ ({a} : Finset α), s x = s a := by simp - -theorem iSup_option_toFinset (o : Option α) (f : α → β) : ⨆ x ∈ o.toFinset, f x = ⨆ x ∈ o, f x := by - simp - -theorem iInf_option_toFinset (o : Option α) (f : α → β) : ⨅ x ∈ o.toFinset, f x = ⨅ x ∈ o, f x := - @iSup_option_toFinset _ βᵒᵈ _ _ _ - -variable [DecidableEq α] - -theorem iSup_union {f : α → β} {s t : Finset α} : - ⨆ x ∈ s ∪ t, f x = (⨆ x ∈ s, f x) ⊔ ⨆ x ∈ t, f x := by simp [iSup_or, iSup_sup_eq] - -theorem iInf_union {f : α → β} {s t : Finset α} : - ⨅ x ∈ s ∪ t, f x = (⨅ x ∈ s, f x) ⊓ ⨅ x ∈ t, f x := - @iSup_union α βᵒᵈ _ _ _ _ _ - -theorem iSup_insert (a : α) (s : Finset α) (t : α → β) : - ⨆ x ∈ insert a s, t x = t a ⊔ ⨆ x ∈ s, t x := by - rw [insert_eq] - simp only [iSup_union, Finset.iSup_singleton] - -theorem iInf_insert (a : α) (s : Finset α) (t : α → β) : - ⨅ x ∈ insert a s, t x = t a ⊓ ⨅ x ∈ s, t x := - @iSup_insert α βᵒᵈ _ _ _ _ _ - -theorem iSup_finset_image {f : γ → α} {g : α → β} {s : Finset γ} : - ⨆ x ∈ s.image f, g x = ⨆ y ∈ s, g (f y) := by rw [← iSup_coe, coe_image, iSup_image, iSup_coe] - -theorem iInf_finset_image {f : γ → α} {g : α → β} {s : Finset γ} : - ⨅ x ∈ s.image f, g x = ⨅ y ∈ s, g (f y) := by rw [← iInf_coe, coe_image, iInf_image, iInf_coe] - -theorem iSup_insert_update {x : α} {t : Finset α} (f : α → β) {s : β} (hx : x ∉ t) : - ⨆ i ∈ insert x t, Function.update f x s i = s ⊔ ⨆ i ∈ t, f i := by - simp only [Finset.iSup_insert, update_same] - rcongr (i hi); apply update_noteq; rintro rfl; exact hx hi - -theorem iInf_insert_update {x : α} {t : Finset α} (f : α → β) {s : β} (hx : x ∉ t) : - ⨅ i ∈ insert x t, update f x s i = s ⊓ ⨅ i ∈ t, f i := - @iSup_insert_update α βᵒᵈ _ _ _ _ f _ hx - -theorem iSup_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → β) : - ⨆ y ∈ s.biUnion t, f y = ⨆ (x ∈ s) (y ∈ t x), f y := by simp [@iSup_comm _ α, iSup_and] - -theorem iInf_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → β) : - ⨅ y ∈ s.biUnion t, f y = ⨅ (x ∈ s) (y ∈ t x), f y := - @iSup_biUnion _ βᵒᵈ _ _ _ _ _ _ - -end Lattice - -theorem set_biUnion_coe (s : Finset α) (t : α → Set β) : ⋃ x ∈ (↑s : Set α), t x = ⋃ x ∈ s, t x := - rfl - -theorem set_biInter_coe (s : Finset α) (t : α → Set β) : ⋂ x ∈ (↑s : Set α), t x = ⋂ x ∈ s, t x := - rfl - -theorem set_biUnion_singleton (a : α) (s : α → Set β) : ⋃ x ∈ ({a} : Finset α), s x = s a := - iSup_singleton a s - -theorem set_biInter_singleton (a : α) (s : α → Set β) : ⋂ x ∈ ({a} : Finset α), s x = s a := - iInf_singleton a s - -@[simp] -theorem set_biUnion_preimage_singleton (f : α → β) (s : Finset β) : - ⋃ y ∈ s, f ⁻¹' {y} = f ⁻¹' s := - Set.biUnion_preimage_singleton f s - -theorem set_biUnion_option_toFinset (o : Option α) (f : α → Set β) : - ⋃ x ∈ o.toFinset, f x = ⋃ x ∈ o, f x := - iSup_option_toFinset o f - -theorem set_biInter_option_toFinset (o : Option α) (f : α → Set β) : - ⋂ x ∈ o.toFinset, f x = ⋂ x ∈ o, f x := - iInf_option_toFinset o f - -theorem subset_set_biUnion_of_mem {s : Finset α} {f : α → Set β} {x : α} (h : x ∈ s) : - f x ⊆ ⋃ y ∈ s, f y := - show f x ≤ ⨆ y ∈ s, f y from le_iSup_of_le x <| by simp only [h, iSup_pos, le_refl] - -variable [DecidableEq α] - -theorem set_biUnion_union (s t : Finset α) (u : α → Set β) : - ⋃ x ∈ s ∪ t, u x = (⋃ x ∈ s, u x) ∪ ⋃ x ∈ t, u x := - iSup_union - -theorem set_biInter_inter (s t : Finset α) (u : α → Set β) : - ⋂ x ∈ s ∪ t, u x = (⋂ x ∈ s, u x) ∩ ⋂ x ∈ t, u x := - iInf_union - -theorem set_biUnion_insert (a : α) (s : Finset α) (t : α → Set β) : - ⋃ x ∈ insert a s, t x = t a ∪ ⋃ x ∈ s, t x := - iSup_insert a s t - -theorem set_biInter_insert (a : α) (s : Finset α) (t : α → Set β) : - ⋂ x ∈ insert a s, t x = t a ∩ ⋂ x ∈ s, t x := - iInf_insert a s t - -theorem set_biUnion_finset_image {f : γ → α} {g : α → Set β} {s : Finset γ} : - ⋃ x ∈ s.image f, g x = ⋃ y ∈ s, g (f y) := - iSup_finset_image - -theorem set_biInter_finset_image {f : γ → α} {g : α → Set β} {s : Finset γ} : - ⋂ x ∈ s.image f, g x = ⋂ y ∈ s, g (f y) := - iInf_finset_image - -theorem set_biUnion_insert_update {x : α} {t : Finset α} (f : α → Set β) {s : Set β} (hx : x ∉ t) : - ⋃ i ∈ insert x t, @update _ _ _ f x s i = s ∪ ⋃ i ∈ t, f i := - iSup_insert_update f hx - -theorem set_biInter_insert_update {x : α} {t : Finset α} (f : α → Set β) {s : Set β} (hx : x ∉ t) : - ⋂ i ∈ insert x t, @update _ _ _ f x s i = s ∩ ⋂ i ∈ t, f i := - iInf_insert_update f hx - -theorem set_biUnion_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → Set β) : - ⋃ y ∈ s.biUnion t, f y = ⋃ (x ∈ s) (y ∈ t x), f y := - iSup_biUnion s t f - -theorem set_biInter_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → Set β) : - ⋂ y ∈ s.biUnion t, f y = ⋂ (x ∈ s) (y ∈ t x), f y := - iInf_biUnion s t f - -end Finset - -set_option linter.style.longFile 2100 diff --git a/Mathlib/Data/Finset/Max.lean b/Mathlib/Data/Finset/Max.lean new file mode 100644 index 0000000000000..a972df5dc3ddc --- /dev/null +++ b/Mathlib/Data/Finset/Max.lean @@ -0,0 +1,543 @@ +/- +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.Finset.Lattice + +/-! +# Maximum and minimum of finite sets +-/ + +assert_not_exists OrderedCommMonoid +assert_not_exists MonoidWithZero + +open Function Multiset OrderDual + +variable {F α β γ ι κ : Type*} + +namespace Finset + +/-! ### max and min of finite sets -/ + +section MaxMin + +variable [LinearOrder α] + +/-- Let `s` be a finset in a linear order. Then `s.max` is the maximum of `s` if `s` is not empty, +and `⊥` otherwise. It belongs to `WithBot α`. If you want to get an element of `α`, see +`s.max'`. -/ +protected def max (s : Finset α) : WithBot α := + sup s (↑) + +theorem max_eq_sup_coe {s : Finset α} : s.max = s.sup (↑) := + rfl + +theorem max_eq_sup_withBot (s : Finset α) : s.max = sup s (↑) := + rfl + +@[simp] +theorem max_empty : (∅ : Finset α).max = ⊥ := + rfl + +@[simp] +theorem max_insert {a : α} {s : Finset α} : (insert a s).max = max ↑a s.max := + fold_insert_idem + +@[simp] +theorem max_singleton {a : α} : Finset.max {a} = (a : WithBot α) := by + rw [← insert_emptyc_eq] + exact max_insert + +theorem max_of_mem {s : Finset α} {a : α} (h : a ∈ s) : ∃ b : α, s.max = b := by + obtain ⟨b, h, _⟩ := le_sup (α := WithBot α) h _ rfl + exact ⟨b, h⟩ + +theorem max_of_nonempty {s : Finset α} (h : s.Nonempty) : ∃ a : α, s.max = a := + let ⟨_, h⟩ := h + max_of_mem h + +theorem max_eq_bot {s : Finset α} : s.max = ⊥ ↔ s = ∅ := + ⟨fun h ↦ s.eq_empty_or_nonempty.elim id fun H ↦ by + obtain ⟨a, ha⟩ := max_of_nonempty H + rw [h] at ha; cases ha; , -- the `;` is needed since the `cases` syntax allows `cases a, b` + fun h ↦ h.symm ▸ max_empty⟩ + +theorem mem_of_max {s : Finset α} : ∀ {a : α}, s.max = a → a ∈ s := by + induction' s using Finset.induction_on with b s _ ih + · intro _ H; cases H + · intro a h + by_cases p : b = a + · induction p + exact mem_insert_self b s + · cases' max_choice (↑b) s.max with q q <;> rw [max_insert, q] at h + · cases h + cases p rfl + · exact mem_insert_of_mem (ih h) + +theorem le_max {a : α} {s : Finset α} (as : a ∈ s) : ↑a ≤ s.max := + le_sup as + +theorem not_mem_of_max_lt_coe {a : α} {s : Finset α} (h : s.max < a) : a ∉ s := + mt le_max h.not_le + +theorem le_max_of_eq {s : Finset α} {a b : α} (h₁ : a ∈ s) (h₂ : s.max = b) : a ≤ b := + WithBot.coe_le_coe.mp <| (le_max h₁).trans h₂.le + +theorem not_mem_of_max_lt {s : Finset α} {a b : α} (h₁ : b < a) (h₂ : s.max = ↑b) : a ∉ s := + Finset.not_mem_of_max_lt_coe <| h₂.trans_lt <| WithBot.coe_lt_coe.mpr h₁ + +@[gcongr] +theorem max_mono {s t : Finset α} (st : s ⊆ t) : s.max ≤ t.max := + sup_mono st + +protected theorem max_le {M : WithBot α} {s : Finset α} (st : ∀ a ∈ s, (a : WithBot α) ≤ M) : + s.max ≤ M := + Finset.sup_le st + +@[simp] +protected lemma max_le_iff {m : WithBot α} {s : Finset α} : s.max ≤ m ↔ ∀ a ∈ s, a ≤ m := + Finset.sup_le_iff + +@[simp] +protected lemma max_eq_top [OrderTop α] {s : Finset α} : s.max = ⊤ ↔ ⊤ ∈ s := + Finset.sup_eq_top_iff.trans <| by simp + +/-- Let `s` be a finset in a linear order. Then `s.min` is the minimum of `s` if `s` is not empty, +and `⊤` otherwise. It belongs to `WithTop α`. If you want to get an element of `α`, see +`s.min'`. -/ +protected def min (s : Finset α) : WithTop α := + inf s (↑) + +theorem min_eq_inf_withTop (s : Finset α) : s.min = inf s (↑) := + rfl + +@[simp] +theorem min_empty : (∅ : Finset α).min = ⊤ := + rfl + +@[simp] +theorem min_insert {a : α} {s : Finset α} : (insert a s).min = min (↑a) s.min := + fold_insert_idem + +@[simp] +theorem min_singleton {a : α} : Finset.min {a} = (a : WithTop α) := by + rw [← insert_emptyc_eq] + exact min_insert + +theorem min_of_mem {s : Finset α} {a : α} (h : a ∈ s) : ∃ b : α, s.min = b := by + obtain ⟨b, h, _⟩ := inf_le (α := WithTop α) h _ rfl + exact ⟨b, h⟩ + +theorem min_of_nonempty {s : Finset α} (h : s.Nonempty) : ∃ a : α, s.min = a := + let ⟨_, h⟩ := h + min_of_mem h + +@[simp] +theorem min_eq_top {s : Finset α} : s.min = ⊤ ↔ s = ∅ := by + simp [Finset.min, eq_empty_iff_forall_not_mem] + +theorem mem_of_min {s : Finset α} : ∀ {a : α}, s.min = a → a ∈ s := + @mem_of_max αᵒᵈ _ s + +theorem min_le {a : α} {s : Finset α} (as : a ∈ s) : s.min ≤ a := + inf_le as + +theorem not_mem_of_coe_lt_min {a : α} {s : Finset α} (h : ↑a < s.min) : a ∉ s := + mt min_le h.not_le + +theorem min_le_of_eq {s : Finset α} {a b : α} (h₁ : b ∈ s) (h₂ : s.min = a) : a ≤ b := + WithTop.coe_le_coe.mp <| h₂.ge.trans (min_le h₁) + +theorem not_mem_of_lt_min {s : Finset α} {a b : α} (h₁ : a < b) (h₂ : s.min = ↑b) : a ∉ s := + Finset.not_mem_of_coe_lt_min <| (WithTop.coe_lt_coe.mpr h₁).trans_eq h₂.symm + +@[gcongr] +theorem min_mono {s t : Finset α} (st : s ⊆ t) : t.min ≤ s.min := + inf_mono st + +protected theorem le_min {m : WithTop α} {s : Finset α} (st : ∀ a : α, a ∈ s → m ≤ a) : m ≤ s.min := + Finset.le_inf st + +@[simp] +protected theorem le_min_iff {m : WithTop α} {s : Finset α} : m ≤ s.min ↔ ∀ a ∈ s, m ≤ a := + Finset.le_inf_iff + +@[simp] +protected theorem min_eq_bot [OrderBot α] {s : Finset α} : s.min = ⊥ ↔ ⊥ ∈ s := + Finset.max_eq_top (α := αᵒᵈ) + +/-- Given a nonempty finset `s` in a linear order `α`, then `s.min' H` is its minimum, as an +element of `α`, where `H` is a proof of nonemptiness. Without this assumption, use instead `s.min`, +taking values in `WithTop α`. -/ +def min' (s : Finset α) (H : s.Nonempty) : α := + inf' s H id + +/-- Given a nonempty finset `s` in a linear order `α`, then `s.max' H` is its maximum, as an +element of `α`, where `H` is a proof of nonemptiness. Without this assumption, use instead `s.max`, +taking values in `WithBot α`. -/ +def max' (s : Finset α) (H : s.Nonempty) : α := + sup' s H id + +variable (s : Finset α) (H : s.Nonempty) {x : α} + +theorem min'_mem : s.min' H ∈ s := + mem_of_min <| by simp only [Finset.min, min', id_eq, coe_inf']; rfl + +theorem min'_le (x) (H2 : x ∈ s) : s.min' ⟨x, H2⟩ ≤ x := + min_le_of_eq H2 (WithTop.coe_untop _ _).symm + +theorem le_min' (x) (H2 : ∀ y ∈ s, x ≤ y) : x ≤ s.min' H := + H2 _ <| min'_mem _ _ + +theorem isLeast_min' : IsLeast (↑s) (s.min' H) := + ⟨min'_mem _ _, min'_le _⟩ + +@[simp] +theorem le_min'_iff {x} : x ≤ s.min' H ↔ ∀ y ∈ s, x ≤ y := + le_isGLB_iff (isLeast_min' s H).isGLB + +/-- `{a}.min' _` is `a`. -/ +@[simp] +theorem min'_singleton (a : α) : ({a} : Finset α).min' (singleton_nonempty _) = a := by simp [min'] + +theorem max'_mem : s.max' H ∈ s := + mem_of_max <| by simp only [max', Finset.max, id_eq, coe_sup']; rfl + +theorem le_max' (x) (H2 : x ∈ s) : x ≤ s.max' ⟨x, H2⟩ := + le_max_of_eq H2 (WithBot.coe_unbot _ _).symm + +theorem max'_le (x) (H2 : ∀ y ∈ s, y ≤ x) : s.max' H ≤ x := + H2 _ <| max'_mem _ _ + +theorem isGreatest_max' : IsGreatest (↑s) (s.max' H) := + ⟨max'_mem _ _, le_max' _⟩ + +@[simp] +theorem max'_le_iff {x} : s.max' H ≤ x ↔ ∀ y ∈ s, y ≤ x := + isLUB_le_iff (isGreatest_max' s H).isLUB + +@[simp] +theorem max'_lt_iff {x} : s.max' H < x ↔ ∀ y ∈ s, y < x := + ⟨fun Hlt y hy => (s.le_max' y hy).trans_lt Hlt, fun H => H _ <| s.max'_mem _⟩ + +@[simp] +theorem lt_min'_iff : x < s.min' H ↔ ∀ y ∈ s, x < y := + @max'_lt_iff αᵒᵈ _ _ H _ + +theorem max'_eq_sup' : s.max' H = s.sup' H id := rfl + +theorem min'_eq_inf' : s.min' H = s.inf' H id := rfl + +/-- `{a}.max' _` is `a`. -/ +@[simp] +theorem max'_singleton (a : α) : ({a} : Finset α).max' (singleton_nonempty _) = a := by simp [max'] + +theorem min'_lt_max' {i j} (H1 : i ∈ s) (H2 : j ∈ s) (H3 : i ≠ j) : + s.min' ⟨i, H1⟩ < s.max' ⟨i, H1⟩ := + isGLB_lt_isLUB_of_ne (s.isLeast_min' _).isGLB (s.isGreatest_max' _).isLUB H1 H2 H3 + +/-- If there's more than 1 element, the min' is less than the max'. An alternate version of +`min'_lt_max'` which is sometimes more convenient. +-/ +theorem min'_lt_max'_of_card (h₂ : 1 < card s) : + s.min' (Finset.card_pos.1 <| by omega) < s.max' (Finset.card_pos.1 <| by omega) := by + rcases one_lt_card.1 h₂ with ⟨a, ha, b, hb, hab⟩ + exact s.min'_lt_max' ha hb hab + +theorem map_ofDual_min (s : Finset αᵒᵈ) : s.min.map ofDual = (s.image ofDual).max := by + rw [max_eq_sup_withBot, sup_image] + exact congr_fun Option.map_id _ + +theorem map_ofDual_max (s : Finset αᵒᵈ) : s.max.map ofDual = (s.image ofDual).min := by + rw [min_eq_inf_withTop, inf_image] + exact congr_fun Option.map_id _ + +theorem map_toDual_min (s : Finset α) : s.min.map toDual = (s.image toDual).max := by + rw [max_eq_sup_withBot, sup_image] + exact congr_fun Option.map_id _ + +theorem map_toDual_max (s : Finset α) : s.max.map toDual = (s.image toDual).min := by + rw [min_eq_inf_withTop, inf_image] + exact congr_fun Option.map_id _ + +-- Porting note: new proofs without `convert` for the next four theorems. + +theorem ofDual_min' {s : Finset αᵒᵈ} (hs : s.Nonempty) : + ofDual (min' s hs) = max' (s.image ofDual) (hs.image _) := by + rw [← WithBot.coe_eq_coe] + simp only [min'_eq_inf', id_eq, ofDual_inf', Function.comp_apply, coe_sup', max'_eq_sup', + sup_image] + rfl + +theorem ofDual_max' {s : Finset αᵒᵈ} (hs : s.Nonempty) : + ofDual (max' s hs) = min' (s.image ofDual) (hs.image _) := by + rw [← WithTop.coe_eq_coe] + simp only [max'_eq_sup', id_eq, ofDual_sup', Function.comp_apply, coe_inf', min'_eq_inf', + inf_image] + rfl + +theorem toDual_min' {s : Finset α} (hs : s.Nonempty) : + toDual (min' s hs) = max' (s.image toDual) (hs.image _) := by + rw [← WithBot.coe_eq_coe] + simp only [min'_eq_inf', id_eq, toDual_inf', Function.comp_apply, coe_sup', max'_eq_sup', + sup_image] + rfl + +theorem toDual_max' {s : Finset α} (hs : s.Nonempty) : + toDual (max' s hs) = min' (s.image toDual) (hs.image _) := by + rw [← WithTop.coe_eq_coe] + simp only [max'_eq_sup', id_eq, toDual_sup', Function.comp_apply, coe_inf', min'_eq_inf', + inf_image] + rfl + +theorem max'_subset {s t : Finset α} (H : s.Nonempty) (hst : s ⊆ t) : + s.max' H ≤ t.max' (H.mono hst) := + le_max' _ _ (hst (s.max'_mem H)) + +theorem min'_subset {s t : Finset α} (H : s.Nonempty) (hst : s ⊆ t) : + t.min' (H.mono hst) ≤ s.min' H := + min'_le _ _ (hst (s.min'_mem H)) + +theorem max'_insert (a : α) (s : Finset α) (H : s.Nonempty) : + (insert a s).max' (s.insert_nonempty a) = max (s.max' H) a := + (isGreatest_max' _ _).unique <| by + rw [coe_insert, max_comm] + exact (isGreatest_max' _ _).insert _ + +theorem min'_insert (a : α) (s : Finset α) (H : s.Nonempty) : + (insert a s).min' (s.insert_nonempty a) = min (s.min' H) a := + (isLeast_min' _ _).unique <| by + rw [coe_insert, min_comm] + exact (isLeast_min' _ _).insert _ + +theorem lt_max'_of_mem_erase_max' [DecidableEq α] {a : α} (ha : a ∈ s.erase (s.max' H)) : + a < s.max' H := + lt_of_le_of_ne (le_max' _ _ (mem_of_mem_erase ha)) <| ne_of_mem_of_not_mem ha <| not_mem_erase _ _ + +theorem min'_lt_of_mem_erase_min' [DecidableEq α] {a : α} (ha : a ∈ s.erase (s.min' H)) : + s.min' H < a := + @lt_max'_of_mem_erase_max' αᵒᵈ _ s H _ a ha + +/-- 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' h.of_image) := by + simp only [max', sup'_image] + exact .symm <| comp_sup'_eq_sup'_comp _ _ fun _ _ ↦ hf.map_max + +/-- 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' h.of_image) := by + simp only [min', inf'_image] + exact .symm <| comp_inf'_eq_inf'_comp _ _ fun _ _ ↦ hf.map_min + +/-- 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 + +theorem coe_min' {s : Finset α} (hs : s.Nonempty) : ↑(s.min' hs) = s.min := + coe_inf' hs id + +theorem max_mem_image_coe {s : Finset α} (hs : s.Nonempty) : + s.max ∈ (s.image (↑) : Finset (WithBot α)) := + mem_image.2 ⟨max' s hs, max'_mem _ _, coe_max' hs⟩ + +theorem min_mem_image_coe {s : Finset α} (hs : s.Nonempty) : + s.min ∈ (s.image (↑) : Finset (WithTop α)) := + mem_image.2 ⟨min' s hs, min'_mem _ _, coe_min' hs⟩ + +theorem max_mem_insert_bot_image_coe (s : Finset α) : + s.max ∈ (insert ⊥ (s.image (↑)) : Finset (WithBot α)) := + mem_insert.2 <| s.eq_empty_or_nonempty.imp max_eq_bot.2 max_mem_image_coe + +theorem min_mem_insert_top_image_coe (s : Finset α) : + s.min ∈ (insert ⊤ (s.image (↑)) : Finset (WithTop α)) := + mem_insert.2 <| s.eq_empty_or_nonempty.imp min_eq_top.2 min_mem_image_coe + +theorem max'_erase_ne_self {s : Finset α} (s0 : (s.erase x).Nonempty) : (s.erase x).max' s0 ≠ x := + ne_of_mem_erase (max'_mem _ s0) + +theorem min'_erase_ne_self {s : Finset α} (s0 : (s.erase x).Nonempty) : (s.erase x).min' s0 ≠ x := + ne_of_mem_erase (min'_mem _ s0) + +theorem max_erase_ne_self {s : Finset α} : (s.erase x).max ≠ x := by + by_cases s0 : (s.erase x).Nonempty + · refine ne_of_eq_of_ne (coe_max' s0).symm ?_ + exact WithBot.coe_eq_coe.not.mpr (max'_erase_ne_self _) + · rw [not_nonempty_iff_eq_empty.mp s0, max_empty] + exact WithBot.bot_ne_coe + +theorem min_erase_ne_self {s : Finset α} : (s.erase x).min ≠ x := by + -- Porting note: old proof `convert @max_erase_ne_self αᵒᵈ _ _ _` + convert @max_erase_ne_self αᵒᵈ _ (toDual x) (s.map toDual.toEmbedding) using 1 + apply congr_arg -- Porting note: forces unfolding to see `Finset.min` is `Finset.max` + congr! + ext; simp only [mem_map_equiv]; exact Iff.rfl + +theorem exists_next_right {x : α} {s : Finset α} (h : ∃ y ∈ s, x < y) : + ∃ y ∈ s, x < y ∧ ∀ z ∈ s, x < z → y ≤ z := + have Hne : (s.filter (x < ·)).Nonempty := h.imp fun y hy => mem_filter.2 (by simpa) + have aux := mem_filter.1 (min'_mem _ Hne) + ⟨min' _ Hne, aux.1, by simp, fun z hzs hz => min'_le _ _ <| mem_filter.2 ⟨hzs, by simpa⟩⟩ + +theorem exists_next_left {x : α} {s : Finset α} (h : ∃ y ∈ s, y < x) : + ∃ y ∈ s, y < x ∧ ∀ z ∈ s, z < x → z ≤ y := + @exists_next_right αᵒᵈ _ x s h + +/-- If finsets `s` and `t` are interleaved, then `Finset.card s ≤ Finset.card t + 1`. -/ +theorem card_le_of_interleaved {s t : Finset α} + (h : ∀ᵉ (x ∈ s) (y ∈ s), + x < y → (∀ z ∈ s, z ∉ Set.Ioo x y) → ∃ z ∈ t, x < z ∧ z < y) : + s.card ≤ t.card + 1 := by + replace h : ∀ᵉ (x ∈ s) (y ∈ s), x < y → ∃ z ∈ t, x < z ∧ z < y := by + intro x hx y hy hxy + rcases exists_next_right ⟨y, hy, hxy⟩ with ⟨a, has, hxa, ha⟩ + rcases h x hx a has hxa fun z hzs hz => hz.2.not_le <| ha _ hzs hz.1 with ⟨b, hbt, hxb, hba⟩ + exact ⟨b, hbt, hxb, hba.trans_le <| ha _ hy hxy⟩ + set f : α → WithTop α := fun x => (t.filter fun y => x < y).min + have f_mono : StrictMonoOn f s := by + intro x hx y hy hxy + rcases h x hx y hy hxy with ⟨a, hat, hxa, hay⟩ + calc + f x ≤ a := min_le (mem_filter.2 ⟨hat, by simpa⟩) + _ < f y := + (Finset.lt_inf_iff <| WithTop.coe_lt_top a).2 fun b hb => + WithTop.coe_lt_coe.2 <| hay.trans (by simpa using (mem_filter.1 hb).2) + + calc + s.card = (s.image f).card := (card_image_of_injOn f_mono.injOn).symm + _ ≤ (insert ⊤ (t.image (↑)) : Finset (WithTop α)).card := + card_mono <| image_subset_iff.2 fun x _ => + insert_subset_insert _ (image_subset_image <| filter_subset _ _) + (min_mem_insert_top_image_coe _) + _ ≤ t.card + 1 := (card_insert_le _ _).trans (Nat.add_le_add_right card_image_le _) + +/-- If finsets `s` and `t` are interleaved, then `Finset.card s ≤ Finset.card (t \ s) + 1`. -/ +theorem card_le_diff_of_interleaved {s t : Finset α} + (h : + ∀ᵉ (x ∈ s) (y ∈ s), + x < y → (∀ z ∈ s, z ∉ Set.Ioo x y) → ∃ z ∈ t, x < z ∧ z < y) : + s.card ≤ (t \ s).card + 1 := + card_le_of_interleaved fun x hx y hy hxy hs => + let ⟨z, hzt, hxz, hzy⟩ := h x hx y hy hxy hs + ⟨z, mem_sdiff.2 ⟨hzt, fun hzs => hs z hzs ⟨hxz, hzy⟩⟩, hxz, hzy⟩ + +/-- Induction principle for `Finset`s in a linearly ordered type: a predicate is true on all +`s : Finset α` provided that: + +* it is true on the empty `Finset`, +* for every `s : Finset α` and an element `a` strictly greater than all elements of `s`, `p s` + implies `p (insert a s)`. -/ +@[elab_as_elim] +theorem induction_on_max [DecidableEq α] {p : Finset α → Prop} (s : Finset α) (h0 : p ∅) + (step : ∀ a s, (∀ x ∈ s, x < a) → p s → p (insert a s)) : p s := by + induction' s using Finset.strongInductionOn with s ihs + rcases s.eq_empty_or_nonempty with (rfl | hne) + · exact h0 + · have H : s.max' hne ∈ s := max'_mem s hne + rw [← insert_erase H] + exact step _ _ (fun x => s.lt_max'_of_mem_erase_max' hne) (ihs _ <| erase_ssubset H) + +/-- Induction principle for `Finset`s in a linearly ordered type: a predicate is true on all +`s : Finset α` provided that: + +* it is true on the empty `Finset`, +* for every `s : Finset α` and an element `a` strictly less than all elements of `s`, `p s` + implies `p (insert a s)`. -/ +@[elab_as_elim] +theorem induction_on_min [DecidableEq α] {p : Finset α → Prop} (s : Finset α) (h0 : p ∅) + (step : ∀ a s, (∀ x ∈ s, a < x) → p s → p (insert a s)) : p s := + @induction_on_max αᵒᵈ _ _ _ s h0 step + +end MaxMin + +section MaxMinInductionValue + +variable [LinearOrder α] [LinearOrder β] + +/-- Induction principle for `Finset`s in any type from which a given function `f` maps to a linearly +ordered type : a predicate is true on all `s : Finset α` provided that: + +* it is true on the empty `Finset`, +* for every `s : Finset α` and an element `a` such that for elements of `s` denoted by `x` we have + `f x ≤ f a`, `p s` implies `p (insert a s)`. -/ +@[elab_as_elim] +theorem induction_on_max_value [DecidableEq ι] (f : ι → α) {p : Finset ι → Prop} (s : Finset ι) + (h0 : p ∅) (step : ∀ a s, a ∉ s → (∀ x ∈ s, f x ≤ f a) → p s → p (insert a s)) : p s := by + induction' s using Finset.strongInductionOn with s ihs + rcases (s.image f).eq_empty_or_nonempty with (hne | hne) + · simp only [image_eq_empty] at hne + simp only [hne, h0] + · have H : (s.image f).max' hne ∈ s.image f := max'_mem (s.image f) hne + simp only [mem_image, exists_prop] at H + rcases H with ⟨a, has, hfa⟩ + rw [← insert_erase has] + refine step _ _ (not_mem_erase a s) (fun x hx => ?_) (ihs _ <| erase_ssubset has) + rw [hfa] + exact le_max' _ _ (mem_image_of_mem _ <| mem_of_mem_erase hx) + +/-- Induction principle for `Finset`s in any type from which a given function `f` maps to a linearly +ordered type : a predicate is true on all `s : Finset α` provided that: + +* it is true on the empty `Finset`, +* for every `s : Finset α` and an element `a` such that for elements of `s` denoted by `x` we have + `f a ≤ f x`, `p s` implies `p (insert a s)`. -/ +@[elab_as_elim] +theorem induction_on_min_value [DecidableEq ι] (f : ι → α) {p : Finset ι → Prop} (s : Finset ι) + (h0 : p ∅) (step : ∀ a s, a ∉ s → (∀ x ∈ s, f a ≤ f x) → p s → p (insert a s)) : p s := + @induction_on_max_value αᵒᵈ ι _ _ _ _ s h0 step + +end MaxMinInductionValue + +section ExistsMaxMin + +variable [LinearOrder α] + +theorem exists_max_image (s : Finset β) (f : β → α) (h : s.Nonempty) : + ∃ x ∈ s, ∀ x' ∈ s, f x' ≤ f x := by + cases' max_of_nonempty (h.image f) with y hy + rcases mem_image.mp (mem_of_max hy) with ⟨x, hx, rfl⟩ + exact ⟨x, hx, fun x' hx' => le_max_of_eq (mem_image_of_mem f hx') hy⟩ + +theorem exists_min_image (s : Finset β) (f : β → α) (h : s.Nonempty) : + ∃ x ∈ s, ∀ x' ∈ s, f x ≤ f x' := + @exists_max_image αᵒᵈ β _ s f h + +end ExistsMaxMin + +theorem isGLB_iff_isLeast [LinearOrder α] (i : α) (s : Finset α) (hs : s.Nonempty) : + IsGLB (s : Set α) i ↔ IsLeast (↑s) i := by + refine ⟨fun his => ?_, IsLeast.isGLB⟩ + suffices i = min' s hs by + rw [this] + exact isLeast_min' s hs + rw [IsGLB, IsGreatest, mem_lowerBounds, mem_upperBounds] at his + exact le_antisymm (his.1 (Finset.min' s hs) (Finset.min'_mem s hs)) (his.2 _ (Finset.min'_le s)) + +theorem isLUB_iff_isGreatest [LinearOrder α] (i : α) (s : Finset α) (hs : s.Nonempty) : + IsLUB (s : Set α) i ↔ IsGreatest (↑s) i := + @isGLB_iff_isLeast αᵒᵈ _ i s hs + +theorem isGLB_mem [LinearOrder α] {i : α} (s : Finset α) (his : IsGLB (s : Set α) i) + (hs : s.Nonempty) : i ∈ s := by + rw [← mem_coe] + exact ((isGLB_iff_isLeast i s hs).mp his).1 + +theorem isLUB_mem [LinearOrder α] {i : α} (s : Finset α) (his : IsLUB (s : Set α) i) + (hs : s.Nonempty) : i ∈ s := + @isGLB_mem αᵒᵈ _ i s his hs + +end Finset diff --git a/Mathlib/Data/Finset/MulAntidiagonal.lean b/Mathlib/Data/Finset/MulAntidiagonal.lean index d361b2e348cd7..534b98c618c6b 100644 --- a/Mathlib/Data/Finset/MulAntidiagonal.lean +++ b/Mathlib/Data/Finset/MulAntidiagonal.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Yaël Dillies -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.Monoid.Defs import Mathlib.Data.Set.MulAntidiagonal diff --git a/Mathlib/Data/Finset/NAry.lean b/Mathlib/Data/Finset/NAry.lean index fa32e7a832096..4db70840b348d 100644 --- a/Mathlib/Data/Finset/NAry.lean +++ b/Mathlib/Data/Finset/NAry.lean @@ -454,9 +454,9 @@ theorem card_dvd_card_image₂_left (hf : ∀ b ∈ t, Injective fun a => f a b) /-- 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) : +theorem subset_set_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 + rw [← Set.image_prod, subset_set_image_iff] at hu rcases hu with ⟨u, hu, rfl⟩ classical use u.image Prod.fst, u.image Prod.snd @@ -464,6 +464,8 @@ theorem subset_image₂ {s : Set α} {t : Set β} (hu : ↑u ⊆ image2 f s t) : image_subset_iff] exact ⟨fun _ h ↦ (hu h).1, fun _ h ↦ (hu h).2, fun x hx ↦ mem_image₂_of_mem hx hx⟩ +@[deprecated (since := "2024-09-22")] alias subset_image₂ := subset_set_image₂ + end section UnionInter diff --git a/Mathlib/Data/Finset/Pi.lean b/Mathlib/Data/Finset/Pi.lean index 8edf7868f430a..9751986c4519c 100644 --- a/Mathlib/Data/Finset/Pi.lean +++ b/Mathlib/Data/Finset/Pi.lean @@ -92,6 +92,10 @@ lemma pi_nonempty : (s.pi t).Nonempty ↔ ∀ a ∈ s, (t a).Nonempty := by @[aesop safe apply (rule_sets := [finsetNonempty])] alias ⟨_, pi_nonempty_of_forall_nonempty⟩ := pi_nonempty +@[simp] +lemma pi_eq_empty : s.pi t = ∅ ↔ ∃ a ∈ s, t a = ∅ := by + simp [← not_nonempty_iff_eq_empty] + @[simp] theorem pi_insert [∀ a, DecidableEq (β a)] {s : Finset α} {t : ∀ a : α, Finset (β a)} {a : α} (ha : a ∉ s) : pi (insert a s) t = (t a).biUnion fun b => (pi s t).image (Pi.cons s a b) := by diff --git a/Mathlib/Data/Finset/PiInduction.lean b/Mathlib/Data/Finset/PiInduction.lean index 4eb4a769d4e6a..14801945c227c 100644 --- a/Mathlib/Data/Finset/PiInduction.lean +++ b/Mathlib/Data/Finset/PiInduction.lean @@ -3,6 +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.Data.Finset.Max import Mathlib.Data.Finset.Sigma import Mathlib.Data.Fintype.Card diff --git a/Mathlib/Data/Finset/Preimage.lean b/Mathlib/Data/Finset/Preimage.lean index 840e7e2c93e3e..657acee065919 100644 --- a/Mathlib/Data/Finset/Preimage.lean +++ b/Mathlib/Data/Finset/Preimage.lean @@ -80,6 +80,10 @@ theorem map_subset_iff_subset_preimage {f : α ↪ β} {s : Finset α} {t : Fins s.map f ⊆ t ↔ s ⊆ t.preimage f f.injective.injOn := by classical rw [map_eq_image, image_subset_iff_subset_preimage] +lemma card_preimage (s : Finset β) (f : α → β) (hf) [DecidablePred (· ∈ Set.range f)] : + (s.preimage f hf).card = {x ∈ s | x ∈ Set.range f}.card := + card_nbij f (by simp) (by simpa) (fun b hb ↦ by aesop) + theorem image_preimage [DecidableEq β] (f : α → β) (s : Finset β) [∀ x, Decidable (x ∈ Set.range f)] (hf : Set.InjOn f (f ⁻¹' ↑s)) : image f (preimage s f hf) = s.filter fun x => x ∈ Set.range f := Finset.coe_inj.1 <| by @@ -96,7 +100,7 @@ theorem preimage_subset {f : α ↪ β} {s : Finset β} {t : Finset α} (hs : s theorem subset_map_iff {f : α ↪ β} {s : Finset β} {t : Finset α} : s ⊆ t.map f ↔ ∃ u ⊆ t, s = u.map f := by classical - simp_rw [← coe_subset, coe_map, subset_image_iff, map_eq_image, eq_comm] + simp_rw [map_eq_image, subset_image_iff, eq_comm] theorem sigma_preimage_mk {β : α → Type*} [DecidableEq α] (s : Finset (Σa, β a)) (t : Finset α) : (t.sigma fun a => s.preimage (Sigma.mk a) sigma_mk_injective.injOn) = @@ -114,5 +118,13 @@ theorem sigma_image_fst_preimage_mk {β : α → Type*} [DecidableEq α] (s : Fi s := s.sigma_preimage_mk_of_subset (Subset.refl _) +@[simp] lemma preimage_inl (s : Finset (α ⊕ β)) : + s.preimage Sum.inl Sum.inl_injective.injOn = s.toLeft := by + ext x; simp + +@[simp] lemma preimage_inr (s : Finset (α ⊕ β)) : + s.preimage Sum.inr Sum.inr_injective.injOn = s.toRight := by + ext x; simp + end Preimage end Finset diff --git a/Mathlib/Data/Finset/SMulAntidiagonal.lean b/Mathlib/Data/Finset/SMulAntidiagonal.lean index 20da3b77568f0..53d0c959253ec 100644 --- a/Mathlib/Data/Finset/SMulAntidiagonal.lean +++ b/Mathlib/Data/Finset/SMulAntidiagonal.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Scott Carnahan. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Scott Carnahan -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Data.Set.SMulAntidiagonal /-! diff --git a/Mathlib/Data/Finset/Sigma.lean b/Mathlib/Data/Finset/Sigma.lean index e3f0b82144225..9be90160317cf 100644 --- a/Mathlib/Data/Finset/Sigma.lean +++ b/Mathlib/Data/Finset/Sigma.lean @@ -5,6 +5,7 @@ Authors: Mario Carneiro, Yaël Dillies, Bhavik Mehta -/ import Mathlib.Data.Finset.Lattice import Mathlib.Data.Set.Sigma +import Mathlib.Order.CompleteLattice.Finset /-! # Finite sets in a sigma type diff --git a/Mathlib/Data/Finset/Sort.lean b/Mathlib/Data/Finset/Sort.lean index 8d825b85b9622..361e4f3721a7f 100644 --- a/Mathlib/Data/Finset/Sort.lean +++ b/Mathlib/Data/Finset/Sort.lean @@ -6,7 +6,7 @@ Authors: Mario Carneiro import Mathlib.Order.RelIso.Set import Mathlib.Data.Multiset.Sort import Mathlib.Data.List.NodupEquivFin -import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Finset.Max import Mathlib.Data.Fintype.Card /-! @@ -32,6 +32,10 @@ variable (r : α → α → Prop) [DecidableRel r] [IsTrans α r] [IsAntisymm α def sort (s : Finset α) : List α := Multiset.sort r s.1 +@[simp] +theorem sort_val (s : Finset α) : Multiset.sort r s.val = sort r s := + rfl + @[simp] theorem sort_sorted (s : Finset α) : List.Sorted r (sort r s) := Multiset.sort_sorted _ _ @@ -64,11 +68,27 @@ theorem sort_empty : sort r ∅ = [] := theorem sort_singleton (a : α) : sort r {a} = [a] := Multiset.sort_singleton r a +theorem sort_cons {a : α} {s : Finset α} (h₁ : ∀ b ∈ s, r a b) (h₂ : a ∉ s) : + sort r (cons a s h₂) = a :: sort r s := by + rw [sort, cons_val, Multiset.sort_cons r a _ h₁, sort_val] + +theorem sort_insert [DecidableEq α] {a : α} {s : Finset α} (h₁ : ∀ b ∈ s, r a b) (h₂ : a ∉ s) : + sort r (insert a s) = a :: sort r s := by + rw [← cons_eq_insert _ _ h₂, sort_cons r h₁] + open scoped List in theorem sort_perm_toList (s : Finset α) : sort r s ~ s.toList := by rw [← Multiset.coe_eq_coe] simp only [coe_toList, sort_eq] +theorem _root_.List.toFinset_sort [DecidableEq α] {l : List α} (hl : l.Nodup) : + sort r l.toFinset = l ↔ l.Sorted r := by + refine ⟨?_, List.eq_of_perm_of_sorted ((sort_perm_toList r _).trans (List.toFinset_toList hl)) + (sort_sorted r _)⟩ + intro h + rw [← h] + exact sort_sorted r _ + end sort section SortLinearOrder diff --git a/Mathlib/Data/Finset/Sum.lean b/Mathlib/Data/Finset/Sum.lean index f9863829696b5..678aaccf6ad61 100644 --- a/Mathlib/Data/Finset/Sum.lean +++ b/Mathlib/Data/Finset/Sum.lean @@ -1,7 +1,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 +Authors: Yaël Dillies, Bhavik Mehta -/ import Mathlib.Data.Multiset.Sum import Mathlib.Data.Finset.Card @@ -15,6 +15,8 @@ the `Finset.sum` operation which computes the additive sum. ## Main declarations * `Finset.disjSum`: `s.disjSum t` is the disjoint sum of `s` and `t`. +* `Finset.toLeft`: Given a finset of elements `α ⊕ β`, extracts all the elements of the form `α`. +* `Finset.toRight`: Given a finset of elements `α ⊕ β`, extracts all the elements of the form `β`. -/ @@ -94,4 +96,109 @@ theorem disj_sum_strictMono_right (s : Finset α) : StrictMono (s.disjSum : Finset β → Finset (α ⊕ β)) := fun _ _ => disjSum_ssubset_disjSum_of_subset_of_ssubset Subset.rfl +@[simp] lemma disjSum_inj {α β : Type*} {s₁ s₂ : Finset α} {t₁ t₂ : Finset β} : + s₁.disjSum t₁ = s₂.disjSum t₂ ↔ s₁ = s₂ ∧ t₁ = t₂ := by + simp [Finset.ext_iff] + +lemma Injective2_disjSum {α β : Type*} : Function.Injective2 (@disjSum α β) := + fun _ _ _ _ => by simp [Finset.ext_iff] + +/-- +Given a finset of elements `α ⊕ β`, extract all the elements of the form `α`. This +forms a quasi-inverse to `disjSum`, in that it recovers its left input. + +See also `List.partitionMap`. +-/ +def toLeft (s : Finset (α ⊕ β)) : Finset α := + s.disjiUnion (Sum.elim singleton (fun _ => ∅)) <| by + simp [Set.PairwiseDisjoint, Set.Pairwise, Function.onFun, eq_comm] + +/-- +Given a finset of elements `α ⊕ β`, extract all the elements of the form `β`. This +forms a quasi-inverse to `disjSum`, in that it recovers its right input. + +See also `List.partitionMap`. +-/ +def toRight (s : Finset (α ⊕ β)) : Finset β := + s.disjiUnion (Sum.elim (fun _ => ∅) singleton) <| by + simp [Set.PairwiseDisjoint, Set.Pairwise, Function.onFun, eq_comm] + +variable {u v : Finset (α ⊕ β)} + +@[simp] lemma mem_toLeft {x : α} : x ∈ u.toLeft ↔ inl x ∈ u := by + simp [toLeft] + +@[simp] lemma mem_toRight {x : β} : x ∈ u.toRight ↔ inr x ∈ u := by + simp [toRight] + +@[gcongr] +lemma toLeft_subset_toLeft : u ⊆ v → u.toLeft ⊆ v.toLeft := + fun h _ => by simpa only [mem_toLeft] using @h _ + +@[gcongr] +lemma toRight_subset_toRight : u ⊆ v → u.toRight ⊆ v.toRight := + fun h _ => by simpa only [mem_toRight] using @h _ + +lemma toLeft_monotone : Monotone (@toLeft α β) := fun _ _ => toLeft_subset_toLeft +lemma toRight_monotone : Monotone (@toRight α β) := fun _ _ => toRight_subset_toRight + +lemma toLeft_disjSum_toRight : u.toLeft.disjSum u.toRight = u := by + ext (x | x) <;> simp + +lemma card_toLeft_add_card_toRight : u.toLeft.card + u.toRight.card = u.card := by + rw [← card_disjSum, toLeft_disjSum_toRight] + +lemma card_toLeft_le : u.toLeft.card ≤ u.card := + (Nat.le_add_right _ _).trans_eq card_toLeft_add_card_toRight + +lemma card_toRight_le : u.toRight.card ≤ u.card := + (Nat.le_add_left _ _).trans_eq card_toLeft_add_card_toRight + +@[simp] lemma toLeft_disjSum : (s.disjSum t).toLeft = s := by ext x; simp + +@[simp] lemma toRight_disjSum : (s.disjSum t).toRight = t := by ext x; simp + +lemma disjSum_eq_iff : s.disjSum t = u ↔ s = u.toLeft ∧ t = u.toRight := + ⟨fun h => by simp [← h], fun h => by simp [h, toLeft_disjSum_toRight]⟩ + +lemma eq_disjSum_iff : u = s.disjSum t ↔ u.toLeft = s ∧ u.toRight = t := + ⟨fun h => by simp [h], fun h => by simp [← h, toLeft_disjSum_toRight]⟩ + +@[simp] lemma toLeft_map_sumComm : (u.map (Equiv.sumComm _ _).toEmbedding).toLeft = u.toRight := by + ext x; simp + +@[simp] lemma toRight_map_sumComm : (u.map (Equiv.sumComm _ _).toEmbedding).toRight = u.toLeft := by + ext x; simp + +@[simp] lemma toLeft_cons_inl (ha) : + (cons (inl a) u ha).toLeft = cons a u.toLeft (by simpa) := by ext y; simp +@[simp] lemma toLeft_cons_inr (hb) : + (cons (inr b) u hb).toLeft = u.toLeft := by ext y; simp +@[simp] lemma toRight_cons_inl (ha) : + (cons (inl a) u ha).toRight = u.toRight := by ext y; simp +@[simp] lemma toRight_cons_inr (hb) : + (cons (inr b) u hb).toRight = cons b u.toRight (by simpa) := by ext y; simp + +variable [DecidableEq α] [DecidableEq β] + +lemma toLeft_image_swap : (u.image Sum.swap).toLeft = u.toRight := by + ext x; simp + +lemma toRight_image_swap : (u.image Sum.swap).toRight = u.toLeft := by + ext x; simp + +@[simp] lemma toLeft_insert_inl : (insert (inl a) u).toLeft = insert a u.toLeft := by ext y; simp +@[simp] lemma toLeft_insert_inr : (insert (inr b) u).toLeft = u.toLeft := by ext y; simp +@[simp] lemma toRight_insert_inl : (insert (inl a) u).toRight = u.toRight := by ext y; simp +@[simp] lemma toRight_insert_inr : (insert (inr b) u).toRight = insert b u.toRight := by ext y; simp + +lemma toLeft_inter : (u ∩ v).toLeft = u.toLeft ∩ v.toLeft := by ext x; simp +lemma toRight_inter : (u ∩ v).toRight = u.toRight ∩ v.toRight := by ext x; simp + +lemma toLeft_union : (u ∪ v).toLeft = u.toLeft ∪ v.toLeft := by ext x; simp +lemma toRight_union : (u ∪ v).toRight = u.toRight ∪ v.toRight := by ext x; simp + +lemma toLeft_sdiff : (u \ v).toLeft = u.toLeft \ v.toLeft := by ext x; simp +lemma toRight_sdiff : (u \ v).toRight = u.toRight \ v.toRight := by ext x; simp + end Finset diff --git a/Mathlib/Data/Finset/Sups.lean b/Mathlib/Data/Finset/Sups.lean index 16e426c59c332..5188385616bb7 100644 --- a/Mathlib/Data/Finset/Sups.lean +++ b/Mathlib/Data/Finset/Sups.lean @@ -146,7 +146,7 @@ theorem sups_inter_subset_right : s ⊻ (t₁ ∩ t₂) ⊆ s ⊻ t₁ ∩ s ⊻ theorem subset_sups {s t : Set α} : ↑u ⊆ s ⊻ t → ∃ s' t' : Finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' ⊻ t' := - subset_image₂ + subset_set_image₂ lemma image_sups (f : F) (s t : Finset α) : image f (s ⊻ t) = image f s ⊻ image f t := image_image₂_distrib <| map_sup f @@ -293,7 +293,7 @@ theorem infs_inter_subset_right : s ⊼ (t₁ ∩ t₂) ⊆ s ⊼ t₁ ∩ s ⊼ theorem subset_infs {s t : Set α} : ↑u ⊆ s ⊼ t → ∃ s' t' : Finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' ⊼ t' := - subset_image₂ + subset_set_image₂ lemma image_infs (f : F) (s t : Finset α) : image f (s ⊼ t) = image f s ⊼ image f t := image_image₂_distrib <| map_inf f @@ -582,7 +582,7 @@ lemma diffs_inter_subset_right : s \\ (t₁ ∩ t₂) ⊆ s \\ t₁ ∩ s \\ t lemma subset_diffs {s t : Set α} : ↑u ⊆ Set.image2 (· \ ·) s t → ∃ s' t' : Finset α, ↑s' ⊆ s ∧ ↑t' ⊆ t ∧ u ⊆ s' \\ t' := - subset_image₂ + subset_set_image₂ variable (s t u) diff --git a/Mathlib/Data/Finset/Sym.lean b/Mathlib/Data/Finset/Sym.lean index c591056cea7ff..f7fe2a928b7c4 100644 --- a/Mathlib/Data/Finset/Sym.lean +++ b/Mathlib/Data/Finset/Sym.lean @@ -2,8 +2,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 - -[`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.Vector diff --git a/Mathlib/Data/Finsupp/Defs.lean b/Mathlib/Data/Finsupp/Defs.lean index 70c91059b3738..17844597d0e12 100644 --- a/Mathlib/Data/Finsupp/Defs.lean +++ b/Mathlib/Data/Finsupp/Defs.lean @@ -714,6 +714,10 @@ theorem mapRange_comp (f : N → P) (hf : f 0 = 0) (f₂ : M → N) (hf₂ : f (g : α →₀ M) : mapRange (f ∘ f₂) h g = mapRange f hf (mapRange f₂ hf₂ g) := ext fun _ => rfl +@[simp] +lemma mapRange_mapRange (e₁ : N → P) (e₂ : M → N) (he₁ he₂) (f : α →₀ M) : + mapRange e₁ he₁ (mapRange e₂ he₂ f) = mapRange (e₁ ∘ e₂) (by simp [*]) f := ext fun _ ↦ rfl + theorem support_mapRange {f : M → N} {hf : f 0 = 0} {g : α →₀ M} : (mapRange f hf g).support ⊆ g.support := support_onFinset_subset @@ -730,6 +734,14 @@ theorem support_mapRange_of_injective {e : M → N} (he0 : e 0 = 0) (f : ι → simp only [Finsupp.mem_support_iff, Ne, Finsupp.mapRange_apply] exact he.ne_iff' he0 +/-- `Finsupp.mapRange` of a surjective function is surjective. -/ +lemma mapRange_surjective (e : M → N) (he₀ : e 0 = 0) (he : Surjective e) : + Surjective (Finsupp.mapRange (α := α) e he₀) := by + classical + let d (n : N) : M := if n = 0 then 0 else surjInv he n + have : RightInverse d e := fun n ↦ by by_cases h : n = 0 <;> simp [d, h, he₀, surjInv_eq he n] + exact fun f ↦ ⟨mapRange d (by simp [d]) f, by simp [this.comp_eq_id]⟩ + end MapRange /-! ### Declarations about `embDomain` -/ @@ -1048,6 +1060,60 @@ theorem induction_linear {p : (α →₀ M) → Prop} (f : α →₀ M) (h0 : p (hadd : ∀ f g : α →₀ M, p f → p g → p (f + g)) (hsingle : ∀ a b, p (single a b)) : p f := induction₂ f h0 fun _a _b _f _ _ w => hadd _ _ w (hsingle _ _) +section LinearOrder + +variable [LinearOrder α] {p : (α →₀ M) → Prop} + +/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. + +The theorem `induction_on_max₂` swaps the argument order in the sum. -/ +theorem induction_on_max (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (single a b + f)) : + p f := by + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) + · rwa [support_eq_empty.1 h] + · have hs' : (erase a f).support = s := by + rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] + rw [← single_add_erase a f] + refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') + rw [← mem_support_iff, hs] + exact mem_insert_self a s + +/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. + +The theorem `induction_on_min₂` swaps the argument order in the sum. -/ +theorem induction_on_min (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (single a b + f)) : + p f := + induction_on_max (α := αᵒᵈ) f h0 ha + +/-- A finitely supported function can be built by adding up `single a b` for increasing `a`. + +The theorem `induction_on_max` swaps the argument order in the sum. -/ +theorem induction_on_max₂ (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, c < a) → b ≠ 0 → p f → p (f + single a b)) : + p f := by + suffices ∀ (s) (f : α →₀ M), f.support = s → p f from this _ _ rfl + refine fun s => s.induction_on_max (fun f h => ?_) (fun a s hm hf f hs => ?_) + · rwa [support_eq_empty.1 h] + · have hs' : (erase a f).support = s := by + rw [support_erase, hs, erase_insert (fun ha => (hm a ha).false)] + rw [← erase_add_single a f] + refine ha _ _ _ (fun c hc => hm _ <| hs'.symm ▸ hc) ?_ (hf _ hs') + rw [← mem_support_iff, hs] + exact mem_insert_self a s + +/-- A finitely supported function can be built by adding up `single a b` for decreasing `a`. + +The theorem `induction_on_min` swaps the argument order in the sum. -/ +theorem induction_on_min₂ (f : α →₀ M) (h0 : p 0) + (ha : ∀ (a b) (f : α →₀ M), (∀ c ∈ f.support, a < c) → b ≠ 0 → p f → p (f + single a b)) : + p f := + induction_on_max₂ (α := αᵒᵈ) f h0 ha + +end LinearOrder + @[simp] theorem add_closure_setOf_eq_single : AddSubmonoid.closure { f : α →₀ M | ∃ a b, f = single a b } = ⊤ := diff --git a/Mathlib/Data/Finsupp/Order.lean b/Mathlib/Data/Finsupp/Order.lean index c77303cc05d77..2d4dbe742d79c 100644 --- a/Mathlib/Data/Finsupp/Order.lean +++ b/Mathlib/Data/Finsupp/Order.lean @@ -3,7 +3,9 @@ Copyright (c) 2021 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin, Aaron Anderson -/ +import Mathlib.Algebra.Order.BigOperators.Group.Finset import Mathlib.Algebra.Order.Module.Defs +import Mathlib.Algebra.Order.Pi import Mathlib.Data.Finsupp.Basic /-! @@ -21,7 +23,7 @@ noncomputable section open Finset -variable {ι α β : Type*} +variable {ι κ α β : Type*} namespace Finsupp @@ -32,6 +34,15 @@ section Zero variable [Zero α] +section OrderedAddCommMonoid +variable [OrderedAddCommMonoid β] {f : ι →₀ α} {h₁ h₂ : ι → α → β} + +@[gcongr] +lemma sum_le_sum (h : ∀ i ∈ f.support, h₁ i (f i) ≤ h₂ i (f i)) : f.sum h₁ ≤ f.sum h₂ := + Finset.sum_le_sum h + +end OrderedAddCommMonoid + section LE variable [LE α] {f g : ι →₀ α} @@ -58,7 +69,7 @@ theorem orderEmbeddingToFun_apply {f : ι →₀ α} {i : ι} : orderEmbeddingTo end LE section Preorder -variable [Preorder α] {f g : ι →₀ α} +variable [Preorder α] {f g : ι →₀ α} {i : ι} {a b : α} instance preorder : Preorder (ι →₀ α) := { Finsupp.instLEFinsupp with @@ -72,6 +83,26 @@ lemma coe_mono : Monotone (Finsupp.toFun : (ι →₀ α) → ι → α) := fun lemma coe_strictMono : Monotone (Finsupp.toFun : (ι →₀ α) → ι → α) := fun _ _ ↦ id +@[simp] lemma single_le_single : single i a ≤ single i b ↔ a ≤ b := by + classical exact Pi.single_le_single + +lemma single_mono : Monotone (single i : α → ι →₀ α) := fun _ _ ↦ single_le_single.2 + +@[gcongr] protected alias ⟨_, GCongr.single_mono⟩ := single_le_single + +@[simp] lemma single_nonneg : 0 ≤ single i a ↔ 0 ≤ a := by classical exact Pi.single_nonneg +@[simp] lemma single_nonpos : single i a ≤ 0 ↔ a ≤ 0 := by classical exact Pi.single_nonpos + +variable [OrderedAddCommMonoid β] + +lemma sum_le_sum_index [DecidableEq ι] {f₁ f₂ : ι →₀ α} {h : ι → α → β} (hf : f₁ ≤ f₂) + (hh : ∀ i ∈ f₁.support ∪ f₂.support, Monotone (h i)) + (hh₀ : ∀ i ∈ f₁.support ∪ f₂.support, h i 0 = 0) : f₁.sum h ≤ f₂.sum h := by + classical + rw [sum_of_support_subset _ Finset.subset_union_left _ hh₀, + sum_of_support_subset _ Finset.subset_union_right _ hh₀] + exact Finset.sum_le_sum fun i hi ↦ hh _ hi <| hf _ + end Preorder instance partialorder [PartialOrder α] : PartialOrder (ι →₀ α) := @@ -117,11 +148,24 @@ end Zero /-! ### Algebraic order structures -/ +section OrderedAddCommMonoid +variable [OrderedAddCommMonoid α] {i : ι} {f : ι → κ} {g g₁ g₂ : ι →₀ α} -instance orderedAddCommMonoid [OrderedAddCommMonoid α] : OrderedAddCommMonoid (ι →₀ α) := +instance orderedAddCommMonoid : OrderedAddCommMonoid (ι →₀ α) := { Finsupp.instAddCommMonoid, Finsupp.partialorder with add_le_add_left := fun _a _b h c s => add_le_add_left (h s) (c s) } +lemma mapDomain_mono : Monotone (mapDomain f : (ι →₀ α) → (κ →₀ α)) := by + classical exact fun g₁ g₂ h ↦ sum_le_sum_index h (fun _ _ ↦ single_mono) (by simp) + +@[gcongr] protected lemma GCongr.mapDomain_mono (hg : g₁ ≤ g₂) : g₁.mapDomain f ≤ g₂.mapDomain f := + mapDomain_mono hg + +lemma mapDomain_nonneg (hg : 0 ≤ g) : 0 ≤ g.mapDomain f := by simpa using mapDomain_mono hg +lemma mapDomain_nonpos (hg : g ≤ 0) : g.mapDomain f ≤ 0 := by simpa using mapDomain_mono hg + +end OrderedAddCommMonoid + instance orderedCancelAddCommMonoid [OrderedCancelAddCommMonoid α] : OrderedCancelAddCommMonoid (ι →₀ α) := { Finsupp.orderedAddCommMonoid with diff --git a/Mathlib/Data/Finsupp/Weight.lean b/Mathlib/Data/Finsupp/Weight.lean index fc57c22790c2d..ed767ee615ac8 100644 --- a/Mathlib/Data/Finsupp/Weight.lean +++ b/Mathlib/Data/Finsupp/Weight.lean @@ -157,7 +157,7 @@ theorem weight_eq_zero_iff_eq_zero ext s simp only [Finsupp.coe_zero, Pi.zero_apply] by_contra hs - apply NonTorsionWeight.ne_zero w _ + apply NonTorsionWeight.ne_zero w s rw [← nonpos_iff_eq_zero, ← h] exact le_weight_of_ne_zero' w hs · intro h diff --git a/Mathlib/Data/Fintype/Basic.lean b/Mathlib/Data/Fintype/Basic.lean index e18eca0fb06df..0ff3b973f0141 100644 --- a/Mathlib/Data/Fintype/Basic.lean +++ b/Mathlib/Data/Fintype/Basic.lean @@ -93,7 +93,7 @@ theorem Nonempty.eq_univ [Subsingleton α] : s.Nonempty → s = univ := by theorem univ_nonempty_iff : (univ : Finset α).Nonempty ↔ Nonempty α := by rw [← coe_nonempty, coe_univ, Set.nonempty_iff_univ_nonempty] -@[aesop unsafe apply (rule_sets := [finsetNonempty])] +@[simp, aesop unsafe apply (rule_sets := [finsetNonempty])] theorem univ_nonempty [Nonempty α] : (univ : Finset α).Nonempty := univ_nonempty_iff.2 ‹_› @@ -492,7 +492,7 @@ This function computes by checking all terms `a : α` to find the `f a = b`, so -/ def invOfMemRange : Set.range f → α := fun b => Finset.choose (fun a => f a = b) Finset.univ - ((existsUnique_congr (by simp)).mp (hf.exists_unique_of_mem_range b.property)) + ((existsUnique_congr (by simp)).mp (hf.existsUnique_of_mem_range b.property)) theorem left_inv_of_invOfMemRange (b : Set.range f) : f (hf.invOfMemRange b) = b := (Finset.choose_spec (fun a => f a = b) _ _).right diff --git a/Mathlib/Data/Fintype/Card.lean b/Mathlib/Data/Fintype/Card.lean index fd8ebbddcb92b..45c0a90562ef5 100644 --- a/Mathlib/Data/Fintype/Card.lean +++ b/Mathlib/Data/Fintype/Card.lean @@ -48,8 +48,6 @@ assert_not_exists MulAction open Function -open Nat - universe u v variable {α β γ : Type*} diff --git a/Mathlib/Data/Fintype/Fin.lean b/Mathlib/Data/Fintype/Fin.lean index 79f88ae3dc5ed..9c66b04ae7c46 100644 --- a/Mathlib/Data/Fintype/Fin.lean +++ b/Mathlib/Data/Fintype/Fin.lean @@ -52,15 +52,14 @@ theorem Iio_castSucc (i : Fin n) : Iio (castSucc i) = (Iio i).map Fin.castSuccEm rw [Finset.map_map, Fin.map_valEmbedding_Iio] exact (Fin.map_valEmbedding_Iio i).symm -theorem card_filter_univ_succ' (p : Fin (n + 1) → Prop) [DecidablePred p] : - (univ.filter p).card = ite (p 0) 1 0 + (univ.filter (p ∘ Fin.succ)).card := by - rw [Fin.univ_succ, filter_cons, card_disjUnion, filter_map, card_map] - split_ifs <;> simp - theorem card_filter_univ_succ (p : Fin (n + 1) → Prop) [DecidablePred p] : (univ.filter p).card = - if p 0 then (univ.filter (p ∘ Fin.succ)).card + 1 else (univ.filter (p ∘ Fin.succ)).card := - (card_filter_univ_succ' p).trans (by split_ifs <;> simp [add_comm 1]) + if p 0 then (univ.filter (p ∘ Fin.succ)).card + 1 else (univ.filter (p ∘ Fin.succ)).card := by + rw [Fin.univ_succ, filter_cons, apply_ite Finset.card, card_cons, filter_map, card_map]; rfl + +theorem card_filter_univ_succ' (p : Fin (n + 1) → Prop) [DecidablePred p] : + (univ.filter p).card = ite (p 0) 1 0 + (univ.filter (p ∘ Fin.succ)).card := by + rw [card_filter_univ_succ]; split_ifs <;> simp [add_comm] theorem card_filter_univ_eq_vector_get_eq_count [DecidableEq α] (a : α) (v : Vector α n) : (univ.filter fun i => v.get i = a).card = v.toList.count a := by diff --git a/Mathlib/Data/Fintype/Lattice.lean b/Mathlib/Data/Fintype/Lattice.lean index 27835fd7979ce..64865d35bb0c7 100644 --- a/Mathlib/Data/Fintype/Lattice.lean +++ b/Mathlib/Data/Fintype/Lattice.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro -/ import Mathlib.Data.Fintype.Card -import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Finset.Max /-! # Lemmas relating fintypes and order/lattice structure. diff --git a/Mathlib/Data/Fintype/Order.lean b/Mathlib/Data/Fintype/Order.lean index 6fa3b6c7e32fd..127472ab51f1d 100644 --- a/Mathlib/Data/Fintype/Order.lean +++ b/Mathlib/Data/Fintype/Order.lean @@ -6,6 +6,7 @@ Authors: Peter Nelson, Yaël Dillies import Mathlib.Data.Finset.Order import Mathlib.Order.Atoms import Mathlib.Data.Set.Finite +import Mathlib.Order.Minimal /-! # Order structures on finite types diff --git a/Mathlib/Data/Fintype/Pi.lean b/Mathlib/Data/Fintype/Pi.lean index 8b57b9e376500..99a88bda7004a 100644 --- a/Mathlib/Data/Fintype/Pi.lean +++ b/Mathlib/Data/Fintype/Pi.lean @@ -49,12 +49,13 @@ theorem piFinset_subset (t₁ t₂ : ∀ a, Finset (δ a)) (h : ∀ a, t₁ a piFinset t₁ ⊆ piFinset t₂ := fun _ hg => mem_piFinset.2 fun a => h a <| mem_piFinset.1 hg a @[simp] -theorem piFinset_empty [Nonempty α] : piFinset (fun _ => ∅ : ∀ i, Finset (δ i)) = ∅ := - eq_empty_of_forall_not_mem fun _ => by simp +theorem piFinset_eq_empty : piFinset s = ∅ ↔ ∃ i, s i = ∅ := by simp [piFinset] @[simp] -lemma piFinset_nonempty : (piFinset s).Nonempty ↔ ∀ a, (s a).Nonempty := by - simp [Finset.Nonempty, Classical.skolem] +theorem piFinset_empty [Nonempty α] : piFinset (fun _ => ∅ : ∀ i, Finset (δ i)) = ∅ := by simp + +@[simp] +lemma piFinset_nonempty : (piFinset s).Nonempty ↔ ∀ a, (s a).Nonempty := by simp [piFinset] @[aesop safe apply (rule_sets := [finsetNonempty])] alias ⟨_, Aesop.piFinset_nonempty_of_forall_nonempty⟩ := piFinset_nonempty diff --git a/Mathlib/Data/Fintype/Prod.lean b/Mathlib/Data/Fintype/Prod.lean index 0d91984495e7f..2a5dfcdbbbf59 100644 --- a/Mathlib/Data/Fintype/Prod.lean +++ b/Mathlib/Data/Fintype/Prod.lean @@ -14,8 +14,6 @@ import Mathlib.Data.Finset.Prod open Function -open Nat - universe u v variable {α β γ : Type*} diff --git a/Mathlib/Data/Fintype/Sigma.lean b/Mathlib/Data/Fintype/Sigma.lean index 64f8de8f89ab0..6827beb23b927 100644 --- a/Mathlib/Data/Fintype/Sigma.lean +++ b/Mathlib/Data/Fintype/Sigma.lean @@ -17,7 +17,7 @@ open Nat universe u v -variable {ι α β γ : Type*} {κ : ι → Type*} [Π i, Fintype (κ i)] +variable {ι α : Type*} {κ : ι → Type*} [Π i, Fintype (κ i)] open Finset Function diff --git a/Mathlib/Data/FunLike/Basic.lean b/Mathlib/Data/FunLike/Basic.lean index f23481b549544..3a04435a85ca6 100644 --- a/Mathlib/Data/FunLike/Basic.lean +++ b/Mathlib/Data/FunLike/Basic.lean @@ -17,7 +17,7 @@ There is the "D"ependent version `DFunLike` and the non-dependent version `FunLi A typical type of morphisms should be declared as: ``` -structure MyHom (A B : Type*) [MyClass A] [MyClass B] := +structure MyHom (A B : Type*) [MyClass A] [MyClass B] where (toFun : A → B) (map_op' : ∀ (x y : A), toFun (MyClass.op x y) = MyClass.op (toFun x) (toFun y)) @@ -79,7 +79,7 @@ The second step is to add instances of your new `MyHomClass` for all types exten Typically, you can just declare a new class analogous to `MyHomClass`: ``` -structure CoolerHom (A B : Type*) [CoolClass A] [CoolClass B] extends MyHom A B := +structure CoolerHom (A B : Type*) [CoolClass A] [CoolClass B] extends MyHom A B where (map_cool' : toFun CoolClass.cool = CoolClass.cool) class CoolerHomClass (F : Type*) (A B : outParam Type*) [CoolClass A] [CoolClass B] diff --git a/Mathlib/Data/FunLike/Embedding.lean b/Mathlib/Data/FunLike/Embedding.lean index b65a26da5cc05..a8551af72e079 100644 --- a/Mathlib/Data/FunLike/Embedding.lean +++ b/Mathlib/Data/FunLike/Embedding.lean @@ -14,7 +14,7 @@ This typeclass is primarily for use by embeddings such as `RelEmbedding`. A typical type of embeddings should be declared as: ``` -structure MyEmbedding (A B : Type*) [MyClass A] [MyClass B] := +structure MyEmbedding (A B : Type*) [MyClass A] [MyClass B] where (toFun : A → B) (injective' : Function.Injective toFun) (map_op' : ∀ (x y : A), toFun (MyClass.op x y) = MyClass.op (toFun x) (toFun y)) @@ -58,8 +58,8 @@ Continuing the example above: You should extend this class when you extend `MyEmbedding`. -/ class MyEmbeddingClass (F : Type*) (A B : outParam Type*) [MyClass A] [MyClass B] [FunLike F A B] - extends EmbeddingLike F A B := - (map_op : ∀ (f : F) (x y : A), f (MyClass.op x y) = MyClass.op (f x) (f y)) + extends EmbeddingLike F A B where + 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] [FunLike F A B] [MyEmbeddingClass F A B] @@ -84,12 +84,12 @@ The second step is to add instances of your new `MyEmbeddingClass` for all types Typically, you can just declare a new class analogous to `MyEmbeddingClass`: ``` -structure CoolerEmbedding (A B : Type*) [CoolClass A] [CoolClass B] extends MyEmbedding A B := +structure CoolerEmbedding (A B : Type*) [CoolClass A] [CoolClass B] extends MyEmbedding A B where (map_cool' : toFun CoolClass.cool = CoolClass.cool) class CoolerEmbeddingClass (F : Type*) (A B : outParam Type*) [CoolClass A] [CoolClass B] [FunLike F A B] - extends MyEmbeddingClass F A B := + extends MyEmbeddingClass F A B where (map_cool : ∀ (f : F), f CoolClass.cool = CoolClass.cool) @[simp] diff --git a/Mathlib/Data/FunLike/Equiv.lean b/Mathlib/Data/FunLike/Equiv.lean index d2a640eddc593..92881dc5ec3a9 100644 --- a/Mathlib/Data/FunLike/Equiv.lean +++ b/Mathlib/Data/FunLike/Equiv.lean @@ -14,7 +14,7 @@ This typeclass is primarily for use by isomorphisms like `MonoidEquiv` and `Line A typical type of isomorphisms should be declared as: ``` -structure MyIso (A B : Type*) [MyClass A] [MyClass B] extends Equiv A B := +structure MyIso (A B : Type*) [MyClass A] [MyClass B] extends Equiv A B where (map_op' : ∀ (x y : A), toFun (MyClass.op x y) = MyClass.op (toFun x) (toFun y)) namespace MyIso @@ -77,12 +77,12 @@ The second step is to add instances of your new `MyIsoClass` for all types exten Typically, you can just declare a new class analogous to `MyIsoClass`: ``` -structure CoolerIso (A B : Type*) [CoolClass A] [CoolClass B] extends MyIso A B := +structure CoolerIso (A B : Type*) [CoolClass A] [CoolClass B] extends MyIso A B where (map_cool' : toFun CoolClass.cool = CoolClass.cool) class CoolerIsoClass (F : Type*) (A B : outParam Type*) [CoolClass A] [CoolClass B] [EquivLike F A B] - extends MyIsoClass F A B := + extends MyIsoClass F A B where (map_cool : ∀ (f : F), f CoolClass.cool = CoolClass.cool) @[simp] lemma map_cool {F A B : Type*} [CoolClass A] [CoolClass B] diff --git a/Mathlib/Data/Holor.lean b/Mathlib/Data/Holor.lean index d51140bf97ce3..b7fc524917add 100644 --- a/Mathlib/Data/Holor.lean +++ b/Mathlib/Data/Holor.lean @@ -181,9 +181,9 @@ theorem slice_eq (x : Holor α (d :: ds)) (y : Holor α (d :: ds)) (h : slice x have hid : i < d := (forall₂_cons.1 hiisdds).1 have hisds : Forall₂ (· < ·) is ds := (forall₂_cons.1 hiisdds).2 calc - x ⟨i :: is, _⟩ = slice x i hid ⟨is, hisds⟩ := congr_arg (fun t => x t) (Subtype.eq rfl) + x ⟨i :: is, _⟩ = slice x i hid ⟨is, hisds⟩ := congr_arg x (Subtype.eq rfl) _ = slice y i hid ⟨is, hisds⟩ := by rw [h] - _ = y ⟨i :: is, _⟩ := congr_arg (fun t => y t) (Subtype.eq rfl) + _ = y ⟨i :: is, _⟩ := congr_arg y (Subtype.eq rfl) theorem slice_unitVec_mul [Ring α] {i : ℕ} {j : ℕ} (hid : i < d) (x : Holor α ds) : slice (unitVec d j ⊗ x) i hid = if i = j then x else 0 := diff --git a/Mathlib/Data/Int/CardIntervalMod.lean b/Mathlib/Data/Int/CardIntervalMod.lean index 045f7ee4c7aa8..b5725e3f43eb6 100644 --- a/Mathlib/Data/Int/CardIntervalMod.lean +++ b/Mathlib/Data/Int/CardIntervalMod.lean @@ -43,14 +43,14 @@ include hr lemma Ico_filter_dvd_eq : (Ico a b).filter (r ∣ ·) = (Ico ⌈a / (r : ℚ)⌉ ⌈b / (r : ℚ)⌉).map ⟨(· * r), mul_left_injective₀ hr.ne'⟩ := by ext x - simp only [mem_map, mem_filter, mem_Ico, ceil_le, lt_ceil, div_le_iff₀, lt_div_iff, + simp only [mem_map, mem_filter, mem_Ico, ceil_le, lt_ceil, div_le_iff₀, lt_div_iff₀, dvd_iff_exists_eq_mul_left, cast_pos.2 hr, ← cast_mul, cast_lt, cast_le] aesop lemma Ioc_filter_dvd_eq : (Ioc a b).filter (r ∣ ·) = (Ioc ⌊a / (r : ℚ)⌋ ⌊b / (r : ℚ)⌋).map ⟨(· * r), mul_left_injective₀ hr.ne'⟩ := by ext x - simp only [mem_map, mem_filter, mem_Ioc, floor_lt, le_floor, div_lt_iff, le_div_iff₀, + simp only [mem_map, mem_filter, mem_Ioc, floor_lt, le_floor, div_lt_iff₀, le_div_iff₀, dvd_iff_exists_eq_mul_left, cast_pos.2 hr, ← cast_mul, cast_lt, cast_le] aesop @@ -125,7 +125,7 @@ theorem count_modEq_card_eq_ceil (v : ℕ) : rw [← div_add_mod v r, cast_add, cast_mul, add_comm] tactic => simp_rw [← sub_sub, sub_div (_ - _), mul_div_cancel_left₀ _ hr'.ne', ceil_sub_nat] rw [sub_sub_sub_cancel_right, cast_zero, zero_sub] - rw [sub_eq_self, ceil_eq_zero_iff, Set.mem_Ioc, div_le_iff₀ hr', lt_div_iff hr', neg_one_mul, + rw [sub_eq_self, ceil_eq_zero_iff, Set.mem_Ioc, div_le_iff₀ hr', lt_div_iff₀ hr', neg_one_mul, zero_mul, neg_lt_neg_iff, cast_lt] exact ⟨mod_lt _ hr, by simp⟩ @@ -139,10 +139,10 @@ theorem count_modEq_card (v : ℕ) : mul_div_cancel_left₀ _ hr'.ne', add_comm, Int.ceil_add_nat, add_comm] rw [add_right_inj] split_ifs with h - · rw [← cast_sub h.le, Int.ceil_eq_iff, div_le_iff₀ hr', lt_div_iff hr', cast_one, Int.cast_one, + · rw [← cast_sub h.le, Int.ceil_eq_iff, div_le_iff₀ hr', lt_div_iff₀ hr', cast_one, Int.cast_one, sub_self, zero_mul, cast_pos, tsub_pos_iff_lt, one_mul, cast_le, tsub_le_iff_right] exact ⟨h, ((mod_lt _ hr).trans_le (by simp)).le⟩ - · rw [cast_zero, ceil_eq_zero_iff, Set.mem_Ioc, div_le_iff₀ hr', lt_div_iff hr', zero_mul, + · rw [cast_zero, ceil_eq_zero_iff, Set.mem_Ioc, div_le_iff₀ hr', lt_div_iff₀ hr', zero_mul, tsub_nonpos, ← neg_eq_neg_one_mul, neg_lt_sub_iff_lt_add, ← cast_add, cast_lt, cast_le] exact ⟨(mod_lt _ hr).trans_le (by simp), not_lt.mp h⟩ diff --git a/Mathlib/Data/Int/Defs.lean b/Mathlib/Data/Int/Defs.lean index b5619f8bcea08..6bf06c9ff023a 100644 --- a/Mathlib/Data/Int/Defs.lean +++ b/Mathlib/Data/Int/Defs.lean @@ -30,7 +30,6 @@ namespace Int variable {a b c d m n : ℤ} section Order -variable {a b c : ℤ} protected lemma le_rfl : a ≤ a := a.le_refl protected lemma lt_or_lt_of_ne : a ≠ b → a < b ∨ b < a := Int.lt_or_gt_of_ne @@ -43,6 +42,7 @@ protected lemma le_antisymm_iff : a = b ↔ a ≤ b ∧ b ≤ a := ⟨fun h ↦ ⟨Int.le_of_eq h, Int.ge_of_eq h⟩, fun h ↦ Int.le_antisymm h.1 h.2⟩ protected lemma le_iff_eq_or_lt : a ≤ b ↔ a = b ∨ a < b := by rw [Int.le_antisymm_iff, Int.lt_iff_le_not_le, ← and_or_left]; simp [em] + protected lemma le_iff_lt_or_eq : a ≤ b ↔ a < b ∨ a = b := by rw [Int.le_iff_eq_or_lt, or_comm] end Order diff --git a/Mathlib/Data/Int/DivMod.lean b/Mathlib/Data/Int/DivMod.lean new file mode 100644 index 0000000000000..e2d8db47293a8 --- /dev/null +++ b/Mathlib/Data/Int/DivMod.lean @@ -0,0 +1,20 @@ +/- +Copyright (c) 2024 Lean FRO. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kim Morrison +-/ + +/-! +# Basic lemmas about division and modulo for integers + +-/ + +namespace Int + +/-! ### `emod` -/ + +theorem emod_eq_sub_self_emod {a b : Int} : a % b = (a - b) % b := + (emod_sub_cancel a b).symm + +theorem emod_eq_add_self_emod {a b : Int} : a % b = (a + b) % b := + add_emod_self.symm diff --git a/Mathlib/Data/Int/GCD.lean b/Mathlib/Data/Int/GCD.lean index 6c4e2b4ad9ed9..eccc02d840c40 100644 --- a/Mathlib/Data/Int/GCD.lean +++ b/Mathlib/Data/Int/GCD.lean @@ -7,7 +7,9 @@ import Mathlib.Algebra.Group.Int import Mathlib.Algebra.GroupWithZero.Semiconj import Mathlib.Algebra.Group.Commute.Units import Mathlib.Data.Nat.GCD.Basic -import Mathlib.Order.Bounds.Basic +import Mathlib.Order.Lattice +import Mathlib.Data.Set.Operations +import Mathlib.Order.Bounds.Defs /-! # Extended GCD and divisibility over ℤ diff --git a/Mathlib/Data/Int/Lemmas.lean b/Mathlib/Data/Int/Lemmas.lean index 9300c6b89865c..61ccb22c02adb 100644 --- a/Mathlib/Data/Int/Lemmas.lean +++ b/Mathlib/Data/Int/Lemmas.lean @@ -6,6 +6,7 @@ Authors: Jeremy Avigad import Mathlib.Data.Int.Bitwise import Mathlib.Data.Int.Order.Lemmas import Mathlib.Data.Set.Function +import Mathlib.Data.Set.Monotone import Mathlib.Order.Interval.Set.Basic /-! diff --git a/Mathlib/Data/Int/Log.lean b/Mathlib/Data/Int/Log.lean index 8d9efb0ac2af0..e6f5f9f457159 100644 --- a/Mathlib/Data/Int/Log.lean +++ b/Mathlib/Data/Int/Log.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Algebra.Order.Floor -import Mathlib.Algebra.Order.Field.Power import Mathlib.Data.Nat.Log /-! @@ -94,7 +93,7 @@ theorem zpow_log_le_self {b : ℕ} {r : R} (hb : 1 < b) (hr : 0 < r) : (b : R) ^ rw [zpow_natCast, ← Nat.cast_pow, ← Nat.le_floor_iff hr.le] exact Nat.pow_log_le_self b (Nat.floor_pos.mpr hr1).ne' · rw [log_of_right_le_one _ hr1, zpow_neg, zpow_natCast, ← Nat.cast_pow] - exact inv_le_of_inv_le hr (Nat.ceil_le.1 <| Nat.le_pow_clog hb _) + exact inv_le_of_inv_le₀ hr (Nat.ceil_le.1 <| Nat.le_pow_clog hb _) theorem lt_zpow_succ_log_self {b : ℕ} (hb : 1 < b) (r : R) : r < (b : R) ^ (log b r + 1) := by rcases le_or_lt r 0 with hr | hr @@ -106,11 +105,11 @@ theorem lt_zpow_succ_log_self {b : ℕ} (hb : 1 < b) (r : R) : r < (b : R) ^ (lo apply Nat.lt_of_floor_lt exact Nat.lt_pow_succ_log_self hb _ · rw [log_of_right_le_one _ hr1.le] - have hcri : 1 < r⁻¹ := one_lt_inv hr hr1 + have hcri : 1 < r⁻¹ := (one_lt_inv₀ hr).2 hr1 have : 1 ≤ Nat.clog b ⌈r⁻¹⌉₊ := Nat.succ_le_of_lt (Nat.clog_pos hb <| Nat.one_lt_cast.1 <| hcri.trans_le (Nat.le_ceil _)) rw [neg_add_eq_sub, ← neg_sub, ← Int.ofNat_one, ← Int.ofNat_sub this, zpow_neg, zpow_natCast, - lt_inv hr (pow_pos (Nat.cast_pos.mpr <| zero_lt_one.trans hb) _), ← Nat.cast_pow] + lt_inv_comm₀ hr (pow_pos (Nat.cast_pos.mpr <| zero_lt_one.trans hb) _), ← Nat.cast_pow] refine Nat.lt_ceil.1 ?_ exact Nat.pow_pred_clog_lt_self hb <| Nat.one_lt_cast.1 <| hcri.trans_le <| Nat.le_ceil _ @@ -135,18 +134,17 @@ theorem log_one_left (r : R) : log 1 r = 0 := by -- Porting note: needed to replace b ^ z with (b : R) ^ z in the below theorem log_zpow {b : ℕ} (hb : 1 < b) (z : ℤ) : log b ((b : R) ^ z : R) = z := by obtain ⟨n, rfl | rfl⟩ := Int.eq_nat_or_neg z - · rw [log_of_one_le_right _ (one_le_zpow_of_nonneg _ <| Int.natCast_nonneg _), zpow_natCast, ← - Nat.cast_pow, Nat.floor_natCast, Nat.log_pow hb] - exact mod_cast hb.le - · rw [log_of_right_le_one _ (zpow_le_one_of_nonpos _ <| neg_nonpos.mpr (Int.natCast_nonneg _)), + · rw [log_of_one_le_right _ (one_le_zpow₀ (mod_cast hb.le) <| Int.natCast_nonneg _), zpow_natCast, + ← Nat.cast_pow, Nat.floor_natCast, Nat.log_pow hb] + · rw [log_of_right_le_one _ (zpow_le_one_of_nonpos₀ (mod_cast hb.le) <| + neg_nonpos.2 (Int.natCast_nonneg _)), zpow_neg, inv_inv, zpow_natCast, ← Nat.cast_pow, Nat.ceil_natCast, Nat.clog_pow _ _ hb] - exact mod_cast hb.le @[mono] theorem log_mono_right {b : ℕ} {r₁ r₂ : R} (h₀ : 0 < r₁) (h : r₁ ≤ r₂) : log b r₁ ≤ log b r₂ := by rcases le_total r₁ 1 with h₁ | h₁ <;> rcases le_total r₂ 1 with h₂ | h₂ · rw [log_of_right_le_one _ h₁, log_of_right_le_one _ h₂, neg_le_neg_iff, Int.ofNat_le] - exact Nat.clog_mono_right _ (Nat.ceil_mono <| inv_le_inv_of_le h₀ h) + exact Nat.clog_mono_right _ (Nat.ceil_mono <| inv_anti₀ h₀ h) · rw [log_of_right_le_one _ h₁, log_of_one_le_right _ h₂] exact (neg_nonpos.mpr (Int.natCast_nonneg _)).trans (Int.natCast_nonneg _) · obtain rfl := le_antisymm h (h₂.trans h₁) @@ -160,10 +158,10 @@ variable (R) def zpowLogGi {b : ℕ} (hb : 1 < b) : GaloisCoinsertion (fun z : ℤ => - Subtype.mk ((b : R) ^ z) <| zpow_pos_of_pos (mod_cast zero_lt_one.trans hb) z) + Subtype.mk ((b : R) ^ z) <| zpow_pos (mod_cast zero_lt_one.trans hb) z) fun r : Set.Ioi (0 : R) => Int.log b (r : R) := GaloisCoinsertion.monotoneIntro (fun r₁ _ => log_mono_right r₁.2) - (fun _ _ hz => Subtype.coe_le_coe.mp <| (zpow_strictMono <| mod_cast hb).monotone hz) + (fun _ _ hz => Subtype.coe_le_coe.mp <| (zpow_right_strictMono₀ <| mod_cast hb).monotone hz) (fun r => Subtype.coe_le_coe.mp <| zpow_log_le_self hb r.2) fun _ => log_zpow (R := R) hb _ variable {R} @@ -203,8 +201,8 @@ theorem clog_of_right_le_zero (b : ℕ) {r : R} (hr : r ≤ 0) : clog b r = 0 := theorem clog_inv (b : ℕ) (r : R) : clog b r⁻¹ = -log b r := by cases' lt_or_le 0 r with hrp hrp · obtain hr | hr := le_total 1 r - · rw [clog_of_right_le_one _ (inv_le_one hr), log_of_one_le_right _ hr, inv_inv] - · rw [clog_of_one_le_right _ (one_le_inv hrp hr), log_of_right_le_one _ hr, neg_neg] + · rw [clog_of_right_le_one _ (inv_le_one_of_one_le₀ hr), log_of_one_le_right _ hr, inv_inv] + · rw [clog_of_one_le_right _ ((one_le_inv₀ hrp).2 hr), log_of_right_le_one _ hr, neg_neg] · rw [clog_of_right_le_zero _ (inv_nonpos.mpr hrp), log_of_right_le_zero _ hrp, neg_zero] @[simp] @@ -235,15 +233,15 @@ theorem self_le_zpow_clog {b : ℕ} (hb : 1 < b) (r : R) : r ≤ (b : R) ^ clog rcases le_or_lt r 0 with hr | hr · rw [clog_of_right_le_zero _ hr, zpow_zero] exact hr.trans zero_le_one - rw [← neg_log_inv_eq_clog, zpow_neg, le_inv hr (zpow_pos_of_pos _ _)] + rw [← neg_log_inv_eq_clog, zpow_neg, le_inv_comm₀ hr (zpow_pos ..)] · exact zpow_log_le_self hb (inv_pos.mpr hr) · exact Nat.cast_pos.mpr (zero_le_one.trans_lt hb) theorem zpow_pred_clog_lt_self {b : ℕ} {r : R} (hb : 1 < b) (hr : 0 < r) : (b : R) ^ (clog b r - 1) < r := by - rw [← neg_log_inv_eq_clog, ← neg_add', zpow_neg, inv_lt _ hr] + rw [← neg_log_inv_eq_clog, ← neg_add', zpow_neg, inv_lt_comm₀ _ hr] · exact lt_zpow_succ_log_self hb _ - · exact zpow_pos_of_pos (Nat.cast_pos.mpr <| zero_le_one.trans_lt hb) _ + · exact zpow_pos (Nat.cast_pos.mpr <| zero_le_one.trans_lt hb) _ @[simp] theorem clog_zero_right (b : ℕ) : clog b (0 : R) = 0 := @@ -271,16 +269,16 @@ theorem clog_zpow {b : ℕ} (hb : 1 < b) (z : ℤ) : clog b ((b : R) ^ z : R) = theorem clog_mono_right {b : ℕ} {r₁ r₂ : R} (h₀ : 0 < r₁) (h : r₁ ≤ r₂) : clog b r₁ ≤ clog b r₂ := by rw [← neg_log_inv_eq_clog, ← neg_log_inv_eq_clog, neg_le_neg_iff] - exact log_mono_right (inv_pos.mpr <| h₀.trans_le h) (inv_le_inv_of_le h₀ h) + exact log_mono_right (inv_pos.mpr <| h₀.trans_le h) (inv_anti₀ h₀ h) variable (R) /-- Over suitable subtypes, `Int.clog` and `zpow` form a galois insertion -/ def clogZPowGi {b : ℕ} (hb : 1 < b) : GaloisInsertion (fun r : Set.Ioi (0 : R) => Int.clog b (r : R)) fun z : ℤ => - ⟨(b : R) ^ z, zpow_pos_of_pos (mod_cast zero_lt_one.trans hb) z⟩ := + ⟨(b : R) ^ z, zpow_pos (mod_cast zero_lt_one.trans hb) z⟩ := GaloisInsertion.monotoneIntro - (fun _ _ hz => Subtype.coe_le_coe.mp <| (zpow_strictMono <| mod_cast hb).monotone hz) + (fun _ _ hz => Subtype.coe_le_coe.mp <| (zpow_right_strictMono₀ <| mod_cast hb).monotone hz) (fun r₁ _ => clog_mono_right r₁.2) (fun _ => Subtype.coe_le_coe.mp <| self_le_zpow_clog hb _) fun _ => clog_zpow (R := R) hb _ diff --git a/Mathlib/Data/Int/ModEq.lean b/Mathlib/Data/Int/ModEq.lean index 2f973a2e81d79..d171639d57b4d 100644 --- a/Mathlib/Data/Int/ModEq.lean +++ b/Mathlib/Data/Int/ModEq.lean @@ -4,8 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.Data.Nat.ModEq -import Mathlib.Tactic.Abel -import Mathlib.Tactic.GCongr.CoreAttrs /-! @@ -92,8 +90,7 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] := @[simp] theorem neg_modEq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] := by --- Porting note: Restore old proof once #3309 is through - simp [-sub_neg_eq_add, neg_sub_neg, modEq_iff_dvd, dvd_sub_comm] + simp only [modEq_iff_dvd, (by omega : -b - -a = -(b - a)), Int.dvd_neg] @[simp] theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modEq_iff_dvd] @@ -105,9 +102,9 @@ protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] := by obtain hc | rfl | hc := lt_trichotomy c 0 - · rw [← neg_modEq_neg, ← modEq_neg, ← neg_mul, ← neg_mul, ← neg_mul] + · rw [← neg_modEq_neg, ← modEq_neg, ← Int.neg_mul, ← Int.neg_mul, ← Int.neg_mul] simp only [ModEq, mul_emod_mul_of_pos _ _ (neg_pos.2 hc), h.eq] - · simp only [zero_mul, ModEq.rfl] + · simp only [Int.zero_mul, ModEq.rfl] · simp only [ModEq, mul_emod_mul_of_pos _ _ hc, h.eq] protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by @@ -115,7 +112,7 @@ protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * @[gcongr] protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] := - modEq_iff_dvd.2 <| by convert dvd_add h₁.dvd h₂.dvd using 1; abel + modEq_iff_dvd.2 <| by convert Int.dvd_add h₁.dvd h₂.dvd using 1; omega @[gcongr] protected theorem add_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c + a ≡ c + b [ZMOD n] := ModEq.rfl.add h @@ -125,10 +122,10 @@ protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + protected theorem add_left_cancel (h₁ : a ≡ b [ZMOD n]) (h₂ : a + c ≡ b + d [ZMOD n]) : c ≡ d [ZMOD n] := - have : d - c = b + d - (a + c) - (b - a) := by abel + have : d - c = b + d - (a + c) - (b - a) := by omega modEq_iff_dvd.2 <| by rw [this] - exact dvd_sub h₂.dvd h₁.dvd + exact Int.dvd_sub h₂.dvd h₁.dvd protected theorem add_left_cancel' (c : ℤ) (h : c + a ≡ c + b [ZMOD n]) : a ≡ b [ZMOD n] := ModEq.rfl.add_left_cancel h @@ -183,7 +180,7 @@ theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : 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) gcd_dvd_right, sub_mul] + · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) gcd_dvd_right, Int.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')] @@ -233,7 +230,7 @@ theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n * _ ≡ b [ZMOD n] := by rw [add_zero] theorem modEq_sub_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a - n * c ≡ b [ZMOD n] := by - convert Int.modEq_add_fac (-c) ha using 1; rw [mul_neg, sub_eq_add_neg] + convert Int.modEq_add_fac (-c) ha using 1; rw [Int.mul_neg, sub_eq_add_neg] theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] := modEq_add_fac _ ModEq.rfl diff --git a/Mathlib/Data/Int/Order/Lemmas.lean b/Mathlib/Data/Int/Order/Lemmas.lean index e7bc9e148fc42..d664a5b284aca 100644 --- a/Mathlib/Data/Int/Order/Lemmas.lean +++ b/Mathlib/Data/Int/Order/Lemmas.lean @@ -34,15 +34,4 @@ theorem natAbs_le_iff_mul_self_le {a b : ℤ} : a.natAbs ≤ b.natAbs ↔ a * a rw [← abs_le_iff_mul_self_le, abs_eq_natAbs, abs_eq_natAbs] exact Int.ofNat_le.symm -/-! ### units -/ - - -theorem eq_zero_of_abs_lt_dvd {m x : ℤ} (h1 : m ∣ x) (h2 : |x| < m) : x = 0 := by - obtain rfl | hm := eq_or_ne m 0 - · exact Int.zero_dvd.1 h1 - rcases h1 with ⟨d, rfl⟩ - apply mul_eq_zero_of_right - rw [← abs_lt_one_iff, ← mul_lt_iff_lt_one_right (abs_pos.mpr hm), ← abs_mul] - exact lt_of_lt_of_le h2 (le_abs_self m) - end Int diff --git a/Mathlib/Data/Int/WithZero.lean b/Mathlib/Data/Int/WithZero.lean new file mode 100644 index 0000000000000..ec6f9a4c79ab0 --- /dev/null +++ b/Mathlib/Data/Int/WithZero.lean @@ -0,0 +1,91 @@ +/- +Copyright (c) 2024 María Inés de Frutos-Fernández, Filippo A. E. Nuccio. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: María Inés de Frutos-Fernández, Filippo A. E. Nuccio +-/ +import Mathlib.Data.NNReal.Basic + +/-! +# WithZero + +In this file we provide some basic API lemmas for the `WithZero` construction and we define +the morphism `WithZeroMultInt.toNNReal`. + +## Main Definitions + +* `WithZeroMultInt.toNNReal` : The `MonoidWithZeroHom` from `ℤₘ₀ → ℝ≥0` sending `0 ↦ 0` and + `x ↦ e^(Multiplicative.toAdd (WithZero.unzero hx)` when `x ≠ 0`, for a nonzero `e : ℝ≥0`. + +## Main Results + +* `WithZeroMultInt.toNNReal_strictMono` : The map `withZeroMultIntToNNReal` is strictly + monotone whenever `1 < e`. + +## Tags + +WithZero, multiplicative, nnreal +-/ + +noncomputable section + +open scoped NNReal + +open Multiplicative WithZero + +namespace WithZeroMulInt + +/-- Given a nonzero `e : ℝ≥0`, this is the map `ℤₘ₀ → ℝ≥0` sending `0 ↦ 0` and + `x ↦ e^(Multiplicative.toAdd (WithZero.unzero hx)` when `x ≠ 0` as a `MonoidWithZeroHom`. -/ +def toNNReal {e : NNReal} (he : e ≠ 0) : ℤₘ₀ →*₀ ℝ≥0 where + toFun := fun x ↦ if hx : x = 0 then 0 else e ^ Multiplicative.toAdd (WithZero.unzero hx) + map_zero' := rfl + map_one' := by + simp only [dif_neg one_ne_zero] + erw [toAdd_one, zpow_zero] + map_mul' x y := by + simp only + by_cases hxy : x * y = 0 + · cases' zero_eq_mul.mp (Eq.symm hxy) with hx hy + --either x = 0 or y = 0 + · rw [dif_pos hxy, dif_pos hx, MulZeroClass.zero_mul] + · rw [dif_pos hxy, dif_pos hy, MulZeroClass.mul_zero] + · cases' mul_ne_zero_iff.mp hxy with hx hy + -- x Equiv≠ 0 and y ≠ 0 + rw [dif_neg hxy, dif_neg hx, dif_neg hy, ← zpow_add' (Or.inl he), ← toAdd_mul] + congr + rw [← WithZero.coe_inj, WithZero.coe_mul, coe_unzero hx, coe_unzero hy, coe_unzero hxy] + +theorem toNNReal_pos_apply {e : NNReal} (he : e ≠ 0) {x : ℤₘ₀} (hx : x = 0) : + toNNReal he x = 0 := by + simp only [toNNReal, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk] + split_ifs; rfl + +theorem toNNReal_neg_apply {e : NNReal} (he : e ≠ 0) {x : ℤₘ₀} (hx : x ≠ 0) : + toNNReal he x = e ^ Multiplicative.toAdd (WithZero.unzero hx) := by + simp only [toNNReal, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk] + split_ifs + · tauto + · rfl + +/-- `toNNReal` sends nonzero elements to nonzero elements. -/ +theorem toNNReal_ne_zero {e : NNReal} {m : ℤₘ₀} (he : e ≠ 0) (hm : m ≠ 0) : toNNReal he m ≠ 0 := by + simp only [ne_eq, map_eq_zero, hm, not_false_eq_true] + +/-- `toNNReal` sends nonzero elements to positive elements. -/ +theorem toNNReal_pos {e : NNReal} {m : ℤₘ₀} (he : e ≠ 0) (hm : m ≠ 0) : 0 < toNNReal he m := + lt_of_le_of_ne zero_le' (toNNReal_ne_zero he hm).symm + +/-- The map `toNNReal` is strictly monotone whenever `1 < e`. -/ +theorem toNNReal_strictMono {e : NNReal} (he : 1 < e) : + StrictMono (toNNReal (ne_zero_of_lt he)) := by + intro x y hxy + simp only [toNNReal, MonoidWithZeroHom.coe_mk, ZeroHom.coe_mk] + split_ifs with hx hy hy + · simp only [hy, not_lt_zero'] at hxy + · exact zpow_pos he.bot_lt _ + · simp only [hy, not_lt_zero'] at hxy + · rw [zpow_lt_zpow_iff_right₀ he, Multiplicative.toAdd_lt, ← coe_lt_coe, coe_unzero hx, + WithZero.coe_unzero hy] + exact hxy + +end WithZeroMulInt diff --git a/Mathlib/Data/List/Basic.lean b/Mathlib/Data/List/Basic.lean index c239c183abaad..267f3bbefd34e 100644 --- a/Mathlib/Data/List/Basic.lean +++ b/Mathlib/Data/List/Basic.lean @@ -3,6 +3,7 @@ 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.Control.Basic import Mathlib.Data.Nat.Defs import Mathlib.Data.Option.Basic import Mathlib.Data.List.Defs @@ -35,8 +36,6 @@ variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {l₁ l₂ : Lis @[deprecated (since := "2024-07-27")] theorem le_eq_not_gt [LT α] : ∀ l₁ l₂ : List α, (l₁ ≤ l₂) = ¬l₂ < l₁ := fun _ _ => rfl -@[deprecated (since := "2024-06-07")] alias toArray_data := Array.data_toArray - -- Porting note: Delete this attribute -- attribute [inline] List.head! @@ -59,9 +58,6 @@ instance : Std.Associative (α := List α) Append.append where theorem singleton_injective : Injective fun a : α => [a] := fun _ _ h => (cons_eq_cons.1 h).1 -theorem singleton_inj {a b : α} : [a] = [b] ↔ a = b := - singleton_injective.eq_iff - theorem set_of_mem_cons (l : List α) (a : α) : { x | x ∈ a :: l } = insert a { x | x ∈ l } := Set.ext fun _ => mem_cons @@ -199,10 +195,6 @@ theorem map_subset_iff {l₁ l₂ : List α} (f : α → β) (h : Injective f) : theorem append_eq_has_append {L₁ L₂ : List α} : List.append L₁ L₂ = L₁ ++ L₂ := rfl -@[deprecated (since := "2024-03-24")] alias append_eq_cons_iff := append_eq_cons - -@[deprecated (since := "2024-03-24")] alias cons_eq_append_iff := cons_eq_append - @[deprecated (since := "2024-01-18")] alias append_left_cancel := append_cancel_left @[deprecated (since := "2024-01-18")] alias append_right_cancel := append_cancel_right @@ -229,10 +221,10 @@ theorem replicate_subset_singleton (n) (a : α) : replicate n a ⊆ [a] := fun _ mem_singleton.2 (eq_of_mem_replicate h) theorem subset_singleton_iff {a : α} {L : List α} : L ⊆ [a] ↔ ∃ n, L = replicate n a := by - simp only [eq_replicate, subset_def, mem_singleton, exists_eq_left'] + simp only [eq_replicate_iff, subset_def, mem_singleton, exists_eq_left'] theorem replicate_right_injective {n : ℕ} (hn : n ≠ 0) : Injective (@replicate α n) := - fun _ _ h => (eq_replicate.1 h).2 _ <| mem_replicate.2 ⟨hn, rfl⟩ + fun _ _ h => (eq_replicate_iff.1 h).2 _ <| mem_replicate.2 ⟨hn, rfl⟩ theorem replicate_right_inj {a b : α} {n : ℕ} (hn : n ≠ 0) : replicate n a = replicate n b ↔ a = b := @@ -360,21 +352,10 @@ lemma getLast_filter {p : α → Bool} : /-! ### getLast? -/ --- This is a duplicate of `getLast?_eq_none_iff`. --- We should remove one of them. -theorem getLast?_eq_none : ∀ {l : List α}, getLast? l = none ↔ l = [] - | [] => by simp - | [a] => by simp - | a :: b :: l => by simp [@getLast?_eq_none (b :: l)] +@[deprecated (since := "2024-09-06")] alias getLast?_eq_none := getLast?_eq_none_iff @[deprecated (since := "2024-06-20")] alias getLast?_isNone := getLast?_eq_none -@[simp] -theorem getLast?_isSome : ∀ {l : List α}, l.getLast?.isSome ↔ l ≠ [] - | [] => by simp - | [a] => by simp - | a :: b :: l => by simp [@getLast?_isSome (b :: l)] - theorem mem_getLast?_eq_getLast : ∀ {l : List α} {x : α}, x ∈ l.getLast? → ∃ h, x = getLast l h | [], x, hx => False.elim <| by simp at hx | [a], x, hx => @@ -395,10 +376,6 @@ theorem mem_getLast?_cons {x y : α} : ∀ {l : List α}, x ∈ l.getLast? → x | [], _ => by contradiction | _ :: _, h => h -theorem mem_of_mem_getLast? {l : List α} {a : α} (ha : a ∈ l.getLast?) : a ∈ l := - let ⟨_, h₂⟩ := mem_getLast?_eq_getLast ha - h₂.symm ▸ getLast_mem _ - theorem dropLast_append_getLast? : ∀ {l : List α}, ∀ a ∈ l.getLast?, dropLast l ++ [a] = l | [], a, ha => (Option.not_mem_none a ha).elim | [a], _, rfl => rfl @@ -462,9 +439,6 @@ theorem eq_cons_of_mem_head? {x : α} : ∀ {l : List α}, x ∈ l.head? → l = simp only [head?, Option.mem_def, Option.some_inj] at h exact h ▸ rfl -theorem mem_of_mem_head? {x : α} {l : List α} (h : x ∈ l.head?) : x ∈ l := - (eq_cons_of_mem_head? h).symm ▸ mem_cons_self _ _ - @[simp] theorem head!_cons [Inhabited α] (a : α) (l : List α) : head! (a :: l) = a := rfl @[simp] @@ -839,14 +813,6 @@ theorem getElem?_indexOf [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : theorem indexOf_get? [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : get? l (indexOf a l) = some a := by simp [h] -@[deprecated (since := "2023-01-05")] -theorem get_reverse_aux₁ : - ∀ (l r : List α) (i h1 h2), get (reverseAux l r) ⟨i + length l, h1⟩ = get r ⟨i, h2⟩ - | [], r, i => fun h1 _ => rfl - | a :: l, r, i => by - rw [show i + length (a :: l) = i + 1 + length l from Nat.add_right_comm i (length l) 1] - exact fun h1 h2 => get_reverse_aux₁ l (a :: r) (i + 1) h1 (succ_lt_succ h2) - theorem indexOf_inj [DecidableEq α] {l : List α} {x y : α} (hx : x ∈ l) (hy : y ∈ l) : indexOf x l = indexOf y l ↔ x = y := ⟨fun h => by @@ -856,30 +822,13 @@ theorem indexOf_inj [DecidableEq α] {l : List α} {x y : α} (hx : x ∈ l) (hy simp only [h] simp only [indexOf_get] at x_eq_y; exact x_eq_y, fun h => by subst h; rfl⟩ -@[deprecated (since := "2024-08-15")] -theorem getElem_reverse_aux₂ : - ∀ (l r : List α) (i : Nat) (h1) (h2), - (reverseAux l r)[length l - 1 - i]'h1 = l[i]'h2 - | [], r, i, h1, h2 => absurd h2 (Nat.not_lt_zero _) - | a :: l, r, 0, h1, _ => by - have aux := get_reverse_aux₁ l (a :: r) 0 - rw [Nat.zero_add] at aux - exact aux _ (zero_lt_succ _) - | a :: l, r, i + 1, h1, h2 => by - have aux := getElem_reverse_aux₂ l (a :: r) i - have heq : length (a :: l) - 1 - (i + 1) = length l - 1 - i := by rw [length]; omega - rw [← heq] at aux - apply aux - -@[deprecated (since := "2024-06-12")] -theorem get_reverse_aux₂ (l r : List α) (i : Nat) (h1) (h2) : - get (reverseAux l r) ⟨length l - 1 - i, h1⟩ = get l ⟨i, h2⟩ := by - simp only [get_eq_getElem, h2, getElem_reverse_aux₂] - @[deprecated getElem_reverse (since := "2024-06-12")] theorem get_reverse (l : List α) (i : Nat) (h1 h2) : - get (reverse l) ⟨length l - 1 - i, h1⟩ = get l ⟨i, h2⟩ := - get_reverse_aux₂ _ _ _ _ _ + get (reverse l) ⟨length l - 1 - i, h1⟩ = get l ⟨i, h2⟩ := by + rw [get_eq_getElem, get_eq_getElem, getElem_reverse] + congr + dsimp + omega theorem get_reverse' (l : List α) (n) (hn') : l.reverse.get n = l.get ⟨l.length - 1 - n, hn'⟩ := by @@ -938,6 +887,11 @@ theorem get_set_of_ne {l : List α} {i j : ℕ} (h : i ≠ j) (a : α) /-! ### map -/ +-- `List.map_const` (the version with `Function.const` instead of a lambda) is already tagged +-- `simp` in Core +-- TODO: Upstream the tagging to Core? +attribute [simp] map_const' + @[deprecated (since := "2024-06-21")] alias map_congr := map_congr_left theorem bind_pure_eq_map (f : α → β) (l : List α) : l.bind (pure ∘ f) = map f l := @@ -960,9 +914,6 @@ theorem infix_bind_of_mem {a : α} {as : List α} (h : a ∈ as) (f : α → Lis theorem map_eq_map {α β} (f : α → β) (l : List α) : f <$> l = map f l := rfl -@[simp] -theorem map_tail (f : α → β) (l) : map f (tail l) = tail (map f l) := by cases l <;> rfl - /-- A single `List.map` of a composition of functions is equal to composing a `List.map` with another `List.map`, fully applied. This is the reverse direction of `List.map_map`. @@ -1198,7 +1149,7 @@ lemma append_cons_inj_of_not_mem {x₁ x₂ z₁ z₂ : List α} {a₁ a₂ : α (notin_x : a₂ ∉ x₁) (notin_z : a₂ ∉ z₁) : x₁ ++ a₁ :: z₁ = x₂ ++ a₂ :: z₂ ↔ x₁ = x₂ ∧ a₁ = a₂ ∧ z₁ = z₂ := by constructor - · simp only [append_eq_append_iff, cons_eq_append, cons_eq_cons] + · simp only [append_eq_append_iff, cons_eq_append_iff, cons_eq_cons] rintro (⟨c, rfl, ⟨rfl, rfl, rfl⟩ | ⟨d, rfl, rfl⟩⟩ | ⟨c, rfl, ⟨rfl, rfl, rfl⟩ | ⟨d, rfl, rfl⟩⟩) <;> simp_all · rintro ⟨rfl, rfl, rfl⟩ @@ -1267,7 +1218,7 @@ theorem getElem_succ_scanl {i : ℕ} (h : i + 1 < (scanl f b l).length) : · simp only [length] at h exact absurd h (by omega) · simp_rw [scanl_cons] - rw [getElem_append_right'] + rw [getElem_append_right] · simp only [length, Nat.zero_add 1, succ_add_sub_one, hi]; rfl · simp only [length_singleton]; omega @@ -1360,13 +1311,6 @@ local notation a " ⋆ " b => op a b /-- Notation for `foldl op a l`. -/ local notation l " <*> " a => foldl op a l -theorem foldl_assoc : ∀ {l : List α} {a₁ a₂}, (l <*> a₁ ⋆ a₂) = a₁ ⋆ l <*> a₂ - | [], a₁, a₂ => rfl - | a :: l, a₁, a₂ => - calc - ((a :: l) <*> a₁ ⋆ a₂) = l <*> a₁ ⋆ a₂ ⋆ a := by simp only [foldl_cons, ha.assoc] - _ = a₁ ⋆ (a :: l) <*> a₂ := by rw [foldl_assoc, foldl_cons] - theorem foldl_op_eq_op_foldr_assoc : ∀ {l : List α} {a₁ a₂}, ((l <*> a₁) ⋆ a₂) = a₁ ⋆ l.foldr (· ⋆ ·) a₂ | [], a₁, a₂ => rfl @@ -1419,7 +1363,7 @@ theorem intersperse_cons_cons (a b c : α) (tl : List α) : section SplitAtOn -variable (p : α → Bool) (xs ys : List α) (ls : List (List α)) (f : List α → List α) +variable (p : α → Bool) (xs : List α) (ls : List (List α)) attribute [simp] splitAt_eq @@ -1549,18 +1493,19 @@ theorem modifyLast.go_append_one (f : α → α) (a : α) (tl : List α) (r : Ar rw [modifyLast.go, modifyLast.go] case x_3 | x_3 => exact append_ne_nil_of_right_ne_nil tl (cons_ne_nil a []) rw [modifyLast.go_append_one _ _ tl _, modifyLast.go_append_one _ _ tl (Array.push #[] hd)] - simp only [Array.toListAppend_eq, Array.push_data, Array.data_toArray, nil_append, append_assoc] + simp only [Array.toListAppend_eq, Array.push_toList, Array.toList_toArray, nil_append, + append_assoc] theorem modifyLast_append_one (f : α → α) (a : α) (l : List α) : modifyLast f (l ++ [a]) = l ++ [f a] := by cases l with | nil => - simp only [nil_append, modifyLast, modifyLast.go, Array.toListAppend_eq, Array.data_toArray] + simp only [nil_append, modifyLast, modifyLast.go, Array.toListAppend_eq, Array.toList_toArray] | cons _ tl => simp only [cons_append, modifyLast] rw [modifyLast.go] case x_3 => exact append_ne_nil_of_right_ne_nil tl (cons_ne_nil a []) - rw [modifyLast.go_append_one, Array.toListAppend_eq, Array.push_data, Array.data_toArray, + rw [modifyLast.go_append_one, Array.toListAppend_eq, Array.push_toList, Array.toList_toArray, nil_append, cons_append, nil_append, cons_inj_right] exact modifyLast_append_one _ _ tl @@ -1595,8 +1540,6 @@ theorem sizeOf_lt_sizeOf_of_mem [SizeOf α] {x : α} {l : List α} (hx : x ∈ l section find? -variable {p : α → Bool} {l : List α} {a : α} - @[deprecated (since := "2024-05-05")] alias find?_mem := mem_of_find?_eq_some end find? @@ -1611,11 +1554,13 @@ variable (f : α → Option α) theorem lookmap.go_append (l : List α) (acc : Array α) : lookmap.go f l acc = acc.toListAppend (lookmap f l) := by cases l with - | nil => rfl + | nil => simp [go, lookmap] | cons hd tl => rw [lookmap, go, go] cases f hd with - | none => simp only [go_append tl _, Array.toListAppend_eq, append_assoc, Array.push_data]; rfl + | none => + simp only [go_append tl _, Array.toListAppend_eq, append_assoc, Array.push_toList] + rfl | some a => rfl @[simp] @@ -1625,13 +1570,13 @@ theorem lookmap_nil : [].lookmap f = [] := @[simp] theorem lookmap_cons_none {a : α} (l : List α) (h : f a = none) : (a :: l).lookmap f = a :: l.lookmap f := by - simp only [lookmap, lookmap.go, Array.toListAppend_eq, Array.data_toArray, nil_append] + simp only [lookmap, lookmap.go, Array.toListAppend_eq, Array.toList_toArray, nil_append] rw [lookmap.go_append, h]; rfl @[simp] theorem lookmap_cons_some {a b : α} (l : List α) (h : f a = some b) : (a :: l).lookmap f = b :: l := by - simp only [lookmap, lookmap.go, Array.toListAppend_eq, Array.data_toArray, nil_append] + simp only [lookmap, lookmap.go, Array.toListAppend_eq, Array.toList_toArray, nil_append] rw [h] theorem lookmap_some : ∀ l : List α, l.lookmap some = l @@ -1792,7 +1737,7 @@ lemma filter_attach (l : List α) (p : α → Bool) : ← filter_map, attach_map_subtype_val] lemma filter_comm (q) (l : List α) : filter p (filter q l) = filter q (filter p l) := by - simp [and_comm] + simp [Bool.and_comm] @[simp] theorem filter_true (l : List α) : @@ -1914,7 +1859,7 @@ theorem erase_getElem [DecidableEq ι] {l : List ι} {i : ℕ} (hi : i < l.lengt | succ i => have hi' : i < l.length := by simpa using hi if ha : a = l[i] then - simpa [ha] using .trans (perm_cons_erase (l.getElem_mem i _)) (.cons _ (IH hi')) + simpa [ha] using .trans (perm_cons_erase (getElem_mem _)) (.cons _ (IH hi')) else simpa [ha] using IH hi' @@ -2234,16 +2179,8 @@ end Forall /-! ### Miscellaneous lemmas -/ -@[simp] -theorem getElem_attach (L : List α) (i : Nat) (h : i < L.attach.length) : - L.attach[i].1 = L[i]'(length_attach L ▸ h) := - calc - L.attach[i].1 = (L.attach.map Subtype.val)[i]'(by simpa using h) := by - rw [getElem_map] - _ = L[i]'_ := by congr 2; simp - theorem get_attach (L : List α) (i) : - (L.attach.get i).1 = L.get ⟨i, length_attach L ▸ i.2⟩ := by simp + (L.attach.get i).1 = L.get ⟨i, length_attach (L := L) ▸ i.2⟩ := by simp @[simp 1100] theorem mem_map_swap (x : α) (y : β) (xs : List (α × β)) : @@ -2339,8 +2276,7 @@ theorem disjoint_reverse_right {l₁ l₂ : List α} : Disjoint l₁ l₂.revers end Disjoint section lookup - -variable {α β : Type*} [BEq α] [LawfulBEq α] +variable [BEq α] [LawfulBEq α] lemma lookup_graph (f : α → β) {a : α} {as : List α} (h : a ∈ as) : lookup a (as.map fun x => (x, f x)) = some (f a) := by diff --git a/Mathlib/Data/List/Chain.lean b/Mathlib/Data/List/Chain.lean index a1953d0529518..965aee596b838 100644 --- a/Mathlib/Data/List/Chain.lean +++ b/Mathlib/Data/List/Chain.lean @@ -138,6 +138,19 @@ theorem chain_iff_get {R} : ∀ {a : α} {l : List α}, Chain R a l ↔ intro i w exact h (i+1) (by simp only [length_cons]; omega) +theorem chain_replicate_of_rel (n : ℕ) {a : α} (h : r a a) : Chain r a (replicate n a) := + match n with + | 0 => Chain.nil + | n + 1 => Chain.cons h (chain_replicate_of_rel n h) + +theorem chain_eq_iff_eq_replicate {a : α} {l : List α} : + Chain (· = ·) a l ↔ l = replicate l.length a := + match l with + | [] => by simp + | b :: l => by + rw [chain_cons] + simp (config := {contextual := true}) [eq_comm, replicate_succ, chain_eq_iff_eq_replicate] + theorem Chain'.imp {S : α → α → Prop} (H : ∀ a b, R a b → S a b) {l : List α} (p : Chain' R l) : Chain' S l := by cases l <;> [trivial; exact Chain.imp H p] @@ -232,8 +245,7 @@ theorem chain'_append : | [], l => by simp | [a], l => by simp [chain'_cons', and_comm] | a :: b :: l₁, l₂ => by - rw [cons_append, cons_append, chain'_cons, chain'_cons, ← cons_append, chain'_append, - and_assoc] + rw [cons_append, cons_append, chain'_cons, chain'_cons, ← cons_append, chain'_append, and_assoc] simp theorem Chain'.append (h₁ : Chain' R l₁) (h₂ : Chain' R l₂) @@ -419,6 +431,17 @@ lemma Chain'.iterate_eq_of_apply_eq {α : Type*} {f : α → α} {l : List α} apply hl omega +theorem chain'_replicate_of_rel (n : ℕ) {a : α} (h : r a a) : Chain' r (replicate n a) := + match n with + | 0 => chain'_nil + | n + 1 => chain_replicate_of_rel n h + +theorem chain'_eq_iff_eq_replicate {l : List α} : + Chain' (· = ·) l ↔ ∀ a ∈ l.head?, l = replicate l.length a := + match l with + | [] => by simp + | a :: l => by simp [Chain', chain_eq_iff_eq_replicate, replicate_succ] + end List diff --git a/Mathlib/Data/List/Count.lean b/Mathlib/Data/List/Count.lean index 45f4be1166e42..89475cec9fe1e 100644 --- a/Mathlib/Data/List/Count.lean +++ b/Mathlib/Data/List/Count.lean @@ -3,7 +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, Mario Carneiro -/ -import Mathlib.Data.Nat.Defs +import Mathlib.Logic.Function.Basic +import Mathlib.Tactic.Common /-! # Counting in lists @@ -19,7 +20,7 @@ assert_not_exists Ring open Nat -variable {α : Type*} {l : List α} +variable {α : Type*} namespace List @@ -34,14 +35,6 @@ theorem count_map_of_injective {β} [DecidableEq α] [DecidableEq β] (l : List unfold Function.comp simp only [hf.beq_eq] -variable [DecidableEq α] - -@[deprecated (since := "2023-08-23")] -theorem count_cons' (a b : α) (l : List α) : - count a (b :: l) = count a l + if a = b then 1 else 0 := by - simp only [count, beq_iff_eq, countP_cons, Nat.add_right_inj] - simp only [eq_comm] - end Count end List diff --git a/Mathlib/Data/List/Cycle.lean b/Mathlib/Data/List/Cycle.lean index 5f038e2ae1e94..9c8cbaa143209 100644 --- a/Mathlib/Data/List/Cycle.lean +++ b/Mathlib/Data/List/Cycle.lean @@ -334,7 +334,7 @@ theorem prev_next (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : obtain ⟨⟨n, hn⟩, rfl⟩ := get_of_mem hx simp only [next_get, prev_get, h, Nat.mod_add_mod] cases' l with hd tl - · simp at hx + · simp at hn · have : (n + 1 + length tl) % (length tl + 1) = n := by rw [length_cons] at hn rw [add_assoc, add_comm 1, Nat.add_mod_right, Nat.mod_eq_of_lt hn] @@ -345,7 +345,7 @@ theorem next_prev (l : List α) (h : Nodup l) (x : α) (hx : x ∈ l) : obtain ⟨⟨n, hn⟩, rfl⟩ := get_of_mem hx simp only [next_get, prev_get, h, Nat.mod_add_mod] cases' l with hd tl - · simp at hx + · simp at hn · have : (n + length tl + 1) % (length tl + 1) = n := by rw [length_cons] at hn rw [add_assoc, Nat.add_mod_right, Nat.mod_eq_of_lt hn] diff --git a/Mathlib/Data/List/Dedup.lean b/Mathlib/Data/List/Dedup.lean index bb2bf2901cd89..55576850f682a 100644 --- a/Mathlib/Data/List/Dedup.lean +++ b/Mathlib/Data/List/Dedup.lean @@ -82,7 +82,7 @@ theorem dedup_eq_cons (l : List α) (a : α) (l' : List α) : l.dedup = a :: l' ↔ a ∈ l ∧ a ∉ l' ∧ l.dedup.tail = l' := by refine ⟨fun h => ?_, fun h => ?_⟩ · refine ⟨mem_dedup.1 (h.symm ▸ mem_cons_self _ _), fun ha => ?_, by rw [h, tail_cons]⟩ - have := count_pos_iff_mem.2 ha + have := count_pos_iff.2 ha have : count a l.dedup ≤ 1 := nodup_iff_count_le_one.1 (nodup_dedup l) a rw [h, count_cons_self] at this omega diff --git a/Mathlib/Data/List/Defs.lean b/Mathlib/Data/List/Defs.lean index 80750fd2c8b30..f0aad1fcd0f00 100644 --- a/Mathlib/Data/List/Defs.lean +++ b/Mathlib/Data/List/Defs.lean @@ -10,6 +10,7 @@ import Mathlib.Util.CompileInductive import Batteries.Tactic.Lint.Basic import Batteries.Data.List.Lemmas import Batteries.Data.RBMap.Basic +import Batteries.Logic /-! ## Definitions on lists diff --git a/Mathlib/Data/List/Enum.lean b/Mathlib/Data/List/Enum.lean index d4b73fc6bec78..a574ea756a233 100644 --- a/Mathlib/Data/List/Enum.lean +++ b/Mathlib/Data/List/Enum.lean @@ -19,7 +19,7 @@ Any downstream users who can not easily adapt may remove the deprecations as nee namespace List -variable {α β : Type*} +variable {α : Type*} @[deprecated getElem?_enumFrom (since := "2024-08-15")] theorem get?_enumFrom (n) (l : List α) (m) : diff --git a/Mathlib/Data/List/FinRange.lean b/Mathlib/Data/List/FinRange.lean index 240012da5d608..62d8122999597 100644 --- a/Mathlib/Data/List/FinRange.lean +++ b/Mathlib/Data/List/FinRange.lean @@ -42,7 +42,7 @@ theorem finRange_succ (n : ℕ) : theorem ofFn_eq_pmap {n} {f : Fin n → α} : ofFn f = pmap (fun i hi => f ⟨i, hi⟩) (range n) fun _ => mem_range.1 := by rw [pmap_eq_map_attach] - exact ext_getElem (by simp) fun i hi1 hi2 => by simp [getElem_ofFn f i hi1] + exact ext_getElem (by simp) fun i hi1 hi2 => by simp [List.getElem_ofFn f i hi1] theorem ofFn_id (n) : ofFn id = finRange n := ofFn_eq_pmap diff --git a/Mathlib/Data/List/Forall2.lean b/Mathlib/Data/List/Forall2.lean index 79f5bf6c1cb0a..20808976c60ab 100644 --- a/Mathlib/Data/List/Forall2.lean +++ b/Mathlib/Data/List/Forall2.lean @@ -84,14 +84,18 @@ theorem forall₂_cons_right_iff {b l u} : match u, h with | _, ⟨_, _, h₁, h₂, rfl⟩ => Forall₂.cons h₁ h₂ +#adaptation_note +/-- +After nightly-2024-09-06 we can remove the `_root_` prefixes below. +-/ theorem forall₂_and_left {p : α → Prop} : ∀ l u, Forall₂ (fun a b => p a ∧ R a b) l u ↔ (∀ a ∈ l, p a) ∧ Forall₂ R l u | [], u => by simp only [forall₂_nil_left_iff, forall_prop_of_false (not_mem_nil _), imp_true_iff, true_and] | a :: l, u => by - simp only [forall₂_and_left l, forall₂_cons_left_iff, forall_mem_cons, and_assoc, + simp only [forall₂_and_left l, forall₂_cons_left_iff, forall_mem_cons, _root_.and_assoc, @and_comm _ (p a), @and_left_comm _ (p a), exists_and_left] - simp only [and_comm, and_assoc, and_left_comm, ← exists_and_right] + simp only [_root_.and_comm, _root_.and_assoc, and_left_comm, ← exists_and_right] @[simp] theorem forall₂_map_left_iff {f : γ → α} : diff --git a/Mathlib/Data/List/GetD.lean b/Mathlib/Data/List/GetD.lean index bc144f95b4785..e16ce04be7e33 100644 --- a/Mathlib/Data/List/GetD.lean +++ b/Mathlib/Data/List/GetD.lean @@ -72,16 +72,13 @@ alias getD_replicate_default_eq := getElem?_getD_replicate_default_eq theorem getD_append (l l' : List α) (d : α) (n : ℕ) (h : n < l.length) : (l ++ l').getD n d = l.getD n d := by rw [getD_eq_getElem _ _ (Nat.lt_of_lt_of_le h (length_append _ _ ▸ Nat.le_add_right _ _)), - getElem_append _ h, getD_eq_getElem] + getElem_append_left h, getD_eq_getElem] theorem getD_append_right (l l' : List α) (d : α) (n : ℕ) (h : l.length ≤ n) : (l ++ l').getD n d = l'.getD (n - l.length) d := by cases Nat.lt_or_ge n (l ++ l').length with | inl h' => - rw [getD_eq_getElem (l ++ l') d h', getElem_append_right, getD_eq_getElem] - · rw [length_append] at h' - exact Nat.sub_lt_left_of_lt_add h h' - · exact Nat.not_lt_of_le h + rw [getD_eq_getElem (l ++ l') d h', getElem_append_right h, getD_eq_getElem] | inr h' => rw [getD_eq_default _ _ h', getD_eq_default] rwa [Nat.le_sub_iff_add_le' h, ← length_append] diff --git a/Mathlib/Data/List/Indexes.lean b/Mathlib/Data/List/Indexes.lean index b2351ad435a24..7e53018e89d4b 100644 --- a/Mathlib/Data/List/Indexes.lean +++ b/Mathlib/Data/List/Indexes.lean @@ -55,9 +55,9 @@ theorem mapIdxGo_append : ∀ (f : ℕ → α → β) (l₁ l₂ : List α) (arr cases l₂ · rfl · rw [List.length_append] at h; contradiction - rw [l₁_nil, l₂_nil]; simp only [mapIdx.go, Array.toList_eq, Array.toArray_data] + rw [l₁_nil, l₂_nil]; simp only [mapIdx.go, List.toArray_toList] · cases' l₁ with head tail <;> simp only [mapIdx.go] - · simp only [nil_append, Array.toList_eq, Array.toArray_data] + · simp only [nil_append, List.toArray_toList] · simp only [List.append_eq] rw [ih] · simp only [cons_append, length_cons, length_append, Nat.succ.injEq] at h @@ -67,7 +67,7 @@ theorem mapIdxGo_length : ∀ (f : ℕ → α → β) (l : List α) (arr : Array length (mapIdx.go f l arr) = length l + arr.size := by intro f l induction' l with head tail ih - · intro; simp only [mapIdx.go, Array.toList_eq, length_nil, Nat.zero_add] + · intro; simp only [mapIdx.go, length_nil, Nat.zero_add] · intro; simp only [mapIdx.go]; rw [ih]; simp only [Array.size_push, length_cons] simp only [Nat.add_succ, Fin.add_zero, Nat.add_comm] @@ -77,7 +77,7 @@ theorem mapIdx_append_one : ∀ (f : ℕ → α → β) (l : List α) (e : α), unfold mapIdx rw [mapIdxGo_append f l [e]] simp only [mapIdx.go, Array.size_toArray, mapIdxGo_length, length_nil, Nat.add_zero, - Array.toList_eq, Array.push_data, Array.data_toArray] + Array.push_toList, Array.toList_toArray] @[local simp] theorem map_enumFrom_eq_zipWith : ∀ (l : List α) (n : ℕ) (f : ℕ → α → β), @@ -119,15 +119,16 @@ theorem getElem?_mapIdx_go (f : ℕ → α → β) : ∀ (l : List α) (arr : Ar (mapIdx.go f l arr)[i]? = if h : i < arr.size then some arr[i] else Option.map (f i) l[i - arr.size]? | [], arr, i => by - simp [mapIdx.go, getElem?_eq, Array.getElem_eq_data_getElem] + simp only [mapIdx.go, Array.toListImpl_eq, getElem?_eq, Array.length_toList, + Array.getElem_eq_getElem_toList, length_nil, Nat.not_lt_zero, ↓reduceDIte, Option.map_none'] | a :: l, arr, i => by rw [mapIdx.go, getElem?_mapIdx_go] simp only [Array.size_push] split <;> split · simp only [Option.some.injEq] - rw [Array.getElem_eq_data_getElem] - simp only [Array.push_data] - rw [getElem_append_left, Array.getElem_eq_data_getElem] + rw [Array.getElem_eq_getElem_toList] + simp only [Array.push_toList] + rw [getElem_append_left, Array.getElem_eq_getElem_toList] · have : i = arr.size := by omega simp_all · omega @@ -158,7 +159,7 @@ theorem mapIdx_append (K L : List α) (f : ℕ → α → β) : @[simp] theorem mapIdx_eq_nil {f : ℕ → α → β} {l : List α} : List.mapIdx f l = [] ↔ l = [] := by - rw [List.mapIdx_eq_enum_map, List.map_eq_nil, List.enum_eq_nil] + rw [List.mapIdx_eq_enum_map, List.map_eq_nil_iff, List.enum_eq_nil] theorem get_mapIdx (l : List α) (f : ℕ → α → β) (i : ℕ) (h : i < l.length) (h' : i < (l.mapIdx f).length := h.trans_le (l.length_mapIdx f).ge) : @@ -356,12 +357,12 @@ theorem mapIdxMGo_eq_mapIdxMAuxSpec congr conv => { lhs; intro x; rw [ih _ _ h]; } funext x - simp only [Array.toList_eq, Array.push_data, append_assoc, singleton_append, Array.size_push, + simp only [Array.push_toList, append_assoc, singleton_append, Array.size_push, map_eq_pure_bind] theorem mapIdxM_eq_mmap_enum [LawfulMonad m] {β} (f : ℕ → α → m β) (as : List α) : as.mapIdxM f = List.traverse (uncurry f) (enum as) := by - simp only [mapIdxM, mapIdxMGo_eq_mapIdxMAuxSpec, Array.toList_eq, Array.data_toArray, + simp only [mapIdxM, mapIdxMGo_eq_mapIdxMAuxSpec, Array.toList_toArray, nil_append, mapIdxMAuxSpec, Array.size_toArray, length_nil, id_map', enum] end MapIdxM diff --git a/Mathlib/Data/List/Infix.lean b/Mathlib/Data/List/Infix.lean index 974beaac0fde7..b7bf8b65b8356 100644 --- a/Mathlib/Data/List/Infix.lean +++ b/Mathlib/Data/List/Infix.lean @@ -25,11 +25,11 @@ All those (except `insert`) are defined in `Mathlib.Data.List.Defs`. * `l₁ <:+: l₂`: `l₁` is an infix of `l₂`. -/ -variable {α β : Type*} +variable {α : Type*} namespace List -variable {l l₁ l₂ l₃ : List α} {a b : α} {m n : ℕ} +variable {l l₁ l₂ : List α} {a b : α} /-! ### prefix, suffix, infix -/ @@ -69,8 +69,7 @@ theorem tail_subset (l : List α) : tail l ⊆ l := theorem mem_of_mem_dropLast (h : a ∈ l.dropLast) : a ∈ l := dropLast_subset l h -theorem mem_of_mem_tail (h : a ∈ l.tail) : a ∈ l := - tail_subset l h +attribute [gcongr] Sublist.drop theorem concat_get_prefix {x y : List α} (h : x <+: y) (hl : x.length < y.length) : x ++ [y.get ⟨x.length, hl⟩] <+: y := by @@ -79,6 +78,14 @@ theorem concat_get_prefix {x y : List α} (h : x <+: y) (hl : x.length < y.lengt convert List.take_append_drop (x.length + 1) y using 2 rw [← List.take_concat_get, List.concat_eq_append]; rfl +instance decidableInfix [DecidableEq α] : ∀ l₁ l₂ : List α, Decidable (l₁ <:+: l₂) + | [], l₂ => isTrue ⟨[], l₂, rfl⟩ + | a :: l₁, [] => isFalse fun ⟨s, t, te⟩ => by simp at te + | l₁, b :: l₂ => + letI := l₁.decidableInfix l₂ + @decidable_of_decidable_of_iff (l₁ <+: b :: l₂ ∨ l₁ <:+: l₂) _ _ + infix_cons_iff.symm + @[deprecated cons_prefix_cons (since := "2024-08-14")] theorem cons_prefix_iff : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by simp @@ -150,7 +157,17 @@ theorem inits_cons (a : α) (l : List α) : inits (a :: l) = [] :: l.inits.map f theorem tails_cons (a : α) (l : List α) : tails (a :: l) = (a :: l) :: l.tails := by simp -@[simp] +#adaptation_note +/-- +This can be removed after nightly-2024-09-07. +-/ +attribute [-simp] map_tail + +#adaptation_note +/-- +`nolint simpNF` should be removed after nightly-2024-09-07. +-/ +@[simp, nolint simpNF] theorem inits_append : ∀ s t : List α, inits (s ++ t) = s.inits ++ t.inits.tail.map fun l => s ++ l | [], [] => by simp | [], a :: t => by simp diff --git a/Mathlib/Data/List/InsertNth.lean b/Mathlib/Data/List/InsertNth.lean index 99646ea33a4c5..00cef198f31e7 100644 --- a/Mathlib/Data/List/InsertNth.lean +++ b/Mathlib/Data/List/InsertNth.lean @@ -19,9 +19,9 @@ open Nat hiding one_pos namespace List -universe u v w +universe u -variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {l₁ l₂ : List α} +variable {α : Type u} section InsertNth @@ -83,13 +83,17 @@ theorem insertNth_comm (a b : α) : simp only [insertNth_succ_cons, cons.injEq, true_and] exact insertNth_comm a b i j l (Nat.le_of_succ_le_succ h₀) (Nat.le_of_succ_le_succ h₁) +#adaptation_note +/-- +After nightly-2024-09-06 we can remove the `_root_` prefixes below. +-/ theorem mem_insertNth {a b : α} : ∀ {n : ℕ} {l : List α} (_ : n ≤ l.length), a ∈ l.insertNth n b ↔ a = b ∨ a ∈ l | 0, as, _ => by simp | n + 1, [], h => (Nat.not_succ_le_zero _ h).elim | n + 1, a' :: as, h => by rw [List.insertNth_succ_cons, mem_cons, mem_insertNth (Nat.le_of_succ_le_succ h), - ← or_assoc, @or_comm (a = a'), or_assoc, mem_cons] + ← _root_.or_assoc, @or_comm (a = a'), _root_.or_assoc, mem_cons] theorem insertNth_of_length_lt (l : List α) (x : α) (n : ℕ) (h : l.length < n) : insertNth n x l = l := by diff --git a/Mathlib/Data/List/Intervals.lean b/Mathlib/Data/List/Intervals.lean index c1419e19f2901..870f434107df2 100644 --- a/Mathlib/Data/List/Intervals.lean +++ b/Mathlib/Data/List/Intervals.lean @@ -135,7 +135,7 @@ theorem filter_lt_of_top_le {n m l : ℕ} (hml : m ≤ l) : simp only [(lt_of_lt_of_le (mem.1 hk).2 hml), decide_True] theorem filter_lt_of_le_bot {n m l : ℕ} (hln : l ≤ n) : ((Ico n m).filter fun x => x < l) = [] := - filter_eq_nil.2 fun k hk => by + filter_eq_nil_iff.2 fun k hk => by simp only [decide_eq_true_eq, not_lt] apply le_trans hln exact (mem.1 hk).1 @@ -161,7 +161,7 @@ theorem filter_le_of_le_bot {n m l : ℕ} (hln : l ≤ n) : exact le_trans hln (mem.1 hk).1 theorem filter_le_of_top_le {n m l : ℕ} (hml : m ≤ l) : ((Ico n m).filter fun x => l ≤ x) = [] := - filter_eq_nil.2 fun k hk => by + filter_eq_nil_iff.2 fun k hk => by rw [decide_eq_true_eq] exact not_le_of_gt (lt_of_lt_of_le (mem.1 hk).2 hml) diff --git a/Mathlib/Data/List/Lattice.lean b/Mathlib/Data/List/Lattice.lean index 7c3ce41155f9f..5a0ae92ccc6c0 100644 --- a/Mathlib/Data/List/Lattice.lean +++ b/Mathlib/Data/List/Lattice.lean @@ -29,7 +29,7 @@ open Nat namespace List -variable {α : Type*} {l l₁ l₂ : List α} {p : α → Prop} {a : α} +variable {α : Type*} {l₁ l₂ : List α} {p : α → Prop} {a : α} /-! ### `Disjoint` -/ @@ -203,7 +203,7 @@ theorem count_bagInter {a : α} : by_cases ba : b = a · simp only [beq_iff_eq] rw [if_pos ba, Nat.sub_add_cancel] - rwa [succ_le_iff, count_pos_iff_mem, ← ba] + rwa [succ_le_iff, count_pos_iff, ← ba] · simp only [beq_iff_eq] rw [if_neg ba, Nat.sub_zero, Nat.add_zero, Nat.add_zero] · rw [cons_bagInter_of_neg _ hb, count_bagInter] diff --git a/Mathlib/Data/List/Lemmas.lean b/Mathlib/Data/List/Lemmas.lean index 0d7c5ffd0b7ff..b055f1b187222 100644 --- a/Mathlib/Data/List/Lemmas.lean +++ b/Mathlib/Data/List/Lemmas.lean @@ -30,18 +30,6 @@ theorem tail_reverse_eq_reverse_dropLast (l : List α) : · rw [getElem?_eq_none, getElem?_eq_none] all_goals (simp; omega) -theorem getLast_tail (l : List α) (hl : l.tail ≠ []) : - l.tail.getLast hl = l.getLast (by intro h; rw [h] at hl; simp at hl) := by - simp only [← drop_one, ne_eq, drop_eq_nil_iff_le, - not_le, getLast_eq_getElem, length_drop] at hl |- - rw [← getElem_drop'] - · simp [show 1 + (l.length - 1 - 1) = l.length - 1 by omega] - omega - -lemma getElem_tail {i} (L : List α) (hi : i < L.tail.length) : - L.tail[i] = L[i + 1]'(by simp at *; omega) := by - induction L <;> simp at hi |- - @[deprecated (since := "2024-08-19")] alias nthLe_tail := getElem_tail theorem injOn_insertNth_index_of_not_mem (l : List α) (x : α) (hx : x ∉ l) : diff --git a/Mathlib/Data/List/MinMax.lean b/Mathlib/Data/List/MinMax.lean index c20935506c371..52a8f59fb7167 100644 --- a/Mathlib/Data/List/MinMax.lean +++ b/Mathlib/Data/List/MinMax.lean @@ -433,25 +433,31 @@ theorem minimum_of_length_pos_le_getElem {i : ℕ} (w : i < l.length) (h := (Nat l.minimum_of_length_pos h ≤ l[i] := getElem_le_maximum_of_length_pos (α := αᵒᵈ) w -lemma getD_maximum?_eq_unbot'_maximum (l : List α) (d : α) : - l.maximum?.getD d = l.maximum.unbot' d := by +lemma getD_max?_eq_unbot'_maximum (l : List α) (d : α) : + l.max?.getD d = l.maximum.unbot' d := by cases hy : l.maximum with | bot => simp [List.maximum_eq_bot.mp hy] | coe y => rw [List.maximum_eq_coe_iff] at hy simp only [WithBot.unbot'_coe] - cases hz : l.maximum? with - | none => simp [List.maximum?_eq_none_iff.mp hz] at hy + cases hz : l.max? with + | none => simp [List.max?_eq_none_iff.mp hz] at hy | some z => have : Antisymm (α := α) (· ≤ ·) := ⟨_root_.le_antisymm⟩ - rw [List.maximum?_eq_some_iff] at hz + rw [List.max?_eq_some_iff] at hz · rw [Option.getD_some] exact _root_.le_antisymm (hy.right _ hz.left) (hz.right _ hy.left) all_goals simp [le_total] -lemma getD_minimum?_eq_untop'_minimum (l : List α) (d : α) : - l.minimum?.getD d = l.minimum.untop' d := - getD_maximum?_eq_unbot'_maximum (α := αᵒᵈ) _ _ +@[deprecated (since := "2024-09-29")] +alias getD_maximum?_eq_unbot'_maximum := getD_max?_eq_unbot'_maximum + +lemma getD_min?_eq_untop'_minimum (l : List α) (d : α) : + l.min?.getD d = l.minimum.untop' d := + getD_max?_eq_unbot'_maximum (α := αᵒᵈ) _ _ + +@[deprecated (since := "2024-09-29")] +alias getD_minimum?_eq_untop'_minimum := getD_min?_eq_untop'_minimum end LinearOrder diff --git a/Mathlib/Data/List/Monad.lean b/Mathlib/Data/List/Monad.lean index a89b5f05d5272..04d1477cbd14d 100644 --- a/Mathlib/Data/List/Monad.lean +++ b/Mathlib/Data/List/Monad.lean @@ -9,11 +9,11 @@ import Mathlib.Init # Monad instances for `List` -/ -universe u v w +universe u namespace List -variable {α : Type u} {β : Type v} {γ : Type w} +variable {α : Type u} instance instMonad : Monad List.{u} where pure := @List.pure diff --git a/Mathlib/Data/List/Nodup.lean b/Mathlib/Data/List/Nodup.lean index c4ede7b589049..f04247b8a0193 100644 --- a/Mathlib/Data/List/Nodup.lean +++ b/Mathlib/Data/List/Nodup.lean @@ -16,9 +16,9 @@ predicate. universe u v -open Nat Function +open Function -variable {α : Type u} {β : Type v} {l l₁ l₂ : List α} {r : α → α → Prop} {a b : α} +variable {α : Type u} {β : Type v} {l l₁ l₂ : List α} {r : α → α → Prop} {a : α} namespace List @@ -140,14 +140,14 @@ theorem nodup_iff_count_le_one [DecidableEq α] {l : List α} : Nodup l ↔ ∀ theorem nodup_iff_count_eq_one [DecidableEq α] : Nodup l ↔ ∀ a ∈ l, count a l = 1 := nodup_iff_count_le_one.trans <| forall_congr' fun _ => - ⟨fun H h => H.antisymm (count_pos_iff_mem.mpr h), + ⟨fun H h => H.antisymm (count_pos_iff.mpr h), fun H => if h : _ then (H h).le else (count_eq_zero.mpr h).trans_le (Nat.zero_le 1)⟩ @[simp] theorem count_eq_one_of_mem [DecidableEq α] {a : α} {l : List α} (d : Nodup l) (h : a ∈ l) : count a l = 1 := - _root_.le_antisymm (nodup_iff_count_le_one.1 d a) (Nat.succ_le_of_lt (count_pos_iff_mem.2 h)) + _root_.le_antisymm (nodup_iff_count_le_one.1 d a) (Nat.succ_le_of_lt (count_pos_iff.2 h)) theorem count_eq_of_nodup [DecidableEq α] {a : α} {l : List α} (d : Nodup l) : count a l = if a ∈ l then 1 else 0 := by @@ -224,7 +224,7 @@ theorem Nodup.pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} {H} exact h.attach.map fun ⟨a, ha⟩ ⟨b, hb⟩ h => by congr; exact hf a (H _ ha) b (H _ hb) h theorem Nodup.filter (p : α → Bool) {l} : Nodup l → Nodup (filter p l) := by - simpa using Pairwise.filter (fun a ↦ p a) + simpa using Pairwise.filter p @[simp] theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l := @@ -244,8 +244,8 @@ theorem Nodup.erase_getElem [DecidableEq α] {l : List α} (hl : l.Nodup) · simp [IH hl.2] · rw [beq_iff_eq] simp only [getElem_cons_succ] - simp only [length_cons, succ_eq_add_one, Nat.add_lt_add_iff_right] at h - exact mt (· ▸ l.getElem_mem i h) hl.1 + simp only [length_cons, Nat.succ_eq_add_one, Nat.add_lt_add_iff_right] at h + exact mt (· ▸ getElem_mem h) hl.1 theorem Nodup.erase_get [DecidableEq α] {l : List α} (hl : l.Nodup) (i : Fin l.length) : l.erase (l.get i) = l.eraseIdx ↑i := by @@ -262,8 +262,8 @@ theorem nodup_join {L : List (List α)} : theorem nodup_bind {l₁ : List α} {f : α → List β} : Nodup (l₁.bind f) ↔ (∀ x ∈ l₁, Nodup (f x)) ∧ Pairwise (fun a b : α => Disjoint (f a) (f b)) l₁ := by - simp only [List.bind, nodup_join, pairwise_map, and_comm, and_left_comm, mem_map, exists_imp, - and_imp] + simp only [List.bind, nodup_join, pairwise_map, and_comm, and_left_comm, mem_map, + exists_imp, and_imp] rw [show (∀ (l : List β) (x : α), f x = l → x ∈ l₁ → Nodup l) ↔ ∀ x : α, x ∈ l₁ → Nodup (f x) from forall_swap.trans <| forall_congr' fun _ => forall_eq'] @@ -304,13 +304,12 @@ theorem Nodup.union [DecidableEq α] (l₁ : List α) (h : Nodup l₂) : (l₁ theorem Nodup.inter [DecidableEq α] (l₂ : List α) : Nodup l₁ → Nodup (l₁ ∩ l₂) := Nodup.filter _ -theorem Nodup.diff_eq_filter [DecidableEq α] : +theorem Nodup.diff_eq_filter [BEq α] [LawfulBEq α] : ∀ {l₁ l₂ : List α} (_ : l₁.Nodup), l₁.diff l₂ = l₁.filter (· ∉ l₂) | l₁, [], _ => by simp | l₁, a :: l₂, hl₁ => by rw [diff_cons, (hl₁.erase _).diff_eq_filter, hl₁.erase_eq_filter, filter_filter] - simp only [decide_not, Bool.not_eq_true', decide_eq_false_iff_not, bne_iff_ne, ne_eq, and_comm, - Bool.decide_and, mem_cons, not_or] + simp only [decide_not, bne, Bool.and_comm, mem_cons, not_or, decide_mem_cons, Bool.not_or] theorem Nodup.mem_diff_iff [DecidableEq α] (hl₁ : l₁.Nodup) : a ∈ l₁.diff l₂ ↔ a ∈ l₁ ∧ a ∉ l₂ := by rw [hl₁.diff_eq_filter, mem_filter, decide_eq_true_iff] diff --git a/Mathlib/Data/List/NodupEquivFin.lean b/Mathlib/Data/List/NodupEquivFin.lean index 5266ae7b60164..0dcf11280caae 100644 --- a/Mathlib/Data/List/NodupEquivFin.lean +++ b/Mathlib/Data/List/NodupEquivFin.lean @@ -126,7 +126,7 @@ theorem sublist_of_orderEmbedding_get?_eq {l l' : List α} (f : ℕ ↪o ℕ) exact ix.succ_pos rw [← List.take_append_drop (f 0 + 1) l', ← List.singleton_append] apply List.Sublist.append _ (IH _ this) - rw [List.singleton_sublist, ← h, l'.getElem_take _ (Nat.lt_succ_self _)] + rw [List.singleton_sublist, ← h, l'.getElem_take' _ (Nat.lt_succ_self _)] apply List.get_mem /-- A `l : List α` is `Sublist l l'` for `l' : List α` iff diff --git a/Mathlib/Data/List/OfFn.lean b/Mathlib/Data/List/OfFn.lean index cdfcb9554f599..9aa74790b948b 100644 --- a/Mathlib/Data/List/OfFn.lean +++ b/Mathlib/Data/List/OfFn.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 Batteries.Data.List.OfFn import Batteries.Data.List.Pairwise import Mathlib.Data.Fin.Tuple.Basic @@ -16,7 +17,6 @@ of length `n`. The main statements pertain to lists generated using `List.ofFn` -- `List.length_ofFn`, which tells us the length of such a list - `List.get?_ofFn`, which tells us the nth element of such a list - `List.equivSigmaTuple`, which is an `Equiv` between lists and the functions that generate them via `List.ofFn`. @@ -32,44 +32,9 @@ open Nat namespace List -@[simp] -theorem length_ofFn_go {n} (f : Fin n → α) (i j h) : length (ofFn.go f i j h) = i := by - induction i generalizing j <;> simp_all [ofFn.go] - -/-- The length of a list converted from a function is the size of the domain. -/ -@[simp] -theorem length_ofFn {n} (f : Fin n → α) : length (ofFn f) = n := by - simp [ofFn, length_ofFn_go] - -theorem getElem_ofFn_go {n} (f : Fin n → α) (i j h) (k) (hk : k < (ofFn.go f i j h).length) : - (ofFn.go f i j h)[k] = f ⟨j + k, by simp at hk; omega⟩ := by - let i+1 := i - cases k <;> simp [ofFn.go, getElem_ofFn_go (i := i)] - congr 2; omega - -theorem get_ofFn_go {n} (f : Fin n → α) (i j h) (k) (hk) : - get (ofFn.go f i j h) ⟨k, hk⟩ = f ⟨j + k, by simp at hk; omega⟩ := by - simp [getElem_ofFn_go] - -@[simp] -theorem getElem_ofFn {n} (f : Fin n → α) (i : Nat) (h : i < (ofFn f).length) : - (ofFn f)[i] = f ⟨i, by simp_all⟩ := by - simp [ofFn, getElem_ofFn_go] - theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f (Fin.cast (by simp) i) := by simp; congr -/-- The `n`th element of a list -/ -@[simp] -theorem getElem?_ofFn {n} (f : Fin n → α) (i) : (ofFn f)[i]? = ofFnNthVal f i := - if h : i < (ofFn f).length - then by - rw [getElem?_eq_getElem h, getElem_ofFn] - · simp only [length_ofFn] at h; simp [ofFnNthVal, h] - else by - rw [ofFnNthVal, dif_neg] <;> - simpa using h - /-- The `n`th element of a list -/ theorem get?_ofFn {n} (f : Fin n → α) (i) : get? (ofFn f) i = ofFnNthVal f i := by simp diff --git a/Mathlib/Data/List/Pairwise.lean b/Mathlib/Data/List/Pairwise.lean index 1a562e854c8c7..507a0a3195b58 100644 --- a/Mathlib/Data/List/Pairwise.lean +++ b/Mathlib/Data/List/Pairwise.lean @@ -29,7 +29,7 @@ open Nat Function namespace List -variable {α β : Type*} {R S T : α → α → Prop} {a : α} {l : List α} +variable {α β : Type*} {R : α → α → Prop} {l : List α} mk_iff_of_inductive_prop List.Pairwise List.pairwise_iff @@ -69,9 +69,6 @@ theorem pairwise_of_reflexive_of_forall_ne {l : List α} {r : α → α → Prop /-! ### Pairwise filtering -/ - -variable [DecidableRel R] - alias ⟨_, Pairwise.pwFilter⟩ := pwFilter_eq_self -- Porting note: commented out diff --git a/Mathlib/Data/List/Perm.lean b/Mathlib/Data/List/Perm.lean index 36d55e987eaee..52ea464bb6804 100644 --- a/Mathlib/Data/List/Perm.lean +++ b/Mathlib/Data/List/Perm.lean @@ -166,9 +166,14 @@ local notation a " * " b => op a b local notation l " <*> " a => foldl op a l -theorem Perm.fold_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁ <*> a) = l₂ <*> a := +theorem Perm.foldl_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁ <*> a) = l₂ <*> a := h.foldl_eq _ +theorem Perm.foldr_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : l₁.foldr op a = l₂.foldr op a := + h.foldr_eq _ + +@[deprecated (since := "2024-09-28")] alias Perm.fold_op_eq := Perm.foldl_op_eq + end theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by @@ -582,7 +587,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations' convert hk' using 1 exact get_insertNth_add_succ _ _ _ 0 _ · obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H' - erw [length_insertNth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn + rw [length_insertNth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn rw [get_insertNth_add_succ] · convert get_insertNth_add_succ s x k m.succ (by simpa using hn) using 2 · simp [Nat.add_assoc, Nat.add_left_comm] diff --git a/Mathlib/Data/List/Prime.lean b/Mathlib/Data/List/Prime.lean index e5812cb86b262..45c8f957e4d93 100644 --- a/Mathlib/Data/List/Prime.lean +++ b/Mathlib/Data/List/Prime.lean @@ -43,7 +43,7 @@ end CommMonoidWithZero section CancelCommMonoidWithZero -variable {M : Type*} [CancelCommMonoidWithZero M] [Unique (Units M)] +variable {M : Type*} [CancelCommMonoidWithZero M] [Subsingleton Mˣ] theorem mem_list_primes_of_dvd_prod {p : M} (hp : Prime p) {L : List M} (hL : ∀ q ∈ L, Prime q) (hpL : p ∣ L.prod) : p ∈ L := by @@ -54,10 +54,10 @@ theorem perm_of_prod_eq_prod : ∀ {l₁ l₂ : List M}, l₁.prod = l₂.prod → (∀ p ∈ l₁, Prime p) → (∀ p ∈ l₂, Prime p) → Perm l₁ l₂ | [], [], _, _, _ => Perm.nil | [], a :: l, h₁, _, h₃ => - have ha : a ∣ 1 := @prod_nil M _ ▸ h₁.symm ▸ (@prod_cons _ _ l a).symm ▸ dvd_mul_right _ _ + have ha : a ∣ 1 := prod_nil (M := M) ▸ h₁.symm ▸ (prod_cons (l := l)).symm ▸ dvd_mul_right _ _ absurd ha (Prime.not_dvd_one (h₃ a (mem_cons_self _ _))) | a :: l, [], h₁, h₂, _ => - have ha : a ∣ 1 := @prod_nil M _ ▸ h₁ ▸ (@prod_cons _ _ l a).symm ▸ dvd_mul_right _ _ + have ha : a ∣ 1 := prod_nil (M := M) ▸ h₁ ▸ (prod_cons (l := l)).symm ▸ dvd_mul_right _ _ absurd ha (Prime.not_dvd_one (h₂ a (mem_cons_self _ _))) | a :: l₁, b :: l₂, h, hl₁, hl₂ => by classical diff --git a/Mathlib/Data/List/Rotate.lean b/Mathlib/Data/List/Rotate.lean index 5cbd6337a5630..8b6479898785b 100644 --- a/Mathlib/Data/List/Rotate.lean +++ b/Mathlib/Data/List/Rotate.lean @@ -116,7 +116,7 @@ theorem length_rotate (l : List α) (n : ℕ) : (l.rotate n).length = l.length : @[simp] theorem rotate_replicate (a : α) (n : ℕ) (k : ℕ) : (replicate n a).rotate k = replicate n a := - eq_replicate.2 ⟨by rw [length_rotate, length_replicate], fun b hb => + eq_replicate_iff.2 ⟨by rw [length_rotate, length_replicate], fun b hb => eq_of_mem_replicate <| mem_rotate.1 hb⟩ theorem rotate_eq_drop_append_take {l : List α} {n : ℕ} : @@ -473,7 +473,7 @@ theorem IsRotated.dropLast_tail {α} | [] => by simp | [_] => by simp | a :: b :: L => by - simp at hL' |- + simp only [head_cons, ne_eq, reduceCtorEq, not_false_eq_true, getLast_cons] at hL' simp [hL', IsRotated.cons_getLast_dropLast] /-- List of all cyclic permutations of `l`. @@ -610,7 +610,7 @@ variable [DecidableEq α] instance isRotatedDecidable (l l' : List α) : Decidable (l ~r l') := decidable_of_iff' _ isRotated_iff_mem_map_range -instance {l l' : List α} : Decidable (@Setoid.r _ (IsRotated.setoid α) l l') := +instance {l l' : List α} : Decidable (IsRotated.setoid α l l') := List.isRotatedDecidable _ _ end Decidable diff --git a/Mathlib/Data/List/Sort.lean b/Mathlib/Data/List/Sort.lean index 6936029a0217b..be93169d29b88 100644 --- a/Mathlib/Data/List/Sort.lean +++ b/Mathlib/Data/List/Sort.lean @@ -123,8 +123,8 @@ theorem eq_of_perm_of_sorted [IsAntisymm α r] {l₁ l₂ : List α} (hp : l₁ congr have : ∀ x ∈ u₂, x = a := fun x 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] <;> + rw [(@eq_replicate_iff _ a (length u₂ + 1) (a :: u₂)).2, + (@eq_replicate_iff _ a (length u₂ + 1) (u₂ ++ [a])).2] <;> constructor <;> simp [iff_true_intro this, or_comm] @@ -149,7 +149,7 @@ theorem Sorted.rel_of_mem_take_of_mem_drop {l : List α} (h : List.Sorted r l) { (hx : x ∈ List.take k l) (hy : y ∈ List.drop k l) : r x y := by obtain ⟨iy, hiy, rfl⟩ := getElem_of_mem hy obtain ⟨ix, hix, rfl⟩ := getElem_of_mem hx - rw [getElem_take', getElem_drop] + rw [getElem_take, getElem_drop] rw [length_take] at hix exact h.rel_get_of_lt (Nat.lt_add_right _ (Nat.lt_min.mp hix).left) @@ -198,6 +198,10 @@ def orderedInsert (a : α) : List α → List α | [] => [a] | b :: l => if a ≼ b then a :: b :: l else b :: orderedInsert a l +theorem orderedInsert_of_le {a b : α} (l : List α) (h : a ≼ b) : + orderedInsert r a (b :: l) = a :: b :: l := + dif_pos h + /-- `insertionSort l` returns `l` sorted using the insertion sort algorithm. -/ @[simp] def insertionSort : List α → List α @@ -281,6 +285,17 @@ theorem mem_insertionSort {l : List α} {x : α} : x ∈ l.insertionSort r ↔ x theorem length_insertionSort (l : List α) : (insertionSort r l).length = l.length := (perm_insertionSort r _).length_eq +theorem insertionSort_cons {a : α} {l : List α} (h : ∀ b ∈ l, r a b) : + insertionSort r (a :: l) = a :: insertionSort r l := by + rw [insertionSort] + cases hi : insertionSort r l with + | nil => rfl + | cons b m => + rw [orderedInsert_of_le] + apply h b <| (mem_insertionSort r).1 _ + rw [hi] + exact mem_cons_self b m + theorem map_insertionSort (f : α → β) (l : List α) (hl : ∀ a ∈ l, ∀ b ∈ l, a ≼ b ↔ f a ≼ f b) : (l.insertionSort r).map f = (l.map f).insertionSort s := by induction l with @@ -345,6 +360,40 @@ theorem sublist_orderedInsert (x : α) (xs : List α) : xs <+ xs.orderedInsert r refine Sublist.trans ?_ (.append_left (.cons _ (.refl _)) _) rw [takeWhile_append_dropWhile] +theorem cons_sublist_orderedInsert {l c : List α} {a : α} (hl : c <+ l) (ha : ∀ a' ∈ c, a ≼ a') : + a :: c <+ orderedInsert r a l := by + induction l with + | nil => simp_all only [sublist_nil, orderedInsert, Sublist.refl] + | cons _ _ ih => + unfold orderedInsert + split_ifs with hr + · exact .cons₂ _ hl + · cases hl with + | cons _ h => exact .cons _ <| ih h + | cons₂ => exact absurd (ha _ <| mem_cons_self ..) hr + +theorem Sublist.orderedInsert_sublist [IsTrans α r] {as bs} (x) (hs : as <+ bs) (hb : bs.Sorted r) : + orderedInsert r x as <+ orderedInsert r x bs := by + cases as with + | nil => simp + | cons a as => + cases bs with + | nil => contradiction + | cons b bs => + unfold orderedInsert + cases hs <;> split_ifs with hr + · exact .cons₂ _ <| .cons _ ‹a :: as <+ bs› + · have ih := orderedInsert_sublist x ‹a :: as <+ bs› hb.of_cons + simp only [hr, orderedInsert, ite_true] at ih + exact .trans ih <| .cons _ (.refl _) + · have hba := pairwise_cons.mp hb |>.left _ (mem_of_cons_sublist ‹a :: as <+ bs›) + exact absurd (trans_of _ ‹r x b› hba) hr + · have ih := orderedInsert_sublist x ‹a :: as <+ bs› hb.of_cons + rw [orderedInsert, if_neg hr] at ih + exact .cons _ ih + · simp_all only [sorted_cons, cons_sublist_cons] + · exact .cons₂ _ <| orderedInsert_sublist x ‹as <+ bs› hb.of_cons + section TotalAndTransitive variable [IsTotal α r] [IsTrans α r] @@ -374,6 +423,59 @@ theorem sorted_insertionSort : ∀ l, Sorted r (insertionSort r l) end TotalAndTransitive +/-- +If `c` is a sorted sublist of `l`, then `c` is still a sublist of `insertionSort r l`. +-/ +theorem sublist_insertionSort {l c : List α} (hr : c.Pairwise r) (hc : c <+ l) : + c <+ insertionSort r l := by + induction l generalizing c with + | nil => simp_all only [sublist_nil, insertionSort, Sublist.refl] + | cons _ _ ih => + cases hc with + | cons _ h => exact ih hr h |>.trans (sublist_orderedInsert ..) + | cons₂ _ h => + obtain ⟨hr, hp⟩ := pairwise_cons.mp hr + exact cons_sublist_orderedInsert (ih hp h) hr + +/-- +Another statement of stability of insertion sort. +If a pair `[a, b]` is a sublist of `l` and `r a b`, +then `[a, b]` is still a sublist of `insertionSort r l`. +-/ +theorem pair_sublist_insertionSort {a b : α} {l : List α} (hab : r a b) (h : [a, b] <+ l) : + [a, b] <+ insertionSort r l := + sublist_insertionSort (pairwise_pair.mpr hab) h + +variable [IsAntisymm α r] [IsTotal α r] [IsTrans α r] + +/-- +A version of `insertionSort_stable` which only assumes `c <+~ l` (instead of `c <+ l`), but +additionally requires `IsAntisymm α r`, `IsTotal α r` and `IsTrans α r`. +-/ +theorem sublist_insertionSort' {l c : List α} (hs : c.Sorted r) (hc : c <+~ l) : + c <+ insertionSort r l := by + classical + obtain ⟨d, hc, hd⟩ := hc + induction l generalizing c d with + | nil => simp_all only [sublist_nil, insertionSort, nil_perm] + | cons a _ ih => + cases hd with + | cons _ h => exact ih hs _ hc h |>.trans (sublist_orderedInsert ..) + | cons₂ _ h => + specialize ih (hs.erase _) _ (erase_cons_head a ‹List _› ▸ hc.erase a) h + have hm := hc.mem_iff.mp <| mem_cons_self .. + have he := orderedInsert_erase _ _ hm hs + exact he ▸ Sublist.orderedInsert_sublist _ ih (sorted_insertionSort ..) + +/-- +Another statement of stability of insertion sort. +If a pair `[a, b]` is a sublist of a permutation of `l` and `a ≼ b`, +then `[a, b]` is still a sublist of `insertionSort r l`. +-/ +theorem pair_sublist_insertionSort' {a b : α} {l : List α} (hab : a ≼ b) (h : [a, b] <+~ l) : + [a, b] <+ insertionSort r l := + sublist_insertionSort' (pairwise_pair.mpr hab) h + end Correctness end InsertionSort @@ -447,12 +549,12 @@ def mergeSort' : List α → List α let ls := (split (a :: b :: l)) have := length_split_fst_le l have := length_split_snd_le l - exact merge (r · ·) (mergeSort' ls.1) (mergeSort' ls.2) + exact merge (mergeSort' ls.1) (mergeSort' ls.2) (r · ·) termination_by l => length l @[nolint unusedHavesSuffices] -- Porting note: false positive theorem mergeSort'_cons_cons {a b} {l l₁ l₂ : List α} (h : split (a :: b :: l) = (l₁, l₂)) : - mergeSort' r (a :: b :: l) = merge (r · ·) (mergeSort' r l₁) (mergeSort' r l₂) := by + mergeSort' r (a :: b :: l) = merge (mergeSort' r l₁) (mergeSort' r l₂) (r · ·) := by simp only [mergeSort', h] section Correctness @@ -481,13 +583,13 @@ section TotalAndTransitive variable {r} [IsTotal α r] [IsTrans α r] -theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sorted r (merge (r · ·) l l') +theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sorted r (merge l l' (r · ·) ) | [], [], _, _ => by simp | [], b :: l', _, h₂ => by simpa using h₂ | a :: l, [], h₁, _ => by simpa using h₁ | a :: l, b :: l', h₁, h₂ => by by_cases h : a ≼ b - · suffices ∀ b' ∈ List.merge (r · ·) l (b :: l'), r a b' by + · suffices ∀ b' ∈ List.merge l (b :: l') (r · ·) , r a b' by simpa [h, h₁.of_cons.merge h₂] intro b' bm rcases show b' = b ∨ b' ∈ l ∨ b' ∈ l' by @@ -497,7 +599,7 @@ theorem Sorted.merge : ∀ {l l' : List α}, Sorted r l → Sorted r l' → Sort assumption · exact rel_of_sorted_cons h₁ _ bl · exact _root_.trans h (rel_of_sorted_cons h₂ _ bl') - · suffices ∀ b' ∈ List.merge (r · ·) (a :: l) l', r b b' by + · suffices ∀ b' ∈ List.merge (a :: l) l' (r · ·) , r b b' by simpa [h, h₁.merge h₂.of_cons] intro b' bm have ba : b ≼ a := (total_of r _ _).resolve_left h @@ -538,24 +640,6 @@ theorem mergeSort'_nil : [].mergeSort' r = [] := by rw [List.mergeSort'] @[simp] theorem mergeSort'_singleton (a : α) : [a].mergeSort' r = [a] := by rw [List.mergeSort'] -theorem map_merge (f : α → β) (r : α → α → Bool) (s : β → β → Bool) (l l' : List α) - (hl : ∀ a ∈ l, ∀ b ∈ l', r a b = s (f a) (f b)) : - (l.merge r l').map f = (l.map f).merge s (l'.map f) := by - match l, l' with - | [], x' => simp - | x, [] => simp - | x :: xs, x' :: xs' => - simp_rw [List.forall_mem_cons, forall_and] at hl - simp_rw [List.map, List.cons_merge_cons] - rw [← hl.1.1] - split - · rw [List.map, map_merge _ r s, List.map] - simp_rw [List.forall_mem_cons, forall_and] - exact ⟨hl.2.1, hl.2.2⟩ - · rw [List.map, map_merge _ r s, List.map] - simp_rw [List.forall_mem_cons] - exact ⟨hl.1.2, hl.2.2⟩ - theorem map_mergeSort' (f : α → β) (l : List α) (hl : ∀ a ∈ l, ∀ b ∈ l, a ≼ b ↔ f a ≼ f b) : (l.mergeSort' r).map f = (l.map f).mergeSort' s := match l with @@ -572,7 +656,7 @@ theorem map_mergeSort' (f : α → β) (l : List α) (hl : ∀ a ∈ l, ∀ b have := length_split_snd_le l simp_rw [List.map] rw [List.mergeSort'_cons_cons _ e, List.mergeSort'_cons_cons _ fe, - map_merge _ (r · ·) (s · ·), map_mergeSort' _ l₁ hl.1.1, map_mergeSort' _ l₂ hl.2.2] + map_merge, map_mergeSort' _ l₁ hl.1.1, map_mergeSort' _ l₂ hl.2.2] simp_rw [mem_mergeSort', decide_eq_decide] exact hl.1.2 termination_by length l diff --git a/Mathlib/Data/List/Sublists.lean b/Mathlib/Data/List/Sublists.lean index 8eac342a35b41..3d8300bd2d98a 100644 --- a/Mathlib/Data/List/Sublists.lean +++ b/Mathlib/Data/List/Sublists.lean @@ -44,7 +44,7 @@ theorem sublists'Aux_eq_array_foldl (a : α) : ∀ (r₁ r₂ : List (List α)), sublists'Aux a r₁ r₂ = ((r₁.toArray).foldl (init := r₂.toArray) (fun r l => r.push (a :: l))).toList := by intro r₁ r₂ - rw [sublists'Aux, Array.foldl_eq_foldl_data] + rw [sublists'Aux, Array.foldl_eq_foldl_toList] have := List.foldl_hom Array.toList (fun r l => r.push (a :: l)) (fun r l => r ++ [a :: l]) r₁ r₂.toArray (by simp) simpa using this @@ -53,8 +53,7 @@ theorem sublists'_eq_sublists'Aux (l : List α) : sublists' l = l.foldr (fun a r => sublists'Aux a r r) [[]] := by simp only [sublists', sublists'Aux_eq_array_foldl] rw [← List.foldr_hom Array.toList] - · rfl - · intros _ _; congr <;> simp + · intros _ _; congr theorem sublists'Aux_eq_map (a : α) (r₁ : List (List α)) : ∀ (r₂ : List (List α)), sublists'Aux a r₁ r₂ = r₂ ++ map (cons a) r₁ := @@ -107,7 +106,7 @@ theorem sublistsAux_eq_array_foldl : (r.toArray.foldl (init := #[]) fun r l => (r.push l).push (a :: l)).toList := by funext a r - simp only [sublistsAux, Array.foldl_eq_foldl_data, Array.mkEmpty] + simp only [sublistsAux, Array.foldl_eq_foldl_toList, Array.mkEmpty] have := foldl_hom Array.toList (fun r l => (r.push l).push (a :: l)) (fun (r : List (List α)) l => r ++ [l, a :: l]) r #[] (by simp) @@ -126,10 +125,9 @@ theorem sublistsAux_eq_bind : ext α l : 2 trans l.foldr sublistsAux [[]] · rw [sublistsAux_eq_bind, sublists] - · simp only [sublistsFast, sublistsAux_eq_array_foldl, Array.foldr_eq_foldr_data] + · simp only [sublistsFast, sublistsAux_eq_array_foldl, Array.foldr_eq_foldr_toList] rw [← foldr_hom Array.toList] - · rfl - · intros _ _; congr <;> simp + · intros _ _; congr theorem sublists_append (l₁ l₂ : List α) : sublists (l₁ ++ l₂) = (sublists l₂) >>= (fun x => (sublists l₁).map (· ++ x)) := by diff --git a/Mathlib/Data/List/Sym.lean b/Mathlib/Data/List/Sym.lean index 80954c1ad9dc7..1d6228b9258e3 100644 --- a/Mathlib/Data/List/Sym.lean +++ b/Mathlib/Data/List/Sym.lean @@ -237,7 +237,7 @@ theorem sym_one_eq : xs.sym 1 = xs.map (· ::ₛ .nil) := by theorem sym2_eq_sym_two : xs.sym2.map (Sym2.equivSym α) = xs.sym 2 := by induction xs with - | nil => simp only [List.sym, map_eq_nil, sym2_eq_nil_iff] + | nil => simp only [List.sym, map_eq_nil_iff, sym2_eq_nil_iff] | cons x xs ih => rw [List.sym, ← ih, sym_one_eq, map_map, List.sym2, map_append, map_map] rfl diff --git a/Mathlib/Data/MLList/Dedup.lean b/Mathlib/Data/MLList/Dedup.lean index f608048a51890..736453f47d9f1 100644 --- a/Mathlib/Data/MLList/Dedup.lean +++ b/Mathlib/Data/MLList/Dedup.lean @@ -36,7 +36,6 @@ def dedupBy (L : MLList m α) (f : α → m β) : MLList m α := /-- Lazily deduplicate a lazy list, using a stored `HashMap`. -/ @[deprecated "See deprecation note in module documentation." (since := "2024-08-22")] -def dedup (L : MLList m β) : MLList m β := - L.dedupBy (fun b => pure b) +def dedup (L : MLList m β) : MLList m β := L.dedupBy pure end MLList diff --git a/Mathlib/Data/Matrix/Basic.lean b/Mathlib/Data/Matrix/Basic.lean index dfb96ff464262..63bc543ba910b 100644 --- a/Mathlib/Data/Matrix/Basic.lean +++ b/Mathlib/Data/Matrix/Basic.lean @@ -492,6 +492,11 @@ theorem diagonal_conjTranspose [AddMonoid α] [StarAddMonoid α] (v : n → α) rw [conjTranspose, diagonal_transpose, diagonal_map (star_zero _)] rfl +theorem diagonal_unique [Unique m] [DecidableEq m] [Zero α] (d : m → α) : + diagonal d = of fun _ _ => d default := by + ext i j + rw [Subsingleton.elim i default, Subsingleton.elim j default, diagonal_apply_eq _ _, of_apply] + section One variable [Zero α] [One α] @@ -2093,7 +2098,6 @@ variants which this lemma would not apply to: * `Matrix.conjTranspose_intCast_smul` * `Matrix.conjTranspose_inv_natCast_smul` * `Matrix.conjTranspose_inv_intCast_smul` -* `Matrix.conjTranspose_rat_smul` * `Matrix.conjTranspose_ratCast_smul` -/ @[simp] @@ -2161,7 +2165,6 @@ theorem conjTranspose_ratCast_smul [DivisionRing R] [AddCommGroup α] [StarAddMo (c : ℚ) (M : Matrix m n α) : ((c : R) • M)ᴴ = (c : R) • Mᴴ := Matrix.ext <| by simp -@[simp] theorem conjTranspose_rat_smul [AddCommGroup α] [StarAddMonoid α] [Module ℚ α] (c : ℚ) (M : Matrix m n α) : (c • M)ᴴ = c • Mᴴ := Matrix.ext <| by simp diff --git a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean index 6961195e3a83e..1fef44043ba64 100644 --- a/Mathlib/Data/Matrix/ColumnRowPartitioned.lean +++ b/Mathlib/Data/Matrix/ColumnRowPartitioned.lean @@ -258,17 +258,8 @@ lemma fromColumns_mul_fromRows_eq_one_comm [Fintype n₁] [Fintype n₂] [Fintype n] [DecidableEq n] [DecidableEq n₁] [DecidableEq n₂] (e : n ≃ n₁ ⊕ n₂) (A₁ : Matrix n n₁ R) (A₂ : Matrix n n₂ R) (B₁ : Matrix n₁ n R) (B₂ : Matrix n₂ n R) : - fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := by - calc fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 - _ ↔ submatrix (fromColumns A₁ A₂) id e * submatrix (fromRows B₁ B₂) e id = 1 := by - simp - _ ↔ submatrix (fromRows B₁ B₂) e id * submatrix (fromColumns A₁ A₂) id e = 1 := - mul_eq_one_comm - _ ↔ reindex e.symm e.symm (fromRows B₁ B₂ * fromColumns A₁ A₂) = reindex e.symm e.symm 1 := by - simp only [reindex_apply, Equiv.symm_symm, submatrix_one_equiv, - submatrix_mul (he₂ := Function.bijective_id)] - _ ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := - (reindex _ _).injective.eq_iff + fromColumns A₁ A₂ * fromRows B₁ B₂ = 1 ↔ fromRows B₁ B₂ * fromColumns A₁ A₂ = 1 := + mul_eq_one_comm_of_equiv e /-- The lemma `fromColumns_mul_fromRows_eq_one_comm` specialized to the case where the index sets n₁ and n₂, are the result of subtyping by a predicate and its complement. -/ diff --git a/Mathlib/Data/Matrix/DMatrix.lean b/Mathlib/Data/Matrix/DMatrix.lean index d677b3ace646e..2b482b6e0ee61 100644 --- a/Mathlib/Data/Matrix/DMatrix.lean +++ b/Mathlib/Data/Matrix/DMatrix.lean @@ -20,7 +20,7 @@ In most applications `m` and `n` are finite types. -/ def DMatrix (m : Type u) (n : Type u') (α : m → n → Type v) : Type max u u' v := ∀ i j, α i j -variable {l m n o : Type*} +variable {m n : Type*} variable {α : m → n → Type v} namespace DMatrix diff --git a/Mathlib/Data/Matrix/DoublyStochastic.lean b/Mathlib/Data/Matrix/DoublyStochastic.lean new file mode 100644 index 0000000000000..8bc91f3996116 --- /dev/null +++ b/Mathlib/Data/Matrix/DoublyStochastic.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2024 Bhavik Mehta. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bhavik Mehta +-/ + +import Mathlib.Analysis.Convex.Basic +import Mathlib.LinearAlgebra.Matrix.Permutation + +/-! +# Doubly stochastic matrices + +## Main definitions + +* `doublyStochastic`: a square matrix is doubly stochastic if all entries are nonnegative, and left + or right multiplication by the vector of all 1s gives the vector of all 1s. Equivalently, all + row and column sums are equal to 1. + +## Main statements + +* `convex_doublyStochastic`: The set of doubly stochastic matrices is convex. +* `permMatrix_mem_doublyStochastic`: Any permutation matrix is doubly stochastic. + +## TODO + +Define the submonoids of row-stochastic and column-stochastic matrices. +Show that the submonoid of doubly stochastic matrices is the meet of them, or redefine it as such. + +## Tags + +Doubly stochastic, Birkhoff's theorem, Birkhoff-von Neumann theorem +-/ + +open Finset Function Matrix + +variable {R n : Type*} [Fintype n] [DecidableEq n] + +section OrderedSemiring +variable [OrderedSemiring R] {M : Matrix n n R} + +/-- +A square matrix is doubly stochastic iff all entries are nonnegative, and left or right +multiplication by the vector of all 1s gives the vector of all 1s. +-/ +def doublyStochastic (R n : Type*) [Fintype n] [DecidableEq n] [OrderedSemiring R] : + Submonoid (Matrix n n R) where + carrier := {M | (∀ i j, 0 ≤ M i j) ∧ M *ᵥ 1 = 1 ∧ 1 ᵥ* M = 1 } + mul_mem' {M N} hM hN := by + refine ⟨fun i j => sum_nonneg fun i _ => mul_nonneg (hM.1 _ _) (hN.1 _ _), ?_, ?_⟩ + next => rw [← mulVec_mulVec, hN.2.1, hM.2.1] + next => rw [← vecMul_vecMul, hM.2.2, hN.2.2] + one_mem' := by simp [zero_le_one_elem] + +lemma mem_doublyStochastic : + M ∈ doublyStochastic R n ↔ (∀ i j, 0 ≤ M i j) ∧ M *ᵥ 1 = 1 ∧ 1 ᵥ* M = 1 := + Iff.rfl + +lemma mem_doublyStochastic_iff_sum : + M ∈ doublyStochastic R n ↔ + (∀ i j, 0 ≤ M i j) ∧ (∀ i, ∑ j, M i j = 1) ∧ ∀ j, ∑ i, M i j = 1 := by + simp [funext_iff, doublyStochastic, mulVec, vecMul, dotProduct] + +/-- Every entry of a doubly stochastic matrix is nonnegative. -/ +lemma nonneg_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) {i j : n} : 0 ≤ M i j := + hM.1 _ _ + +/-- Each row sum of a doubly stochastic matrix is 1. -/ +lemma sum_row_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) (i : n) : ∑ j, M i j = 1 := + (mem_doublyStochastic_iff_sum.1 hM).2.1 _ + +/-- Each column sum of a doubly stochastic matrix is 1. -/ +lemma sum_col_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) (j : n) : ∑ i, M i j = 1 := + (mem_doublyStochastic_iff_sum.1 hM).2.2 _ + +/-- A doubly stochastic matrix multiplied with the all-ones column vector is 1. -/ +lemma mulVec_one_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) : M *ᵥ 1 = 1 := + (mem_doublyStochastic.1 hM).2.1 + +/-- The all-ones row vector multiplied with a doubly stochastic matrix is 1. -/ +lemma one_vecMul_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) : 1 ᵥ* M = 1 := + (mem_doublyStochastic.1 hM).2.2 + +/-- Every entry of a doubly stochastic matrix is less than or equal to 1. -/ +lemma le_one_of_mem_doublyStochastic (hM : M ∈ doublyStochastic R n) {i j : n} : + M i j ≤ 1 := by + rw [← sum_row_of_mem_doublyStochastic hM i] + exact single_le_sum (fun k _ => hM.1 _ k) (mem_univ j) + +/-- The set of doubly stochastic matrices is convex. -/ +lemma convex_doublyStochastic : Convex R (doublyStochastic R n : Set (Matrix n n R)) := by + intro x hx y hy a b ha hb h + simp only [SetLike.mem_coe, mem_doublyStochastic_iff_sum] at hx hy ⊢ + simp [add_nonneg, ha, hb, mul_nonneg, hx, hy, sum_add_distrib, ← mul_sum, h] + +/-- Any permutation matrix is doubly stochastic. -/ +lemma permMatrix_mem_doublyStochastic {σ : Equiv.Perm n} : + σ.permMatrix R ∈ doublyStochastic R n := by + rw [mem_doublyStochastic_iff_sum] + refine ⟨fun i j => ?g1, ?g2, ?g3⟩ + case g1 => aesop + case g2 => simp [Equiv.toPEquiv_apply] + case g3 => simp [Equiv.toPEquiv_apply, ← Equiv.eq_symm_apply] + +end OrderedSemiring + +section LinearOrderedSemifield + +variable [LinearOrderedSemifield R] {M : Matrix n n R} + +/-- +A matrix is `s` times a doubly stochastic matrix iff all entries are nonnegative, and all row and +column sums are equal to `s`. + +This lemma is useful for the proof of Birkhoff's theorem - in particular because it allows scaling +by nonnegative factors rather than positive ones only. +-/ +lemma exists_mem_doublyStochastic_eq_smul_iff {M : Matrix n n R} {s : R} (hs : 0 ≤ s) : + (∃ M' ∈ doublyStochastic R n, M = s • M') ↔ + (∀ i j, 0 ≤ M i j) ∧ (∀ i, ∑ j, M i j = s) ∧ (∀ j, ∑ i, M i j = s) := by + classical + constructor + case mp => + rintro ⟨M', hM', rfl⟩ + rw [mem_doublyStochastic_iff_sum] at hM' + simp only [smul_apply, smul_eq_mul, ← mul_sum] + exact ⟨fun i j => mul_nonneg hs (hM'.1 _ _), by simp [hM']⟩ + rcases eq_or_lt_of_le hs with rfl | hs + case inl => + simp only [zero_smul, exists_and_right, and_imp] + intro h₁ h₂ _ + refine ⟨⟨1, Submonoid.one_mem _⟩, ?_⟩ + ext i j + specialize h₂ i + rw [sum_eq_zero_iff_of_nonneg (by simp [h₁ i])] at h₂ + exact h₂ _ (by simp) + rintro ⟨hM₁, hM₂, hM₃⟩ + exact ⟨s⁻¹ • M, by simp [mem_doublyStochastic_iff_sum, ← mul_sum, hs.ne', inv_mul_cancel₀, *]⟩ + +end LinearOrderedSemifield diff --git a/Mathlib/Data/Matrix/Invertible.lean b/Mathlib/Data/Matrix/Invertible.lean index 5b38bcb33b6e3..d5581bd17d0de 100644 --- a/Mathlib/Data/Matrix/Invertible.lean +++ b/Mathlib/Data/Matrix/Invertible.lean @@ -1,9 +1,10 @@ /- Copyright (c) 2023 Eric Wieser. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Eric Wieser +Authors: Eric Wieser, Ahmad Alkhalawi -/ import Mathlib.Data.Matrix.Basic +import Mathlib.Tactic.Abel /-! # Extra lemmas about invertible matrices @@ -47,10 +48,14 @@ protected theorem invOf_mul_cancel_right (A : Matrix m n α) (B : Matrix n n α) protected theorem mul_invOf_cancel_right (A : Matrix m n α) (B : Matrix n n α) [Invertible B] : A * B * ⅟ B = A := by rw [Matrix.mul_assoc, mul_invOf_self, Matrix.mul_one] -@[deprecated (since := "2024-09-07")] alias invOf_mul_self_assoc := invOf_mul_cancel_left -@[deprecated (since := "2024-09-07")] alias mul_invOf_self_assoc := mul_invOf_cancel_left -@[deprecated (since := "2024-09-07")] alias mul_invOf_mul_self_cancel := invOf_mul_cancel_right -@[deprecated (since := "2024-09-07")] alias mul_mul_invOf_self_cancel := mul_invOf_cancel_right +@[deprecated (since := "2024-09-07")] +protected alias invOf_mul_self_assoc := Matrix.invOf_mul_cancel_left +@[deprecated (since := "2024-09-07")] +protected alias mul_invOf_self_assoc := Matrix.mul_invOf_cancel_left +@[deprecated (since := "2024-09-07")] +protected alias mul_invOf_mul_self_cancel := Matrix.invOf_mul_cancel_right +@[deprecated (since := "2024-09-07")] +protected alias mul_mul_invOf_self_cancel := Matrix.mul_invOf_cancel_right section ConjTranspose variable [StarRing α] (A : Matrix n n α) @@ -106,4 +111,68 @@ def transposeInvertibleEquivInvertible : Invertible Aᵀ ≃ Invertible A where end CommSemiring +section Ring + +section Woodbury + +variable [Fintype m] [DecidableEq m] [Ring α] + (A : Matrix n n α) (U : Matrix n m α) (C : Matrix m m α) (V : Matrix m n α) + [Invertible A] [Invertible C] [Invertible (⅟C + V * ⅟A * U)] + +-- No spaces around multiplication signs for better clarity +lemma add_mul_mul_invOf_mul_eq_one : + (A + U*C*V)*(⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) = 1 := by + calc + (A + U*C*V)*(⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) + _ = A*⅟A - A*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A + U*C*V*⅟A - U*C*V*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A := by + simp_rw [add_sub_assoc, add_mul, mul_sub, Matrix.mul_assoc] + _ = (1 + U*C*V*⅟A) - (U*⅟(⅟C + V*⅟A*U)*V*⅟A + U*C*V*⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A) := by + rw [mul_invOf_self, Matrix.one_mul] + abel + _ = 1 + U*C*V*⅟A - (U + U*C*V*⅟A*U)*⅟(⅟C + V*⅟A*U)*V*⅟A := by + rw [sub_right_inj, Matrix.add_mul, Matrix.add_mul, Matrix.add_mul] + _ = 1 + U*C*V*⅟A - U*C*(⅟C + V*⅟A*U)*⅟(⅟C + V*⅟A*U)*V*⅟A := by + congr + simp only [Matrix.mul_add, Matrix.mul_invOf_cancel_right, ← Matrix.mul_assoc] + _ = 1 := by + rw [Matrix.mul_invOf_cancel_right] + abel + +/-- Like `add_mul_mul_invOf_mul_eq_one`, but with multiplication reversed. -/ +lemma add_mul_mul_invOf_mul_eq_one' : + (⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A)*(A + U*C*V) = 1 := by + calc + (⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A)*(A + U*C*V) + _ = ⅟A*A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*A + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*U*C*V := by + simp_rw [add_sub_assoc, _root_.mul_add, _root_.sub_mul, Matrix.mul_assoc] + _ = (1 + ⅟A*U*C*V) - (⅟A*U*⅟(⅟C + V*⅟A*U)*V + ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A*U*C*V) := by + rw [invOf_mul_self, Matrix.invOf_mul_cancel_right] + abel + _ = 1 + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*(V + V*⅟A*U*C*V) := by + rw [sub_right_inj, Matrix.mul_add] + simp_rw [Matrix.mul_assoc] + _ = 1 + ⅟A*U*C*V - ⅟A*U*⅟(⅟C + V*⅟A*U)*(⅟C + V*⅟A*U)*C*V := by + congr 1 + simp only [Matrix.mul_add, Matrix.add_mul, ← Matrix.mul_assoc, + Matrix.invOf_mul_cancel_right] + _ = 1 := by + rw [Matrix.invOf_mul_cancel_right] + abel + +/-- If matrices `A`, `C`, and `C⁻¹ + V * A⁻¹ * U` are invertible, then so is `A + U * C * V`-/ +def invertibleAddMulMul : Invertible (A + U*C*V) where + invOf := ⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A + invOf_mul_self := add_mul_mul_invOf_mul_eq_one' _ _ _ _ + mul_invOf_self := add_mul_mul_invOf_mul_eq_one _ _ _ _ + +/-- The **Woodbury Identity** (`⅟` version). -/ +theorem invOf_add_mul_mul [Invertible (A + U*C*V)] : + ⅟(A + U*C*V) = ⅟A - ⅟A*U*⅟(⅟C + V*⅟A*U)*V*⅟A := by + letI := invertibleAddMulMul A U C V + convert (rfl : ⅟(A + U*C*V) = _) + +end Woodbury + +end Ring + end Matrix diff --git a/Mathlib/Data/Matrix/Rank.lean b/Mathlib/Data/Matrix/Rank.lean index d272ff6eb228a..13db0d03e2bc9 100644 --- a/Mathlib/Data/Matrix/Rank.lean +++ b/Mathlib/Data/Matrix/Rank.lean @@ -26,7 +26,7 @@ open Matrix namespace Matrix -open FiniteDimensional +open Module variable {l m n o R : Type*} [Fintype n] [Fintype o] @@ -168,7 +168,7 @@ variable [Field R] /-- The rank of a diagnonal matrix is the count of non-zero elements on its main diagonal -/ theorem rank_diagonal [Fintype m] [DecidableEq m] [DecidableEq R] (w : m → R) : (diagonal w).rank = Fintype.card {i // (w i) ≠ 0} := by - rw [Matrix.rank, ← Matrix.toLin'_apply', FiniteDimensional.finrank, ← LinearMap.rank, + rw [Matrix.rank, ← Matrix.toLin'_apply', Module.finrank, ← LinearMap.rank, LinearMap.rank_diagonal, Cardinal.toNat_natCast] end Field @@ -278,7 +278,7 @@ lemma rank_add_rank_le_card_of_mul_eq_zero [Field R] [Finite l] [Fintype m] let en : Basis n R (n → R) := Pi.basisFun R n rw [Matrix.rank_eq_finrank_range_toLin A el em, Matrix.rank_eq_finrank_range_toLin B em en, - ← FiniteDimensional.finrank_fintype_fun_eq_card R, + ← Module.finrank_fintype_fun_eq_card R, ← LinearMap.finrank_range_add_finrank_ker (Matrix.toLin em el A), add_le_add_iff_left] apply Submodule.finrank_mono diff --git a/Mathlib/Data/Matrix/RowCol.lean b/Mathlib/Data/Matrix/RowCol.lean index 2529d88fd19ee..6ce7feb0bcaa5 100644 --- a/Mathlib/Data/Matrix/RowCol.lean +++ b/Mathlib/Data/Matrix/RowCol.lean @@ -136,6 +136,16 @@ theorem row_mulVec [Fintype n] [NonUnitalNonAssocSemiring α] (M : Matrix m n α ext rfl +theorem row_mulVec_eq_const [Fintype m] [NonUnitalNonAssocSemiring α] (v w : m → α) : + Matrix.row ι v *ᵥ w = Function.const _ (v ⬝ᵥ w) := rfl + +theorem mulVec_col_eq_const [Fintype m] [NonUnitalNonAssocSemiring α] (v w : m → α) : + v ᵥ* Matrix.col ι w = Function.const _ (v ⬝ᵥ w) := rfl + +theorem row_mul_col [Fintype m] [Mul α] [AddCommMonoid α] (v w : m → α) : + row ι v * col ι w = of fun _ _ => v ⬝ᵥ w := + rfl + @[simp] theorem row_mul_col_apply [Fintype m] [Mul α] [AddCommMonoid α] (v w : m → α) (i j) : (row ι v * col ι w) i j = v ⬝ᵥ w := diff --git a/Mathlib/Data/Multiset/Basic.lean b/Mathlib/Data/Multiset/Basic.lean index 9cd7fc8586622..0c4fb024e449e 100644 --- a/Mathlib/Data/Multiset/Basic.lean +++ b/Mathlib/Data/Multiset/Basic.lean @@ -528,6 +528,11 @@ theorem le_cons_of_not_mem (m : a ∉ s) : s ≤ a ::ₘ t ↔ s ≤ t := by perm_middle.subperm_left.2 ((subperm_cons _).2 <| ((sublist_or_mem_of_sublist s).resolve_right m₁).subperm) +theorem cons_le_of_not_mem (hs : a ∉ s) : a ::ₘ s ≤ t ↔ a ∈ t ∧ s ≤ t := by + apply Iff.intro (fun h ↦ ⟨subset_of_le h (mem_cons_self a s), le_trans (le_cons_self s a) h⟩) + rintro ⟨h₁, h₂⟩; rcases exists_cons_of_mem h₁ with ⟨_, rfl⟩ + exact cons_le_cons _ ((le_cons_of_not_mem hs).mp h₂) + @[simp] theorem singleton_ne_zero (a : α) : ({a} : Multiset α) ≠ 0 := ne_of_gt (lt_cons_self _ _) @@ -601,6 +606,10 @@ theorem le_add_right (s t : Multiset α) : s ≤ s + t := by simpa using add_le_ theorem le_add_left (s t : Multiset α) : s ≤ t + s := by simpa using add_le_add_right (zero_le t) s +lemma subset_add_left {s t : Multiset α} : s ⊆ s + t := subset_of_le <| le_add_right s t + +lemma subset_add_right {s t : Multiset α} : s ⊆ t + s := subset_of_le <| le_add_left s t + theorem le_iff_exists_add {s t : Multiset α} : s ≤ t ↔ ∃ u, t = s + u := ⟨fun h => leInductionOn h fun s => @@ -1341,8 +1350,7 @@ theorem pmap_eq_map (p : α → Prop) (f : α → β) (s : Multiset α) : theorem pmap_congr {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a, q a → β} (s : Multiset α) : ∀ {H₁ H₂}, (∀ a ∈ s, ∀ (h₁ h₂), f a h₁ = g a h₂) → pmap f s H₁ = pmap g s H₂ := - @(Quot.inductionOn s (fun l _H₁ _H₂ h => congr_arg _ <| List.pmap_congr l h)) - + @(Quot.inductionOn s (fun l _H₁ _H₂ h => congr_arg _ <| List.pmap_congr_left l h)) theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (s) : ∀ H, map g (pmap f s H) = pmap (fun a h => g (f a h)) s H := @@ -1387,7 +1395,7 @@ theorem attach_cons (a : α) (m : Multiset α) : Quotient.inductionOn m fun l => congr_arg _ <| congr_arg (List.cons _) <| by - rw [List.map_pmap]; exact List.pmap_congr _ fun _ _ _ _ => Subtype.eq rfl + rw [List.map_pmap]; exact List.pmap_congr_left _ fun _ _ _ _ => Subtype.eq rfl section DecidablePiExists @@ -2013,11 +2021,11 @@ theorem countP_eq_countP_filter_add (s) (p q : α → Prop) [DecidablePred p] [D @[simp] theorem countP_True {s : Multiset α} : countP (fun _ => True) s = card s := - Quot.inductionOn s fun _l => List.countP_true + Quot.inductionOn s fun _l => congrFun List.countP_true _ @[simp] theorem countP_False {s : Multiset α} : countP (fun _ => False) s = 0 := - Quot.inductionOn s fun _l => List.countP_false + Quot.inductionOn s fun _l => congrFun List.countP_false _ theorem countP_map (f : α → β) (s : Multiset α) (p : β → Prop) [DecidablePred p] : countP p (map f s) = card (s.filter fun a => p (f a)) := by @@ -2046,7 +2054,7 @@ lemma filter_attach (s : Multiset α) (p : α → Prop) [DecidablePred p] : variable {p} theorem countP_pos {s} : 0 < countP p s ↔ ∃ a ∈ s, p a := - Quot.inductionOn s fun _l => by simpa using List.countP_pos (p ·) + Quot.inductionOn s fun _l => by simp theorem countP_eq_zero {s} : countP p s = 0 ↔ ∀ a ∈ s, ¬p a := Quot.inductionOn s fun _l => by simp [List.countP_eq_zero] @@ -2764,9 +2772,6 @@ theorem coe_subsingletonEquiv [Subsingleton α] : (subsingletonEquiv α : List α → Multiset α) = ofList := rfl -@[deprecated (since := "2023-12-27")] alias card_le_of_le := card_le_card -@[deprecated (since := "2023-12-27")] alias card_lt_of_lt := card_lt_card - end Multiset set_option linter.style.longFile 2900 diff --git a/Mathlib/Data/Multiset/Fintype.lean b/Mathlib/Data/Multiset/Fintype.lean index ee4962cb23b82..369c39be15028 100644 --- a/Mathlib/Data/Multiset/Fintype.lean +++ b/Mathlib/Data/Multiset/Fintype.lean @@ -217,8 +217,7 @@ theorem Multiset.card_coe (m : Multiset α) : Fintype.card m = Multiset.card m : @[to_additive] theorem Multiset.prod_eq_prod_coe [CommMonoid α] (m : Multiset α) : m.prod = ∏ x : m, (x : α) := by congr - -- Porting note: `simp` fails with "maximum recursion depth has been reached" - erw [map_univ_coe] + simp @[to_additive] theorem Multiset.prod_eq_prod_toEnumFinset [CommMonoid α] (m : Multiset α) : diff --git a/Mathlib/Data/Multiset/Functor.lean b/Mathlib/Data/Multiset/Functor.lean index 9c8f9ecbfb459..81575f5f445c4 100644 --- a/Mathlib/Data/Multiset/Functor.lean +++ b/Mathlib/Data/Multiset/Functor.lean @@ -99,7 +99,6 @@ theorem comp_traverse {G H : Type _ → Type _} [Applicative G] [Applicative H] intro simp only [traverse, quot_mk_to_coe, lift_coe, Coe.coe, Function.comp_apply, Functor.map_map, functor_norm] - simp only [Function.comp_def, lift_coe] theorem map_traverse {G : Type* → Type _} [Applicative G] [CommApplicative G] {α β γ : Type _} (g : α → G β) (h : β → γ) (x : Multiset α) : @@ -107,7 +106,8 @@ theorem map_traverse {G : Type* → Type _} [Applicative G] [CommApplicative G] refine Quotient.inductionOn x ?_ intro simp only [traverse, quot_mk_to_coe, lift_coe, Function.comp_apply, Functor.map_map, map_comp_coe] - rw [LawfulFunctor.comp_map, Traversable.map_traverse'] + rw [Traversable.map_traverse'] + simp only [fmap_def, Function.comp_apply, Functor.map_map, List.map_eq_map] rfl theorem traverse_map {G : Type* → Type _} [Applicative G] [CommApplicative G] {α β γ : Type _} diff --git a/Mathlib/Data/Multiset/Sort.lean b/Mathlib/Data/Multiset/Sort.lean index 545d09d151580..997af93b548c0 100644 --- a/Mathlib/Data/Multiset/Sort.lean +++ b/Mathlib/Data/Multiset/Sort.lean @@ -62,6 +62,11 @@ theorem map_sort (f : α → β) (s : Multiset α) revert s exact Quot.ind fun _ => List.map_mergeSort' _ _ _ _ +theorem sort_cons (a : α) (s : Multiset α) : + (∀ b ∈ s, r a b) → sort r (a ::ₘ s) = a :: sort r s := by + refine Quot.inductionOn s fun l => ?_ + simpa [mergeSort'_eq_insertionSort] using insertionSort_cons r + end sort -- TODO: use a sort order if available, gh-18166 diff --git a/Mathlib/Data/NNReal/Basic.lean b/Mathlib/Data/NNReal/Basic.lean index df15ccc645e66..bf80f11181f55 100644 --- a/Mathlib/Data/NNReal/Basic.lean +++ b/Mathlib/Data/NNReal/Basic.lean @@ -3,16 +3,13 @@ Copyright (c) 2018 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Algebra.Algebra.Defs +import Mathlib.Algebra.BigOperators.Expect import Mathlib.Algebra.Order.BigOperators.Ring.Finset import Mathlib.Algebra.Order.Field.Canonical.Basic -import Mathlib.Algebra.Order.Nonneg.Field import Mathlib.Algebra.Order.Nonneg.Floor +import Mathlib.Algebra.Ring.Regular import Mathlib.Data.Real.Pointwise import Mathlib.Order.ConditionallyCompleteLattice.Group -import Mathlib.Tactic.Bound.Attribute -import Mathlib.Tactic.GCongr.CoreAttrs -import Mathlib.Algebra.Ring.Regular /-! # Nonnegative real numbers @@ -55,6 +52,7 @@ This file defines `ℝ≥0` as a localized notation for `NNReal`. assert_not_exists Star open Function +open scoped BigOperators -- to ensure these instances are computable /-- Nonnegative real numbers. -/ @@ -278,22 +276,26 @@ theorem coe_multiset_sum (s : Multiset ℝ≥0) : ((s.sum : ℝ≥0) : ℝ) = (s theorem coe_multiset_prod (s : Multiset ℝ≥0) : ((s.prod : ℝ≥0) : ℝ) = (s.map (↑)).prod := map_multiset_prod toRealHom s +variable {ι : Type*} {s : Finset ι} {f : ι → ℝ} + @[simp, norm_cast] -theorem coe_sum {α} {s : Finset α} {f : α → ℝ≥0} : ↑(∑ a ∈ s, f a) = ∑ a ∈ s, (f a : ℝ) := +theorem coe_sum (s : Finset ι) (f : ι → ℝ≥0) : ∑ i ∈ s, f i = ∑ i ∈ s, (f i : ℝ) := map_sum toRealHom _ _ -theorem _root_.Real.toNNReal_sum_of_nonneg {α} {s : Finset α} {f : α → ℝ} - (hf : ∀ a, a ∈ s → 0 ≤ f a) : +@[simp, norm_cast] +lemma coe_expect (s : Finset ι) (f : ι → ℝ≥0) : 𝔼 i ∈ s, f i = 𝔼 i ∈ s, (f i : ℝ) := + map_expect toRealHom .. + +theorem _root_.Real.toNNReal_sum_of_nonneg (hf : ∀ i ∈ s, 0 ≤ f i) : Real.toNNReal (∑ a ∈ s, f a) = ∑ a ∈ s, Real.toNNReal (f a) := by rw [← coe_inj, NNReal.coe_sum, Real.coe_toNNReal _ (Finset.sum_nonneg hf)] exact Finset.sum_congr rfl fun x hxs => by rw [Real.coe_toNNReal _ (hf x hxs)] @[simp, norm_cast] -theorem coe_prod {α} {s : Finset α} {f : α → ℝ≥0} : ↑(∏ a ∈ s, f a) = ∏ a ∈ s, (f a : ℝ) := +theorem coe_prod (s : Finset ι) (f : ι → ℝ≥0) : ↑(∏ a ∈ s, f a) = ∏ a ∈ s, (f a : ℝ) := map_prod toRealHom _ _ -theorem _root_.Real.toNNReal_prod_of_nonneg {α} {s : Finset α} {f : α → ℝ} - (hf : ∀ a, a ∈ s → 0 ≤ f a) : +theorem _root_.Real.toNNReal_prod_of_nonneg (hf : ∀ a, a ∈ s → 0 ≤ f a) : Real.toNNReal (∏ a ∈ s, f a) = ∏ a ∈ s, Real.toNNReal (f a) := by rw [← coe_inj, NNReal.coe_prod, Real.coe_toNNReal _ (Finset.prod_nonneg hf)] exact Finset.prod_congr rfl fun x hxs => by rw [Real.coe_toNNReal _ (hf x hxs)] @@ -839,25 +841,25 @@ theorem div_le_of_le_mul' {a b c : ℝ≥0} (h : a ≤ b * c) : a / b ≤ c := @[deprecated le_div_iff₀ (since := "2024-08-21")] protected lemma le_div_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ a * r ≤ b := - le_div_iff₀ <| pos_iff_ne_zero.2 hr + le_div_iff₀ hr.bot_lt -nonrec theorem le_div_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ r * a ≤ b := - le_div_iff₀' <| pos_iff_ne_zero.2 hr +@[deprecated le_div_iff₀' (since := "2024-10-02")] +theorem le_div_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a ≤ b / r ↔ r * a ≤ b := le_div_iff₀' hr.bot_lt -theorem div_lt_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a / r < b ↔ a < b * r := - lt_iff_lt_of_le_iff_le (le_div_iff₀ (pos_iff_ne_zero.2 hr)) +@[deprecated div_lt_iff₀ (since := "2024-10-02")] +theorem div_lt_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a / r < b ↔ a < b * r := div_lt_iff₀ hr.bot_lt -theorem div_lt_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a / r < b ↔ a < r * b := - lt_iff_lt_of_le_iff_le (le_div_iff₀' (pos_iff_ne_zero.2 hr)) +@[deprecated div_lt_iff₀' (since := "2024-10-02")] +theorem div_lt_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a / r < b ↔ a < r * b := div_lt_iff₀' hr.bot_lt -theorem lt_div_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a < b / r ↔ a * r < b := - lt_iff_lt_of_le_iff_le (div_le_iff₀ (pos_iff_ne_zero.2 hr)) +@[deprecated lt_div_iff₀ (since := "2024-10-02")] +theorem lt_div_iff {a b r : ℝ≥0} (hr : r ≠ 0) : a < b / r ↔ a * r < b := lt_div_iff₀ hr.bot_lt -theorem lt_div_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a < b / r ↔ r * a < b := - lt_iff_lt_of_le_iff_le (div_le_iff₀' (pos_iff_ne_zero.2 hr)) +@[deprecated lt_div_iff₀' (since := "2024-10-02")] +theorem lt_div_iff' {a b r : ℝ≥0} (hr : r ≠ 0) : a < b / r ↔ r * a < b := lt_div_iff₀' hr.bot_lt theorem mul_lt_of_lt_div {a b r : ℝ≥0} (h : a < b / r) : a * r < b := - (lt_div_iff fun hr => False.elim <| by simp [hr] at h).1 h + (lt_div_iff₀ <| pos_iff_ne_zero.2 fun hr => False.elim <| by simp [hr] at h).1 h theorem div_le_div_left_of_le {a b c : ℝ≥0} (c0 : c ≠ 0) (cb : c ≤ b) : a / b ≤ a / c := @@ -882,8 +884,7 @@ nonrec theorem half_lt_self {a : ℝ≥0} (h : a ≠ 0) : a / 2 < a := half_lt_self h.bot_lt theorem div_lt_one_of_lt {a b : ℝ≥0} (h : a < b) : a / b < 1 := by - rwa [div_lt_iff, one_mul] - exact ne_of_gt (lt_of_le_of_lt (zero_le _) h) + rwa [div_lt_iff₀ h.bot_lt, one_mul] theorem _root_.Real.toNNReal_inv {x : ℝ} : Real.toNNReal x⁻¹ = (Real.toNNReal x)⁻¹ := by rcases le_total 0 x with hx | hx @@ -900,13 +901,13 @@ theorem _root_.Real.toNNReal_div' {x y : ℝ} (hy : 0 ≤ y) : rw [div_eq_inv_mul, div_eq_inv_mul, Real.toNNReal_mul (inv_nonneg.2 hy), Real.toNNReal_inv] theorem inv_lt_one_iff {x : ℝ≥0} (hx : x ≠ 0) : x⁻¹ < 1 ↔ 1 < x := by - rw [← one_div, div_lt_iff hx, one_mul] + rw [← one_div, div_lt_iff₀ hx.bot_lt, one_mul] -theorem zpow_pos {x : ℝ≥0} (hx : x ≠ 0) (n : ℤ) : 0 < x ^ n := - zpow_pos_of_pos hx.bot_lt _ +@[deprecated zpow_pos (since := "2024-10-08")] +protected theorem zpow_pos {x : ℝ≥0} (hx : x ≠ 0) (n : ℤ) : 0 < x ^ n := zpow_pos hx.bot_lt _ theorem inv_lt_inv {x y : ℝ≥0} (hx : x ≠ 0) (h : x < y) : y⁻¹ < x⁻¹ := - inv_lt_inv_of_lt hx.bot_lt h + inv_strictAnti₀ hx.bot_lt h end Inv @@ -944,7 +945,7 @@ theorem iInf_empty [IsEmpty ι] (f : ι → ℝ≥0) : ⨅ i, f i = 0 := by @[simp] theorem iInf_const_zero {α : Sort*} : ⨅ _ : α, (0 : ℝ≥0) = 0 := by rw [← coe_inj, coe_iInf] - exact Real.ciInf_const_zero + exact Real.iInf_const_zero theorem iInf_mul (f : ι → ℝ≥0) (a : ℝ≥0) : iInf f * a = ⨅ i, f i * a := by rw [← coe_inj, NNReal.coe_mul, coe_iInf, coe_iInf] diff --git a/Mathlib/Data/Nat/BitIndices.lean b/Mathlib/Data/Nat/BitIndices.lean index 8e257d61ead92..79bd2eb583ef4 100644 --- a/Mathlib/Data/Nat/BitIndices.lean +++ b/Mathlib/Data/Nat/BitIndices.lean @@ -35,9 +35,9 @@ elements of `s` in increasing order. -/ def bitIndices (n : ℕ) : List ℕ := @binaryRec (fun _ ↦ List ℕ) [] (fun b _ s ↦ b.casesOn (s.map (· + 1)) (0 :: s.map (· + 1))) n -@[simp] theorem bitIndices_zero : bitIndices 0 = [] := by rfl +@[simp] theorem bitIndices_zero : bitIndices 0 = [] := by simp [bitIndices] -@[simp] theorem bitIndices_one : bitIndices 1 = [0] := by rfl +@[simp] theorem bitIndices_one : bitIndices 1 = [0] := by simp [bitIndices] theorem bitIndices_bit_true (n : ℕ) : bitIndices (bit true n) = 0 :: ((bitIndices n).map (· + 1)) := diff --git a/Mathlib/Data/Nat/Bits.lean b/Mathlib/Data/Nat/Bits.lean index feb4a5b86056f..753381e7318d1 100644 --- a/Mathlib/Data/Nat/Bits.lean +++ b/Mathlib/Data/Nat/Bits.lean @@ -25,7 +25,7 @@ and `Nat.digits`. -- Once we're in the `Nat` namespace, `xor` will inconveniently resolve to `Nat.xor`. /-- `bxor` denotes the `xor` function i.e. the exclusive-or function on type `Bool`. -/ -local notation "bxor" => _root_.xor +local notation "bxor" => xor namespace Nat universe u @@ -48,7 +48,7 @@ def bodd (n : ℕ) : Bool := (boddDiv2 n).1 @[simp] lemma bodd_zero : bodd 0 = false := rfl -lemma bodd_one : bodd 1 = true := rfl +@[simp] lemma bodd_one : bodd 1 = true := rfl lemma bodd_two : bodd 2 = false := rfl @@ -88,12 +88,12 @@ lemma mod_two_of_bodd (n : ℕ) : n % 2 = cond (bodd n) 1 0 := by @[simp] lemma div2_zero : div2 0 = 0 := rfl -lemma div2_one : div2 1 = 0 := rfl +@[simp] lemma div2_one : div2 1 = 0 := rfl lemma div2_two : div2 2 = 1 := rfl @[simp] -lemma div2_succ (n : ℕ) : div2 (succ n) = cond (bodd n) (succ (div2 n)) (div2 n) := by +lemma div2_succ (n : ℕ) : div2 (n + 1) = cond (bodd n) (succ (div2 n)) (div2 n) := by simp only [bodd, boddDiv2, div2] rcases boddDiv2 n with ⟨_|_, _⟩ <;> simp @@ -195,6 +195,12 @@ lemma binaryRec_zero {C : Nat → Sort u} (z : C 0) (f : ∀ b n, C n → C (bit rw [binaryRec] rfl +@[simp] +lemma binaryRec_one {C : Nat → Sort u} (z : C 0) (f : ∀ b n, C n → C (bit b n)) : + binaryRec z f 1 = f true 0 z := by + rw [binaryRec] + simp + /-! bitwise ops -/ lemma bodd_bit (b n) : bodd (bit b n) = b := by @@ -391,6 +397,7 @@ theorem bit1_bits (n : ℕ) : (2 * n + 1).bits = true :: n.bits := @[simp] theorem one_bits : Nat.bits 1 = [true] := by convert bit1_bits 0 + simp -- TODO Find somewhere this can live. -- example : bits 3423 = [true, true, true, true, true, false, true, false, true, false, true, true] diff --git a/Mathlib/Data/Nat/Bitwise.lean b/Mathlib/Data/Nat/Bitwise.lean index ea2eb8e119049..98bc466c54c8d 100644 --- a/Mathlib/Data/Nat/Bitwise.lean +++ b/Mathlib/Data/Nat/Bitwise.lean @@ -9,6 +9,7 @@ import Mathlib.Algebra.Ring.Nat import Mathlib.Order.Basic import Mathlib.Tactic.AdaptationNote import Mathlib.Tactic.Common +import Mathlib.Algebra.NeZero /-! # Bitwise operations on natural numbers @@ -272,9 +273,6 @@ theorem lor_comm (n m : ℕ) : n ||| m = m ||| n := theorem land_comm (n m : ℕ) : n &&& m = m &&& n := bitwise_comm Bool.and_comm n m -protected lemma xor_comm (n m : ℕ) : n ^^^ m = m ^^^ n := - bitwise_comm (Bool.bne_eq_xor ▸ Bool.xor_comm) n m - lemma and_two_pow (n i : ℕ) : n &&& 2 ^ i = (n.testBit i).toNat * 2 ^ i := by refine eq_of_testBit_eq fun j => ?_ obtain rfl | hij := Decidable.eq_or_ne i j <;> cases' h : n.testBit i @@ -286,13 +284,6 @@ lemma and_two_pow (n i : ℕ) : n &&& 2 ^ i = (n.testBit i).toNat * 2 ^ i := by lemma two_pow_and (n i : ℕ) : 2 ^ i &&& n = 2 ^ i * (n.testBit i).toNat := by rw [mul_comm, land_comm, and_two_pow] -@[simp] -theorem zero_xor (n : ℕ) : 0 ^^^ n = n := by simp [HXor.hXor, Xor.xor, xor] - -@[simp] -theorem xor_zero (n : ℕ) : n ^^^ 0 = n := by simp [HXor.hXor, Xor.xor, xor] - - /-- Proving associativity of bitwise operations in general essentially boils down to a huge case distinction, so it is shorter to use this tactic instead of proving it in the general case. -/ macro "bitwise_assoc_tac" : tactic => set_option hygiene false in `(tactic| ( @@ -305,22 +296,16 @@ macro "bitwise_assoc_tac" : tactic => set_option hygiene false in `(tactic| ( -- This is necessary because these are simp lemmas in mathlib <;> simp [hn, Bool.or_assoc, Bool.and_assoc, Bool.bne_eq_xor])) -protected lemma xor_assoc (n m k : ℕ) : (n ^^^ m) ^^^ k = n ^^^ (m ^^^ k) := by bitwise_assoc_tac - theorem land_assoc (n m k : ℕ) : (n &&& m) &&& k = n &&& (m &&& k) := by bitwise_assoc_tac theorem lor_assoc (n m k : ℕ) : (n ||| m) ||| k = n ||| (m ||| k) := by bitwise_assoc_tac -@[simp] -theorem xor_self (n : ℕ) : n ^^^ n = 0 := - zero_of_testBit_eq_false fun i => by simp - -- These lemmas match `mul_inv_cancel_right` and `mul_inv_cancel_left`. theorem xor_cancel_right (n m : ℕ) : (m ^^^ n) ^^^ n = m := by - rw [Nat.xor_assoc, xor_self, xor_zero] + rw [Nat.xor_assoc, Nat.xor_self, xor_zero] theorem xor_cancel_left (n m : ℕ) : n ^^^ (n ^^^ m) = m := by - rw [← Nat.xor_assoc, xor_self, zero_xor] + rw [← Nat.xor_assoc, Nat.xor_self, zero_xor] theorem xor_right_injective {n : ℕ} : Function.Injective (HXor.hXor n : ℕ → ℕ) := fun m m' h => by rw [← xor_cancel_left n m, ← xor_cancel_left n m', h] @@ -339,7 +324,7 @@ theorem xor_left_inj {n m m' : ℕ} : m ^^^ n = m' ^^^ n ↔ m = m' := @[simp] theorem xor_eq_zero {n m : ℕ} : n ^^^ m = 0 ↔ n = m := by - rw [← xor_self n, xor_right_inj, eq_comm] + rw [← Nat.xor_self n, xor_right_inj, eq_comm] theorem xor_ne_zero {n m : ℕ} : n ^^^ m ≠ 0 ↔ n ≠ m := xor_eq_zero.not diff --git a/Mathlib/Data/Nat/Cast/Commute.lean b/Mathlib/Data/Nat/Cast/Commute.lean index 4d8306384d75f..9d1e9bc89094b 100644 --- a/Mathlib/Data/Nat/Cast/Commute.lean +++ b/Mathlib/Data/Nat/Cast/Commute.lean @@ -11,7 +11,7 @@ import Mathlib.Algebra.Ring.Commute -/ -variable {α β : Type*} +variable {α : Type*} namespace Nat diff --git a/Mathlib/Data/Nat/Cast/NeZero.lean b/Mathlib/Data/Nat/Cast/NeZero.lean index d49f78b3b3095..c3f00eb8b8820 100644 --- a/Mathlib/Data/Nat/Cast/NeZero.lean +++ b/Mathlib/Data/Nat/Cast/NeZero.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Gabriel Ebner -/ import Mathlib.Data.Nat.Cast.Defs -import Mathlib.Algebra.NeZero /-! # Lemmas about nonzero elements of an `AddMonoidWithOne` diff --git a/Mathlib/Data/Nat/Cast/Order/Field.lean b/Mathlib/Data/Nat/Cast/Order/Field.lean index 8b16df559d51a..bf5cfd6d2e238 100644 --- a/Mathlib/Data/Nat/Cast/Order/Field.lean +++ b/Mathlib/Data/Nat/Cast/Order/Field.lean @@ -22,7 +22,7 @@ variable {α : Type*} [LinearOrderedSemifield α] lemma cast_inv_le_one : ∀ n : ℕ, (n⁻¹ : α) ≤ 1 | 0 => by simp - | n + 1 => inv_le_one <| by simp [Nat.cast_nonneg] + | n + 1 => inv_le_one_of_one_le₀ <| 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 diff --git a/Mathlib/Data/Nat/Cast/Synonym.lean b/Mathlib/Data/Nat/Cast/Synonym.lean index fad1703cc9e63..075d62d0d87cf 100644 --- a/Mathlib/Data/Nat/Cast/Synonym.lean +++ b/Mathlib/Data/Nat/Cast/Synonym.lean @@ -22,7 +22,7 @@ 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 -variable {α β : Type*} +variable {α : Type*} /-! ### Order dual -/ diff --git a/Mathlib/Data/Nat/Choose/Basic.lean b/Mathlib/Data/Nat/Choose/Basic.lean index e3c7af108183b..08947b2993cb9 100644 --- a/Mathlib/Data/Nat/Choose/Basic.lean +++ b/Mathlib/Data/Nat/Choose/Basic.lean @@ -377,7 +377,7 @@ theorem multichoose_eq : ∀ n k : ℕ, multichoose n k = (n + k - 1).choose k | n + 1, k + 1 => by have : n + (k + 1) < (n + 1) + (k + 1) := Nat.add_lt_add_right (Nat.lt_succ_self _) _ have : (n + 1) + k < (n + 1) + (k + 1) := Nat.add_lt_add_left (Nat.lt_succ_self _) _ - erw [multichoose_succ_succ, Nat.add_comm, Nat.succ_add_sub_one, ← Nat.add_assoc, + rw [multichoose_succ_succ, Nat.add_comm, Nat.succ_add_sub_one, ← Nat.add_assoc, Nat.choose_succ_succ] simp [multichoose_eq n (k+1), multichoose_eq (n+1) k] diff --git a/Mathlib/Data/Nat/Choose/Factorization.lean b/Mathlib/Data/Nat/Choose/Factorization.lean index 71966a049eb3a..258c4eb897817 100644 --- a/Mathlib/Data/Nat/Choose/Factorization.lean +++ b/Mathlib/Data/Nat/Choose/Factorization.lean @@ -78,7 +78,7 @@ theorem factorization_choose_of_lt_three_mul (hp' : p ≠ 2) (hk : p ≤ k) (hk' n < 3 * p := hn _ ≤ p * p := mul_le_mul_right' this p _ = p ^ 2 := (sq p).symm - _ ≤ p ^ i := pow_le_pow_right hp.one_lt.le hi + _ ≤ p ^ i := pow_right_mono₀ hp.one_lt.le hi rwa [mod_eq_of_lt (lt_of_le_of_lt hkn hn), mod_eq_of_lt (lt_of_le_of_lt tsub_le_self hn), add_tsub_cancel_of_le hkn] diff --git a/Mathlib/Data/Nat/Choose/Sum.lean b/Mathlib/Data/Nat/Choose/Sum.lean index d9bafecbbe840..d15893af1129d 100644 --- a/Mathlib/Data/Nat/Choose/Sum.lean +++ b/Mathlib/Data/Nat/Choose/Sum.lean @@ -74,6 +74,17 @@ theorem add_pow [CommSemiring R] (x y : R) (n : ℕ) : (x + y) ^ n = ∑ m ∈ range (n + 1), x ^ m * y ^ (n - m) * n.choose m := (Commute.all x y).add_pow n +/-- A special case of the **binomial theorem** -/ +theorem sub_pow [CommRing R] (x y : R) (n : ℕ) : + (x - y) ^ n = ∑ m ∈ range (n + 1), (-1) ^ (m + n) * x ^ m * y ^ (n - m) * n.choose m := by + rw [sub_eq_add_neg, add_pow] + congr! 1 with m hm + have : (-1 : R) ^ (n - m) = (-1) ^ (n + m) := by + rw [mem_range] at hm + simp [show n + m = n - m + 2 * m by omega, pow_add] + rw [neg_pow, this] + ring + namespace Nat /-- The sum of entries in a row of Pascal's triangle -/ @@ -181,7 +192,7 @@ theorem sum_powerset_neg_one_pow_card_of_nonempty {α : Type*} {x : Finset α} ( rw [sum_powerset_neg_one_pow_card] exact if_neg (nonempty_iff_ne_empty.mp h0) -variable {M R : Type*} [CommMonoid M] [NonAssocSemiring R] +variable [NonAssocSemiring R] @[to_additive sum_choose_succ_nsmul] theorem prod_pow_choose_succ {M : Type*} [CommMonoid M] (f : ℕ → ℕ → M) (n : ℕ) : diff --git a/Mathlib/Data/Nat/Defs.lean b/Mathlib/Data/Nat/Defs.lean index b5e07ed1bde05..3bff75138a170 100644 --- a/Mathlib/Data/Nat/Defs.lean +++ b/Mathlib/Data/Nat/Defs.lean @@ -57,7 +57,7 @@ assert_not_exists Monoid open Function namespace Nat -variable {a b c d m n k : ℕ} {p q : ℕ → Prop} +variable {a b c d m n k : ℕ} {p : ℕ → Prop} -- TODO: Move the `LinearOrder ℕ` instance to `Order.Nat` (#13092). instance instLinearOrder : LinearOrder ℕ where @@ -137,10 +137,20 @@ lemma one_lt_iff_ne_zero_and_ne_one : ∀ {n : ℕ}, 1 < n ↔ n ≠ 0 ∧ n ≠ lemma le_one_iff_eq_zero_or_eq_one : ∀ {n : ℕ}, n ≤ 1 ↔ n = 0 ∨ n = 1 := by simp [le_succ_iff] -@[simp] lemma lt_one_iff : n < 1 ↔ n = 0 := Nat.lt_succ_iff.trans <| by rw [le_zero_eq] - lemma one_le_of_lt (h : a < b) : 1 ≤ b := Nat.lt_of_le_of_lt (Nat.zero_le _) h +protected lemma min_left_comm (a b c : ℕ) : min a (min b c) = min b (min a c) := by + rw [← Nat.min_assoc, ← Nat.min_assoc, b.min_comm] + +protected lemma max_left_comm (a b c : ℕ) : max a (max b c) = max b (max a c) := by + rw [← Nat.max_assoc, ← Nat.max_assoc, b.max_comm] + +protected lemma min_right_comm (a b c : ℕ) : min (min a b) c = min (min a c) b := by + rw [Nat.min_assoc, Nat.min_assoc, b.min_comm] + +protected lemma max_right_comm (a b c : ℕ) : max (max a b) c = max (max a c) b := by + rw [Nat.max_assoc, Nat.max_assoc, b.max_comm] + @[simp] lemma min_eq_zero_iff : min m n = 0 ↔ m = 0 ∨ n = 0 := by omega @[simp] lemma max_eq_zero_iff : max m n = 0 ↔ m = 0 ∧ n = 0 := by omega @@ -155,8 +165,13 @@ lemma pred_eq_of_eq_succ (H : m = n.succ) : m.pred = n := by simp [H] @[simp] lemma pred_eq_succ_iff : n - 1 = m + 1 ↔ n = m + 2 := by cases n <;> constructor <;> rintro ⟨⟩ <;> rfl +#adaptation_note +/-- +After nightly-2024-09-06 we can remove both the `_root_` prefixes below. +-/ lemma forall_lt_succ : (∀ m < n + 1, p m) ↔ (∀ m < n, p m) ∧ p n := by - simp only [Nat.lt_succ_iff, Nat.le_iff_lt_or_eq, or_comm, forall_eq_or_imp, and_comm] + simp only [Nat.lt_succ_iff, Nat.le_iff_lt_or_eq, _root_.or_comm, forall_eq_or_imp, + _root_.and_comm] lemma exists_lt_succ : (∃ m < n + 1, p m) ↔ (∃ m < n, p m) ∨ p n := by rw [← not_iff_not] @@ -208,8 +223,7 @@ attribute [simp] le_add_left le_add_right Nat.lt_add_left_iff_pos Nat.lt_add_rig -- 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. --- TODO: This is a duplicate of `Nat.add_eq` -@[simp] lemma add_def : Nat.add m n = m + n := rfl +@[deprecated (since := "2024-04-05")] alias add_def := add_eq -- We want to use these two lemmas earlier than the lemmas simp can prove them with @[simp, nolint simpNF] protected lemma add_eq_left : a + b = a ↔ b = 0 := by omega @@ -298,11 +312,11 @@ lemma two_mul_ne_two_mul_add_one : 2 * n ≠ 2 * m + 1 := -- 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) _ _ + 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) _ _ + 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 := not_congr (Nat.mul_left_inj ha) @@ -586,9 +600,6 @@ protected lemma pow_le_pow_iff_left {n : ℕ} (hn : n ≠ 0) : a ^ n ≤ b ^ n protected lemma pow_lt_pow_iff_left (hn : n ≠ 0) : a ^ n < b ^ n ↔ a < b := by simp only [← Nat.not_le, Nat.pow_le_pow_iff_left hn] -@[deprecated (since := "2023-12-23")] alias pow_lt_pow_of_lt_left := Nat.pow_lt_pow_left -@[deprecated (since := "2023-12-23")] alias pow_le_iff_le_left := Nat.pow_le_pow_iff_left - lemma pow_left_injective (hn : n ≠ 0) : Injective (fun a : ℕ ↦ a ^ n) := by simp [Injective, le_antisymm_iff, Nat.pow_le_pow_iff_left hn] @@ -822,7 +833,7 @@ This is an alias of `Nat.leRec`, specialized to `Prop`. -/ @[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 := - @Nat.leRec (motive := P) base succ + @Nat.leRec (motive := P) _ base succ /-- Induction principle deriving the next case from the two previous ones. -/ def twoStepInduction {P : ℕ → Sort*} (zero : P 0) (one : P 1) @@ -1006,9 +1017,6 @@ lemma div_ne_zero_iff_of_dvd (hba : b ∣ a) : a / b ≠ 0 ↔ a ≠ 0 ∧ b ≠ @[simp] lemma mul_mod_mod (a b c : ℕ) : (a * (b % c)) % c = a * b % c := by rw [mul_mod, mod_mod, ← mul_mod] -@[simp] lemma mod_mul_mod (a b c : ℕ) : (a % c * b) % c = a * b % c := by - rw [mul_mod, mod_mod, ← mul_mod] - lemma pow_mod (a b n : ℕ) : a ^ b % n = (a % n) ^ b % n := by induction b with | zero => rfl diff --git a/Mathlib/Data/Nat/Digits.lean b/Mathlib/Data/Nat/Digits.lean index f7955d0768276..23cd40d657cba 100644 --- a/Mathlib/Data/Nat/Digits.lean +++ b/Mathlib/Data/Nat/Digits.lean @@ -570,7 +570,7 @@ theorem sub_one_mul_sum_log_div_pow_eq_sub_sum_digits {p : ℕ} (n : ℕ) : theorem digits_two_eq_bits (n : ℕ) : digits 2 n = n.bits.map fun b => cond b 1 0 := by induction' n using Nat.binaryRecFromOne with b n h ih · simp - · rfl + · simp rw [bits_append_bit _ _ fun hn => absurd hn h] cases b · rw [digits_def' one_lt_two] diff --git a/Mathlib/Data/Nat/Factorization/Basic.lean b/Mathlib/Data/Nat/Factorization/Basic.lean index a00644b704354..27ddcf0d3a424 100644 --- a/Mathlib/Data/Nat/Factorization/Basic.lean +++ b/Mathlib/Data/Nat/Factorization/Basic.lean @@ -13,7 +13,7 @@ import Mathlib.Tactic.IntervalCases # Basic lemmas on prime factorizations -/ -open Nat Finset List Finsupp +open Finset List Finsupp namespace Nat variable {a b m n p : ℕ} diff --git a/Mathlib/Data/Nat/Factorization/Defs.lean b/Mathlib/Data/Nat/Factorization/Defs.lean index fbabc1edc00fd..fb64f3dd9d2d6 100644 --- a/Mathlib/Data/Nat/Factorization/Defs.lean +++ b/Mathlib/Data/Nat/Factorization/Defs.lean @@ -86,7 +86,7 @@ alias factorization_eq_factors_multiset := factorization_eq_primeFactorsList_mul theorem Prime.factorization_pos_of_dvd {n p : ℕ} (hp : p.Prime) (hn : n ≠ 0) (h : p ∣ n) : 0 < n.factorization p := by - rwa [← primeFactorsList_count_eq, count_pos_iff_mem, mem_primeFactorsList_iff_dvd hn hp] + rwa [← primeFactorsList_count_eq, count_pos_iff, mem_primeFactorsList_iff_dvd hn hp] theorem multiplicity_eq_factorization {n p : ℕ} (pp : p.Prime) (hn : n ≠ 0) : multiplicity p n = n.factorization p := by @@ -172,7 +172,7 @@ theorem factorization_prod {α : Type*} {S : Finset α} {g : α → ℕ} (hS : · simp · intro x T hxS hTS hxT IH have hT : T.prod g ≠ 0 := prod_ne_zero_iff.mpr fun x hx => hS x (hTS hx) - simp [prod_insert hxT, sum_insert hxT, ← IH, factorization_mul (hS x hxS) hT] + simp [prod_insert hxT, sum_insert hxT, IH, factorization_mul (hS x hxS) hT] /-- For any `p`, the power of `p` in `n^k` is `k` times the power in `n` -/ @[simp] diff --git a/Mathlib/Data/Nat/Find.lean b/Mathlib/Data/Nat/Find.lean index e37f555306458..84ee3406a3e5a 100644 --- a/Mathlib/Data/Nat/Find.lean +++ b/Mathlib/Data/Nat/Find.lean @@ -11,7 +11,7 @@ import Batteries.WF # `Nat.find` and `Nat.findGreatest` -/ -variable {a b c d m n k : ℕ} {p q : ℕ → Prop} +variable {m n k : ℕ} {p q : ℕ → Prop} namespace Nat diff --git a/Mathlib/Data/Nat/Log.lean b/Mathlib/Data/Nat/Log.lean index eb2ae3bc58f52..f2cf3df6eca07 100644 --- a/Mathlib/Data/Nat/Log.lean +++ b/Mathlib/Data/Nat/Log.lean @@ -124,8 +124,8 @@ theorem lt_pow_succ_log_self {b : ℕ} (hb : 1 < b) (x : ℕ) : x < b ^ (log b x theorem log_eq_iff {b m n : ℕ} (h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0) : log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1) := by rcases em (1 < b ∧ n ≠ 0) with (⟨hb, hn⟩ | hbn) - · rw [le_antisymm_iff, ← Nat.lt_succ_iff, ← pow_le_iff_le_log, ← lt_pow_iff_log_lt, and_comm] <;> - assumption + · rw [le_antisymm_iff, ← Nat.lt_succ_iff, ← pow_le_iff_le_log, ← lt_pow_iff_log_lt, + and_comm] <;> assumption have hm : m ≠ 0 := h.resolve_right hbn rw [not_and_or, not_lt, Ne, not_not] at hbn rcases hbn with (hb | rfl) diff --git a/Mathlib/Data/Nat/ModEq.lean b/Mathlib/Data/Nat/ModEq.lean index 5877782fc1102..29ff2fed4da9d 100644 --- a/Mathlib/Data/Nat/ModEq.lean +++ b/Mathlib/Data/Nat/ModEq.lean @@ -3,10 +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.Algebra.Ring.Regular +import Mathlib.Algebra.Order.Group.Unbundled.Int import Mathlib.Data.Int.GCD -import Mathlib.Data.Int.Order.Lemmas -import Mathlib.Tactic.NormNum.Basic /-! # Congruences modulo a natural number @@ -24,6 +22,7 @@ and proves basic properties about it such as the Chinese Remainder Theorem ModEq, congruence, mod, MOD, modulo -/ +assert_not_exists OrderedAddCommMonoid assert_not_exists Function.support namespace Nat @@ -37,8 +36,8 @@ notation:50 a " ≡ " b " [MOD " n "]" => ModEq n a b variable {m n a b c d : ℕ} --- Porting note: This instance should be derivable automatically -instance : Decidable (ModEq n a b) := decEq (a % n) (b % n) +-- Since `ModEq` is semi-reducible, we need to provide the decidable instance manually +instance : Decidable (ModEq n a b) := inferInstanceAs <| Decidable (a % n = b % n) namespace ModEq @@ -91,7 +90,7 @@ 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 + modEq_of_dvd <| Int.ofNat_dvd.mpr d |>.trans h.dvd protected theorem mul_left' (c : ℕ) (h : a ≡ b [MOD n]) : c * a ≡ c * b [MOD c * n] := by unfold ModEq at *; rw [mul_mod_mul_left, mul_mod_mul_left, h] @@ -122,7 +121,7 @@ protected theorem pow (m : ℕ) (h : a ≡ b [MOD n]) : a ^ m ≡ b ^ m [MOD n] @[gcongr] protected theorem add (h₁ : a ≡ b [MOD n]) (h₂ : c ≡ d [MOD n]) : a + c ≡ b + d [MOD n] := by rw [modEq_iff_dvd, Int.ofNat_add, Int.ofNat_add, add_sub_add_comm] - exact dvd_add h₁.dvd h₂.dvd + exact Int.dvd_add h₁.dvd h₂.dvd @[gcongr] protected theorem add_left (c : ℕ) (h : a ≡ b [MOD n]) : c + a ≡ c + b [MOD n] := @@ -136,7 +135,7 @@ protected theorem add_left_cancel (h₁ : a ≡ b [MOD n]) (h₂ : a + c ≡ b + c ≡ d [MOD n] := by simp only [modEq_iff_dvd, Int.ofNat_add] at * rw [add_sub_add_comm] at h₂ - convert _root_.dvd_sub h₂ h₁ using 1 + convert Int.dvd_sub h₂ h₁ using 1 rw [add_sub_cancel_left] protected theorem add_left_cancel' (c : ℕ) (h : c + a ≡ c + b [MOD n]) : a ≡ b [MOD n] := @@ -155,7 +154,8 @@ protected theorem add_right_cancel' (c : ℕ) (h : a + c ≡ b + c [MOD n]) : a For cancelling left multiplication in the modulus, see `Nat.ModEq.of_mul_left`. -/ protected theorem mul_left_cancel' {a b c m : ℕ} (hc : c ≠ 0) : c * a ≡ c * b [MOD c * m] → a ≡ b [MOD m] := by - simp [modEq_iff_dvd, ← mul_sub, mul_dvd_mul_iff_left (by simp [hc] : (c : ℤ) ≠ 0)] + simp only [modEq_iff_dvd, Int.natCast_mul, ← Int.mul_sub] + exact fun h => (Int.dvd_of_mul_dvd_mul_left (Int.ofNat_ne_zero.mpr hc) h) protected theorem mul_left_cancel_iff' {a b c m : ℕ} (hc : c ≠ 0) : c * a ≡ c * b [MOD c * m] ↔ a ≡ b [MOD m] := @@ -166,7 +166,8 @@ protected theorem mul_left_cancel_iff' {a b c m : ℕ} (hc : c ≠ 0) : For cancelling right multiplication in the modulus, see `Nat.ModEq.of_mul_right`. -/ protected theorem mul_right_cancel' {a b c m : ℕ} (hc : c ≠ 0) : a * c ≡ b * c [MOD m * c] → a ≡ b [MOD m] := by - simp [modEq_iff_dvd, ← sub_mul, mul_dvd_mul_iff_right (by simp [hc] : (c : ℤ) ≠ 0)] + simp only [modEq_iff_dvd, Int.natCast_mul, ← Int.sub_mul] + exact fun h => (Int.dvd_of_mul_dvd_mul_right (Int.ofNat_ne_zero.mpr hc) h) protected theorem mul_right_cancel_iff' {a b c m : ℕ} (hc : c ≠ 0) : a * c ≡ b * c [MOD m * c] ↔ a ≡ b [MOD m] := @@ -204,10 +205,10 @@ namespace ModEq theorem le_of_lt_add (h1 : a ≡ b [MOD m]) (h2 : a < b + m) : a ≤ b := (le_total a b).elim id fun h3 => Nat.le_of_sub_eq_zero - (eq_zero_of_dvd_of_lt ((modEq_iff_dvd' h3).mp h1.symm) ((tsub_lt_iff_left h3).mpr h2)) + (eq_zero_of_dvd_of_lt ((modEq_iff_dvd' h3).mp h1.symm) (by omega)) theorem add_le_of_lt (h1 : a ≡ b [MOD m]) (h2 : a < b) : a + m ≤ b := - le_of_lt_add (add_modEq_right.trans h1) (add_lt_add_right h2 m) + le_of_lt_add (add_modEq_right.trans h1) (by omega) theorem dvd_iff (h : a ≡ b [MOD m]) (hdm : d ∣ m) : d ∣ a ↔ d ∣ b := by simp only [← modEq_zero_iff_dvd] @@ -227,9 +228,7 @@ lemma eq_of_abs_lt (h : a ≡ b [MOD m]) (h2 : |(b : ℤ) - a| < m) : a = b := b exact Int.eq_zero_of_abs_lt_dvd h.dvd h2 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.natCast_nonneg _).trans_lt <| Int.ofNat_lt.2 hb, - (sub_le_self _ <| Int.natCast_nonneg _).trans_lt <| Int.ofNat_lt.2 ha⟩ + h.eq_of_abs_lt <| Int.abs_sub_lt_of_lt_lt ha hb /-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c` -/ lemma cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m / gcd m c] := by @@ -241,7 +240,7 @@ lemma cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [MOD m]) : a ≡ b · show (m / d : ℤ) ∣ c / d * (b - a) rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.natCast_dvd_natCast.mpr hcd), mul_comm] apply Int.ediv_dvd_ediv (Int.natCast_dvd_natCast.mpr hmd) - rw [mul_sub] + rw [Int.mul_sub] exact modEq_iff_dvd.mp h · show Int.gcd (m / d) (c / d) = 1 simp only [← Int.natCast_div, Int.gcd_natCast_natCast (m / d) (c / d), gcd_div hmd hcd, @@ -299,18 +298,18 @@ def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k have hcoedvd : ∀ t, (gcd n m : ℤ) ∣ t * (b - a) := fun t => h.dvd.mul_left _ have := gcd_eq_gcd_ab n m constructor <;> rw [Int.emod_def, ← sub_add] <;> - refine dvd_add ?_ (dvd_mul_of_dvd_left ?_ _) <;> + refine Int.dvd_add ?_ (dvd_mul_of_dvd_left ?_ _) <;> try norm_cast · rw [← sub_eq_iff_eq_add'] at this - rw [← this, sub_mul, ← add_sub_assoc, add_comm, add_sub_assoc, ← mul_sub, + rw [← this, Int.sub_mul, ← add_sub_assoc, add_comm, add_sub_assoc, ← Int.mul_sub, Int.add_ediv_of_dvd_left, Int.mul_ediv_cancel_left _ hnonzero, - Int.mul_ediv_assoc _ h.dvd, ← sub_sub, sub_self, zero_sub, dvd_neg, mul_assoc] + Int.mul_ediv_assoc _ h.dvd, ← sub_sub, sub_self, zero_sub, Int.dvd_neg, mul_assoc] · exact dvd_mul_right _ _ norm_cast exact dvd_mul_right _ _ · exact dvd_lcm_left n m · rw [← sub_eq_iff_eq_add] at this - rw [← this, sub_mul, sub_add, ← mul_sub, Int.sub_ediv_of_dvd, + rw [← this, Int.sub_mul, sub_add, ← Int.mul_sub, Int.sub_ediv_of_dvd, Int.mul_ediv_cancel_left _ hnonzero, Int.mul_ediv_assoc _ h.dvd, ← sub_add, sub_self, zero_add, mul_assoc] · exact dvd_mul_right _ _ @@ -407,7 +406,7 @@ protected theorem add_div_of_dvd_right {a b c : ℕ} (hca : c ∣ a) : (a + b) / add_div_eq_of_add_mod_lt (by rw [Nat.mod_eq_zero_of_dvd hca, zero_add] - exact Nat.mod_lt _ (pos_iff_ne_zero.mpr h)) + exact Nat.mod_lt _ (zero_lt_of_ne_zero h)) protected theorem add_div_of_dvd_left {a b c : ℕ} (hca : c ∣ b) : (a + b) / c = a / c + b / c := by rwa [add_comm, Nat.add_div_of_dvd_right, add_comm] @@ -430,27 +429,24 @@ theorem odd_mul_odd {n m : ℕ} : n % 2 = 1 → m % 2 = 1 → n * m % 2 = 1 := b theorem odd_mul_odd_div_two {m n : ℕ} (hm1 : m % 2 = 1) (hn1 : n % 2 = 1) : m * n / 2 = m * (n / 2) + m / 2 := - have hm0 : 0 < m := Nat.pos_of_ne_zero fun h => by simp_all have hn0 : 0 < n := Nat.pos_of_ne_zero fun h => by simp_all mul_right_injective₀ two_ne_zero <| by dsimp rw [mul_add, two_mul_odd_div_two hm1, mul_left_comm, two_mul_odd_div_two hn1, - two_mul_odd_div_two (Nat.odd_mul_odd hm1 hn1), mul_tsub, mul_one, ← - add_tsub_assoc_of_le (succ_le_of_lt hm0), - tsub_add_cancel_of_le (le_mul_of_one_le_right (Nat.zero_le _) hn0)] + two_mul_odd_div_two (Nat.odd_mul_odd hm1 hn1), Nat.mul_sub, mul_one, ← + Nat.add_sub_assoc (by omega), Nat.sub_add_cancel (Nat.le_mul_of_pos_right m hn0)] theorem odd_of_mod_four_eq_one {n : ℕ} : n % 4 = 1 → n % 2 = 1 := by - simpa [ModEq, show 2 * 2 = 4 by norm_num] using @ModEq.of_mul_left 2 n 1 2 + simpa [ModEq] using @ModEq.of_mul_left 2 n 1 2 theorem odd_of_mod_four_eq_three {n : ℕ} : n % 4 = 3 → n % 2 = 1 := by - simpa [ModEq, show 2 * 2 = 4 by norm_num, show 3 % 4 = 3 by norm_num] using - @ModEq.of_mul_left 2 n 3 2 + simpa [ModEq] using @ModEq.of_mul_left 2 n 3 2 /-- A natural number is odd iff it has residue `1` or `3` mod `4`-/ theorem odd_mod_four_iff {n : ℕ} : n % 2 = 1 ↔ n % 4 = 1 ∨ n % 4 = 3 := have help : ∀ m : ℕ, m < 4 → m % 2 = 1 → m = 1 ∨ m = 3 := by decide ⟨fun hn => - help (n % 4) (mod_lt n (by norm_num)) <| (mod_mod_of_dvd n (by decide : 2 ∣ 4)).trans hn, + help (n % 4) (mod_lt n (by omega)) <| (mod_mod_of_dvd n (by decide : 2 ∣ 4)).trans hn, fun h => Or.elim h odd_of_mod_four_eq_one odd_of_mod_four_eq_three⟩ lemma mod_eq_of_modEq {a b n} (h : a ≡ b [MOD n]) (hb : b < n) : a % n = b := diff --git a/Mathlib/Data/Nat/Prime/Basic.lean b/Mathlib/Data/Nat/Prime/Basic.lean index d0fe2d6bad6ba..06a9ca4221721 100644 --- a/Mathlib/Data/Nat/Prime/Basic.lean +++ b/Mathlib/Data/Nat/Prime/Basic.lean @@ -287,37 +287,6 @@ lemma Prime.pow_inj {p q m n : ℕ} (hp : p.Prime) (hq : q.Prime) (Prime.dvd_of_dvd_pow hq <| h.symm ▸ dvd_pow_self q (succ_ne_zero n)) exact ⟨H, succ_inj'.mp <| Nat.pow_right_injective hq.two_le (H ▸ h)⟩ -theorem exists_pow_lt_factorial (c : ℕ) : ∃ n0 > 1, ∀ n ≥ n0, c ^ n < (n - 1)! := by - refine ⟨2 * (c ^ 2 + 1), ?_, ?_⟩ - · omega - intro n hn - obtain ⟨d, rfl⟩ := Nat.exists_eq_add_of_le hn - obtain (rfl | c0) := c.eq_zero_or_pos - · simp [Nat.factorial_pos] - refine (Nat.le_mul_of_pos_right _ (Nat.pow_pos (n := d) c0)).trans_lt ?_ - convert_to (c ^ 2) ^ (c ^ 2 + d + 1) < (c ^ 2 + (c ^ 2 + d + 1))! - · rw [← pow_mul, ← pow_add] - congr 1 - omega - · congr - omega - refine lt_of_lt_of_le ?_ Nat.factorial_mul_pow_le_factorial - rw [← one_mul (_ ^ _ : ℕ)] - exact Nat.mul_lt_mul_of_le_of_lt (Nat.one_le_of_lt (Nat.factorial_pos _)) - (Nat.pow_lt_pow_left (Nat.lt_succ_self _) (Nat.succ_ne_zero _)) (Nat.factorial_pos _) - -theorem exists_mul_pow_lt_factorial (a : ℕ) (c : ℕ) : ∃ n0, ∀ n ≥ n0, a * c ^ n < (n - 1)! := by - obtain ⟨n0, hn, h⟩ := Nat.exists_pow_lt_factorial (a * c) - refine ⟨n0, fun n hn => lt_of_le_of_lt ?_ (h n hn)⟩ - rw [mul_pow] - refine Nat.mul_le_mul_right _ (Nat.le_self_pow ?_ _) - omega - -theorem exists_prime_mul_pow_lt_factorial (n a c : ℕ) : ∃ p > n, p.Prime ∧ a * c ^ p < (p - 1)! := - have ⟨n0, h⟩ := Nat.exists_mul_pow_lt_factorial a c - have ⟨p, hp, prime_p⟩ := (max (n + 1) n0).exists_infinite_primes - ⟨p, (le_max_left _ _).trans hp, prime_p, h _ <| le_of_max_le_right hp⟩ - end Nat namespace Int diff --git a/Mathlib/Data/Num/Basic.lean b/Mathlib/Data/Num/Basic.lean index 1353fdd100589..5e35ca5550ad8 100644 --- a/Mathlib/Data/Num/Basic.lean +++ b/Mathlib/Data/Num/Basic.lean @@ -169,33 +169,27 @@ section variable {α : Type*} [One α] [Add α] -section deprecated -set_option linter.deprecated false - /-- `castPosNum` casts a `PosNum` into any type which has `1` and `+`. -/ -@[deprecated (since := "2022-11-18"), coe] +@[coe] def castPosNum : PosNum → α | 1 => 1 | PosNum.bit0 a => castPosNum a + castPosNum a | PosNum.bit1 a => castPosNum a + castPosNum a + 1 /-- `castNum` casts a `Num` into any type which has `0`, `1` and `+`. -/ -@[deprecated (since := "2022-11-18"), coe] +@[coe] def castNum [Zero α] : Num → α | 0 => 0 | Num.pos p => castPosNum p -- see Note [coercion into rings] -@[deprecated (since := "2023-03-31")] instance (priority := 900) posNumCoe : CoeHTCT PosNum α := +instance (priority := 900) posNumCoe : CoeHTCT PosNum α := ⟨castPosNum⟩ -- see Note [coercion into rings] -@[deprecated (since := "2023-03-31")] instance (priority := 900) numNatCoe [Zero α] : CoeHTCT Num α := ⟨castNum⟩ -end deprecated - instance : Repr PosNum := ⟨fun n _ => repr (n : ℕ)⟩ @@ -593,19 +587,17 @@ def gcd (a b : ZNum) : Num := end ZNum section - -set_option linter.deprecated false variable {α : Type*} [Zero α] [One α] [Add α] [Neg α] /-- `castZNum` casts a `ZNum` into any type which has `0`, `1`, `+` and `neg` -/ -@[deprecated (since := "2022-11-18"), coe] +@[coe] def castZNum : ZNum → α | 0 => 0 | ZNum.pos p => p | ZNum.neg p => -p -- see Note [coercion into rings] -@[deprecated (since := "2023-03-31")] instance (priority := 900) znumCoe : CoeHTCT ZNum α := +instance (priority := 900) znumCoe : CoeHTCT ZNum α := ⟨castZNum⟩ instance : Repr ZNum := diff --git a/Mathlib/Data/Num/Lemmas.lean b/Mathlib/Data/Num/Lemmas.lean index ac946c8f455bc..c95ab439e4cf4 100644 --- a/Mathlib/Data/Num/Lemmas.lean +++ b/Mathlib/Data/Num/Lemmas.lean @@ -215,7 +215,7 @@ theorem ofNat'_succ : ∀ {n}, ofNat' (n + 1) = ofNat' n + 1 := cases b · erw [ofNat'_bit true n, ofNat'_bit] simp only [← bit1_of_bit1, ← bit0_of_bit0, cond] - · erw [show n.bit true + 1 = (n + 1).bit false by simp [Nat.bit, mul_add], + · rw [show n.bit true + 1 = (n + 1).bit false by simp [Nat.bit, mul_add], ofNat'_bit, ofNat'_bit, ih] simp only [cond, add_one, bit1_succ]) @@ -867,7 +867,7 @@ theorem castNum_testBit (m n) : testBit m n = Nat.testBit m n := by · rfl · rw [PosNum.cast_bit1, ← two_mul, ← congr_fun Nat.bit_true, Nat.testBit_bit_zero] · rw [PosNum.cast_bit0, ← two_mul, ← congr_fun Nat.bit_false, Nat.testBit_bit_zero] - · simp + · simp [Nat.testBit_add_one] · rw [PosNum.cast_bit1, ← two_mul, ← congr_fun Nat.bit_true, Nat.testBit_bit_succ, IH] · rw [PosNum.cast_bit0, ← two_mul, ← congr_fun Nat.bit_false, Nat.testBit_bit_succ, IH] diff --git a/Mathlib/Data/Opposite.lean b/Mathlib/Data/Opposite.lean index 2482808fe2c64..c9f9e120603ca 100644 --- a/Mathlib/Data/Opposite.lean +++ b/Mathlib/Data/Opposite.lean @@ -30,7 +30,7 @@ variable (α : Sort u) both `unop (op X) = X` and `op (unop X) = X` are definitional equalities. -/ -structure Opposite := +structure Opposite where /-- The canonical map `α → αᵒᵖ`. -/ op :: /-- The canonical map `αᵒᵖ → α`. -/ diff --git a/Mathlib/Data/Option/Basic.lean b/Mathlib/Data/Option/Basic.lean index 138ba4471da95..b0bab527487d9 100644 --- a/Mathlib/Data/Option/Basic.lean +++ b/Mathlib/Data/Option/Basic.lean @@ -137,29 +137,12 @@ variable {p : α → Prop} (f : ∀ a : α, p a → β) (x : Option α) theorem pbind_eq_bind (f : α → Option β) (x : Option α) : (x.pbind fun a _ ↦ f a) = x.bind f := by cases x <;> simp only [pbind, none_bind', some_bind'] -theorem map_bind {α β γ} (f : β → γ) (x : Option α) (g : α → Option β) : - Option.map f (x >>= g) = x >>= fun a ↦ Option.map f (g a) := by - simp only [← map_eq_map, ← bind_pure_comp, LawfulMonad.bind_assoc] - theorem map_bind' (f : β → γ) (x : Option α) (g : α → Option β) : Option.map f (x.bind g) = x.bind fun a ↦ Option.map f (g a) := by cases x <;> simp -theorem map_pbind (f : β → γ) (x : Option α) (g : ∀ a, a ∈ x → Option β) : - Option.map f (x.pbind g) = x.pbind fun a H ↦ Option.map f (g a H) := by - cases x <;> simp only [pbind, map_none'] - theorem pbind_map (f : α → β) (x : Option α) (g : ∀ b : β, b ∈ x.map f → Option γ) : pbind (Option.map f x) g = x.pbind fun a h ↦ g (f a) (mem_map_of_mem _ h) := by cases x <;> rfl -@[simp] -theorem pmap_none (f : ∀ a : α, p a → β) {H} : pmap f (@none α) H = none := - rfl - -@[simp] -theorem pmap_some (f : ∀ a : α, p a → β) {x : α} (h : p x) : - pmap f (some x) = fun _ ↦ some (f x h) := - rfl - theorem mem_pmem {a : α} (h : ∀ a ∈ x, p a) (ha : a ∈ x) : f a (h a ha) ∈ pmap f x h := by rw [mem_def] at ha ⊢ subst ha @@ -208,24 +191,6 @@ theorem pbind_eq_some {f : ∀ a : α, a ∈ x → Option β} {y : β} : simp only [mem_def, Option.some_inj] at H simpa [H] using hz --- Porting note: Can't simp tag this anymore because `pmap` simplifies --- @[simp] -theorem pmap_eq_none_iff {h} : pmap f x h = none ↔ x = none := by cases x <;> simp - --- Porting note: Can't simp tag this anymore because `pmap` simplifies --- @[simp] -theorem pmap_eq_some_iff {hf} {y : β} : - pmap f x hf = some y ↔ ∃ (a : α) (H : x = some a), f a (hf a H) = y := by - rcases x with (_|x) - · simp only [not_mem_none, exists_false, pmap, not_false_iff, exists_prop_of_false, reduceCtorEq] - · constructor - · intro h - simp only [pmap, Option.some_inj] at h - exact ⟨x, rfl, h⟩ - · rintro ⟨a, H, rfl⟩ - simp only [mem_def, Option.some_inj] at H - simp only [H, pmap] - -- Porting note: Can't simp tag this anymore because `join` and `pmap` simplify -- @[simp] theorem join_pmap_eq_pmap_join {f : ∀ a, p a → β} {x : Option (Option α)} (H) : diff --git a/Mathlib/Data/Option/Defs.lean b/Mathlib/Data/Option/Defs.lean index e140c43e996c9..c15bedf853135 100644 --- a/Mathlib/Data/Option/Defs.lean +++ b/Mathlib/Data/Option/Defs.lean @@ -75,10 +75,6 @@ abbrev iget [Inhabited α] : Option α → α theorem iget_some [Inhabited α] {a : α} : (some a).iget = a := rfl -@[simp] -theorem mem_toList {a : α} {o : Option α} : a ∈ toList o ↔ a ∈ o := by - cases o <;> simp [toList, eq_comm] - instance liftOrGet_isCommutative (f : α → α → α) [Std.Commutative f] : Std.Commutative (liftOrGet f) := ⟨fun a b ↦ by cases a <;> cases b <;> simp [liftOrGet, Std.Commutative.comm]⟩ diff --git a/Mathlib/Data/Ordmap/Ordset.lean b/Mathlib/Data/Ordmap/Ordset.lean index 48a139e2ee364..ca4d7b8c2efab 100644 --- a/Mathlib/Data/Ordmap/Ordset.lean +++ b/Mathlib/Data/Ordmap/Ordset.lean @@ -378,7 +378,7 @@ theorem Sized.rotateR_size {l x r} (hl : Sized l) : rw [← size_dual, dual_rotateR, hl.dual.rotateL_size, size_dual, size_dual, add_comm (size l)] theorem Sized.balance' {l x r} (hl : @Sized α l) (hr : Sized r) : Sized (balance' l x r) := by - unfold balance'; split_ifs + unfold Ordnode.balance'; split_ifs · exact hl.node' hr · exact hl.rotateL hr · exact hl.rotateR hr @@ -530,12 +530,12 @@ theorem splitMax_eq : | _, l, x, nil => rfl | _, l, x, node ls ll lx lr => by rw [splitMax', splitMax_eq ls ll lx lr, findMax', eraseMax] --- @[elab_as_elim] -- Porting note: unexpected eliminator resulting type +@[elab_as_elim] theorem findMin'_all {P : α → Prop} : ∀ (t) (x : α), All P t → P x → P (findMin' t x) | nil, _x, _, hx => hx | node _ ll lx _, _, ⟨h₁, h₂, _⟩, _ => findMin'_all ll lx h₁ h₂ --- @[elab_as_elim] -- Porting note: unexpected eliminator resulting type +@[elab_as_elim] theorem findMax'_all {P : α → Prop} : ∀ (x : α) (t), P x → All P t → P (findMax' x t) | _x, nil, hx, _ => hx | _, node _ _ lx lr, _, ⟨_, h₂, h₃⟩ => findMax'_all lx lr h₂ h₃ @@ -1111,7 +1111,7 @@ theorem Valid'.rotateL {l} {x : α} {r o₁ o₂} (hl : Valid' o₁ l x) (hr : V · rcases Nat.eq_zero_or_pos (size rl) with rl0 | rl0 · rw [rl0, not_lt, Nat.le_zero, Nat.mul_eq_zero] at h replace h := h.resolve_left (by decide) - erw [rl0, h, Nat.le_zero, Nat.mul_eq_zero] at H2 + rw [rl0, h, Nat.le_zero, Nat.mul_eq_zero] at H2 rw [hr.2.size_eq, rl0, h, H2.resolve_left (by decide)] at H1 cases H1 (by decide) refine hl.node4L hr.left hr.right rl0 ?_ @@ -1258,7 +1258,7 @@ theorem Valid'.glue_aux {l r o₁ o₂} (hl : Valid' o₁ l o₂) (hr : Valid' o suffices H : _ by refine ⟨Valid'.balanceL (hl.of_lt ?_ ?_) v H, ?_⟩ · refine @findMin'_all (P := fun a : α => Bounded nil o₁ (a : WithBot α)) - rl rx (sep.2.1.1.imp ?_) hr.1.1.to_nil + _ rl rx (sep.2.1.1.imp ?_) hr.1.1.to_nil exact fun y h => hl.1.1.to_nil.mono_right (le_of_lt h) · exact @findMin'_all _ (fun a => All (· < a) (.node ls ll lx lr)) rl rx diff --git a/Mathlib/Data/PNat/Defs.lean b/Mathlib/Data/PNat/Defs.lean index 3004d33fc9df7..6eb644184ac56 100644 --- a/Mathlib/Data/PNat/Defs.lean +++ b/Mathlib/Data/PNat/Defs.lean @@ -3,7 +3,6 @@ Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Neil Strickland -/ -import Mathlib.Algebra.NeZero import Mathlib.Data.Nat.Defs import Mathlib.Order.Basic import Mathlib.Order.TypeTags diff --git a/Mathlib/Data/PNat/Interval.lean b/Mathlib/Data/PNat/Interval.lean index 4a310ffe979ce..f10b5ea85500c 100644 --- a/Mathlib/Data/PNat/Interval.lean +++ b/Mathlib/Data/PNat/Interval.lean @@ -53,35 +53,19 @@ theorem map_subtype_embedding_uIcc : (uIcc a b).map (Embedding.subtype _) = uIcc @[simp] theorem card_Icc : (Icc a b).card = b + 1 - a := by - rw [← Nat.card_Icc] - -- Porting note: I had to change this to `erw` *and* provide the proof, yuck. - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [← Finset.map_subtype_embedding_Icc _ a b (fun c x _ hx _ hc _ => hc.trans_le hx)] - rw [card_map] + rw [← Nat.card_Icc, ← map_subtype_embedding_Icc, card_map] @[simp] theorem card_Ico : (Ico a b).card = b - a := by - rw [← Nat.card_Ico] - -- Porting note: I had to change this to `erw` *and* provide the proof, yuck. - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [← Finset.map_subtype_embedding_Ico _ a b (fun c x _ hx _ hc _ => hc.trans_le hx)] - rw [card_map] + rw [← Nat.card_Ico, ← map_subtype_embedding_Ico, card_map] @[simp] theorem card_Ioc : (Ioc a b).card = b - a := by - rw [← Nat.card_Ioc] - -- Porting note: I had to change this to `erw` *and* provide the proof, yuck. - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [← Finset.map_subtype_embedding_Ioc _ a b (fun c x _ hx _ hc _ => hc.trans_le hx)] - rw [card_map] + rw [← Nat.card_Ioc, ← map_subtype_embedding_Ioc, card_map] @[simp] theorem card_Ioo : (Ioo a b).card = b - a - 1 := by - rw [← Nat.card_Ioo] - -- Porting note: I had to change this to `erw` *and* provide the proof, yuck. - -- https://github.com/leanprover-community/mathlib4/issues/5164 - erw [← Finset.map_subtype_embedding_Ioo _ a b (fun c x _ hx _ hc _ => hc.trans_le hx)] - rw [card_map] + rw [← Nat.card_Ioo, ← map_subtype_embedding_Ioo, card_map] @[simp] theorem card_uIcc : (uIcc a b).card = (b - a : ℤ).natAbs + 1 := by diff --git a/Mathlib/Data/Prod/Basic.lean b/Mathlib/Data/Prod/Basic.lean index f30532075537d..125f987461805 100644 --- a/Mathlib/Data/Prod/Basic.lean +++ b/Mathlib/Data/Prod/Basic.lean @@ -186,12 +186,12 @@ theorem snd_eq_iff : ∀ {p : α × β} {x : β}, p.2 = x ↔ p = (p.1, x) variable {r : α → α → Prop} {s : β → β → Prop} {x y : α × β} -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 _ _ +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 instance Lex.decidable [DecidableEq α] (r : α → α → Prop) (s : β → β → Prop) [DecidableRel r] [DecidableRel s] : DecidableRel (Prod.Lex r s) := - fun _ _ ↦ decidable_of_decidable_of_iff (lex_def r s).symm + fun _ _ ↦ decidable_of_decidable_of_iff lex_def.symm @[refl] theorem Lex.refl_left (r : α → α → Prop) (s : β → β → Prop) [IsRefl α r] : ∀ x, Prod.Lex r s x x diff --git a/Mathlib/Data/Prod/Lex.lean b/Mathlib/Data/Prod/Lex.lean index 1a8b1f220c0f8..b0271fecee021 100644 --- a/Mathlib/Data/Prod/Lex.lean +++ b/Mathlib/Data/Prod/Lex.lean @@ -29,17 +29,13 @@ Related files are: -/ -variable {α β γ : Type*} +variable {α β : Type*} namespace Prod.Lex -@[inherit_doc] notation:35 α " ×ₗ " β:34 => Lex (Prod α β) - -instance decidableEq (α β : Type*) [DecidableEq α] [DecidableEq β] : DecidableEq (α ×ₗ β) := - instDecidableEqProd +open Batteries -instance inhabited (α β : Type*) [Inhabited α] [Inhabited β] : Inhabited (α ×ₗ β) := - instInhabitedProd +@[inherit_doc] notation:35 α " ×ₗ " β:34 => Lex (Prod α β) /-- Dictionary / lexicographic ordering on pairs. -/ instance instLE (α β : Type*) [LT α] [LE β] : LE (α ×ₗ β) where le := Prod.Lex (· < ·) (· ≤ ·) @@ -48,11 +44,11 @@ instance instLT (α β : Type*) [LT α] [LT β] : LT (α ×ₗ β) where lt := P theorem le_iff [LT α] [LE β] (a b : α × β) : toLex a ≤ toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 ≤ b.2 := - Prod.lex_def (· < ·) (· ≤ ·) + Prod.lex_def theorem lt_iff [LT α] [LT β] (a b : α × β) : toLex a < toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 < b.2 := - Prod.lex_def (· < ·) (· < ·) + Prod.lex_def example (x : α) (y : β) : toLex (x, y) = toLex (x, y) := rfl @@ -124,16 +120,36 @@ instance partialOrder (α β : Type*) [PartialOrder α] [PartialOrder β] : Part haveI : IsAntisymm β (· ≤ ·) := ⟨fun _ _ => le_antisymm⟩ exact antisymm (r := Prod.Lex _ _) +instance instOrdLexProd [Ord α] [Ord β] : Ord (α ×ₗ β) := lexOrd + +theorem compare_def [Ord α] [Ord β] : @compare (α ×ₗ β) _ = + compareLex (compareOn fun x => (ofLex x).1) (compareOn fun x => (ofLex x).2) := rfl + +theorem _root_.lexOrd_eq [Ord α] [Ord β] : @lexOrd α β _ _ = instOrdLexProd := rfl + +theorem _root_.Ord.lex_eq [oα : Ord α] [oβ : Ord β] : Ord.lex oα oβ = instOrdLexProd := rfl + +instance [Ord α] [Ord β] [OrientedOrd α] [OrientedOrd β] : OrientedOrd (α ×ₗ β) := + inferInstanceAs (OrientedCmp (compareLex _ _)) + +instance [Ord α] [Ord β] [TransOrd α] [TransOrd β] : TransOrd (α ×ₗ β) := + inferInstanceAs (TransCmp (compareLex _ _)) + /-- Dictionary / lexicographic linear order for pairs. -/ instance linearOrder (α β : Type*) [LinearOrder α] [LinearOrder β] : LinearOrder (α ×ₗ β) := { Prod.Lex.partialOrder α β with - le_total := total_of (Prod.Lex _ _), - decidableLE := Prod.Lex.decidable _ _, - decidableLT := Prod.Lex.decidable _ _, - decidableEq := Lex.decidableEq _ _, } - -instance [Ord α] [Ord β] : Ord (α ×ₗ β) where - compare := compareLex (compareOn (·.1)) (compareOn (·.2)) + le_total := total_of (Prod.Lex _ _) + decidableLE := Prod.Lex.decidable _ _ + decidableLT := Prod.Lex.decidable _ _ + decidableEq := instDecidableEqLex _ + compare_eq_compareOfLessAndEq := fun a b => by + have : DecidableRel (· < · : α ×ₗ β → α ×ₗ β → Prop) := Prod.Lex.decidable _ _ + have : BEqOrd (α ×ₗ β) := ⟨by + simp [compare_def, compareLex, compareOn, Ordering.then_eq_eq, compare_eq_iff_eq]⟩ + have : LTOrd (α ×ₗ β) := ⟨by + simp [compare_def, compareLex, compareOn, Ordering.then_eq_lt, lt_iff, + compare_lt_iff_lt, compare_eq_iff_eq]⟩ + convert LTCmp.eq_compareOfLessAndEq (cmp := compare) a b } instance orderBot [PartialOrder α] [Preorder β] [OrderBot α] [OrderBot β] : OrderBot (α ×ₗ β) where bot := toLex ⊥ diff --git a/Mathlib/Data/Quot.lean b/Mathlib/Data/Quot.lean index 6af294f0b9665..05fbfe253206f 100644 --- a/Mathlib/Data/Quot.lean +++ b/Mathlib/Data/Quot.lean @@ -9,8 +9,11 @@ import Mathlib.Util.Notation3 /-! # Quotient types + This module extends the core library's treatment of quotient types (`Init.Core`). + ## Tags + quotient -/ @@ -18,8 +21,15 @@ variable {α : Sort*} {β : Sort*} namespace Setoid -theorem ext {α : Sort*} : ∀ {s t : Setoid α}, - (∀ a b, @Setoid.r α s a b ↔ @Setoid.r α t a b) → s = t +-- Pretty print `@Setoid.r _ s a b` as `s a b`. +run_cmd Lean.Elab.Command.liftTermElabM do + Lean.Meta.registerCoercion ``Setoid.r + (some { numArgs := 2, coercee := 1, type := .coeFun }) + +instance : CoeFun (Setoid α) (fun _ ↦ α → α → Prop) where + coe := @Setoid.r _ + +theorem ext {α : Sort*} : ∀ {s t : Setoid α}, (∀ a b, s a b ↔ t a b) → s = t | ⟨r, _⟩, ⟨p, _⟩, Eq => by have : r = p := funext fun a ↦ funext fun b ↦ propext <| Eq a b subst this @@ -99,7 +109,6 @@ theorem liftOn_mk (a : α) (f : α → γ) (h : ∀ a₁ a₂, r a₁ a₂ → f ⟨fun hf => hf.comp Quot.exists_rep, fun hf y => let ⟨x, hx⟩ := hf y; ⟨Quot.mk _ x, hx⟩⟩ /-- Descends a function `f : α → β → γ` to quotients of `α` and `β`. -/ --- Porting note: removed `@[elab_as_elim]`, gave "unexpected resulting type γ" -- porting note (#11083): removed `@[reducible]` because it caused extremely slow `simp` protected def lift₂ (f : α → β → γ) (hr : ∀ a b₁ b₂, s b₁ b₂ → f a b₁ = f a b₂) (hs : ∀ a₁ a₂ b, r a₁ a₂ → f a₁ b = f a₂ b) (q₁ : Quot r) (q₂ : Quot s) : γ := @@ -113,7 +122,6 @@ theorem lift₂_mk (f : α → β → γ) (hr : ∀ a b₁ b₂, s b₁ b₂ → rfl /-- Descends a function `f : α → β → γ` to quotients of `α` and `β` and applies it. -/ --- porting note (#11083): removed `@[elab_as_elim]`, gave "unexpected resulting type γ" -- porting note (#11083): removed `@[reducible]` because it caused extremely slow `simp` protected def liftOn₂ (p : Quot r) (q : Quot s) (f : α → β → γ) (hr : ∀ a b₁ b₂, s b₁ b₂ → f a b₁ = f a b₂) (hs : ∀ a₁ a₂ b, r a₁ a₂ → f a₁ b = f a₂ b) : γ := @@ -189,7 +197,7 @@ end Quot namespace Quotient -variable [sa : Setoid α] [sb : Setoid β] +variable {sa : Setoid α} {sb : Setoid β} variable {φ : Quotient sa → Quotient sb → Sort*} -- Porting note: in mathlib3 this notation took the Setoid as an instance-implicit argument, @@ -228,7 +236,7 @@ theorem map_mk (f : α → β) (h : ((· ≈ ·) ⇒ (· ≈ ·)) f f) (x : α) Quotient.map f h (⟦x⟧ : Quotient sa) = (⟦f x⟧ : Quotient sb) := rfl -variable {γ : Sort*} [sc : Setoid γ] +variable {γ : Sort*} {sc : Setoid γ} /-- Map a function `f : α → β → γ` that sends equivalent elements to equivalent elements to a function `f : Quotient sa → Quotient sb → Quotient sc`. @@ -269,7 +277,7 @@ theorem Quot.eq {α : Type*} {r : α → α → Prop} {x y : α} : ⟨Quot.eqvGen_exact, Quot.eqvGen_sound⟩ @[simp] -theorem Quotient.eq [r : Setoid α] {x y : α} : Quotient.mk r x = ⟦y⟧ ↔ x ≈ y := +theorem Quotient.eq {r : Setoid α} {x y : α} : Quotient.mk r x = ⟦y⟧ ↔ x ≈ y := ⟨Quotient.exact, Quotient.sound⟩ theorem Quotient.forall {α : Sort*} {s : Setoid α} {p : Quotient s → Prop} : @@ -281,29 +289,29 @@ theorem Quotient.exists {α : Sort*} {s : Setoid α} {p : Quotient s → Prop} : ⟨fun ⟨q, hq⟩ ↦ q.ind (motive := (p · → _)) .intro hq, fun ⟨a, ha⟩ ↦ ⟨⟦a⟧, ha⟩⟩ @[simp] -theorem Quotient.lift_mk [s : Setoid α] (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) (x : α) : +theorem Quotient.lift_mk {s : Setoid α} (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) (x : α) : Quotient.lift f h (Quotient.mk s x) = f x := rfl @[simp] -theorem Quotient.lift_comp_mk [Setoid α] (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) : +theorem Quotient.lift_comp_mk {_ : Setoid α} (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) : Quotient.lift f h ∘ Quotient.mk _ = f := rfl @[simp] -theorem Quotient.lift₂_mk {α : Sort*} {β : Sort*} {γ : Sort*} [Setoid α] [Setoid β] +theorem Quotient.lift₂_mk {α : Sort*} {β : Sort*} {γ : Sort*} {_ : Setoid α} {_ : Setoid β} (f : α → β → γ) (h : ∀ (a₁ : α) (a₂ : β) (b₁ : α) (b₂ : β), a₁ ≈ b₁ → a₂ ≈ b₂ → f a₁ a₂ = f b₁ b₂) (a : α) (b : β) : Quotient.lift₂ f h (Quotient.mk _ a) (Quotient.mk _ b) = f a b := rfl -theorem Quotient.liftOn_mk [s : Setoid α] (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) (x : α) : +theorem Quotient.liftOn_mk {s : Setoid α} (f : α → β) (h : ∀ a b : α, a ≈ b → f a = f b) (x : α) : Quotient.liftOn (Quotient.mk s x) f h = f x := rfl @[simp] -theorem Quotient.liftOn₂_mk {α : Sort*} {β : Sort*} [Setoid α] (f : α → α → β) +theorem Quotient.liftOn₂_mk {α : Sort*} {β : Sort*} {_ : Setoid α} (f : α → α → β) (h : ∀ a₁ a₂ b₁ b₂ : α, a₁ ≈ b₁ → a₂ ≈ b₂ → f a₁ a₂ = f b₁ b₂) (x y : α) : Quotient.liftOn₂ (Quotient.mk _ x) (Quotient.mk _ y) f h = f x y := rfl @@ -338,22 +346,22 @@ theorem Quot.out_eq {r : α → α → Prop} (q : Quot r) : Quot.mk r q.out = q /-- Choose an element of the equivalence class using the axiom of choice. Sound but noncomputable. -/ -noncomputable def Quotient.out [s : Setoid α] : Quotient s → α := +noncomputable def Quotient.out {s : Setoid α} : Quotient s → α := Quot.out @[simp] -theorem Quotient.out_eq [s : Setoid α] (q : Quotient s) : ⟦q.out⟧ = q := +theorem Quotient.out_eq {s : Setoid α} (q : Quotient s) : ⟦q.out⟧ = q := Quot.out_eq q -theorem Quotient.mk_out [Setoid α] (a : α) : ⟦a⟧.out ≈ a := +theorem Quotient.mk_out {s : Setoid α} (a : α) : (⟦a⟧ : Quotient s).out ≈ a := Quotient.exact (Quotient.out_eq _) -theorem Quotient.mk_eq_iff_out [s : Setoid α] {x : α} {y : Quotient s} : +theorem Quotient.mk_eq_iff_out {s : Setoid α} {x : α} {y : Quotient s} : ⟦x⟧ = y ↔ x ≈ Quotient.out y := by refine Iff.trans ?_ Quotient.eq rw [Quotient.out_eq y] -theorem Quotient.eq_mk_iff_out [s : Setoid α] {x : Quotient s} {y : α} : +theorem Quotient.eq_mk_iff_out {s : Setoid α} {x : Quotient s} {y : α} : x = ⟦y⟧ ↔ Quotient.out x ≈ y := by refine Iff.trans ?_ Quotient.eq rw [Quotient.out_eq x] @@ -379,18 +387,18 @@ instance piSetoid {ι : Sort*} {α : ι → Sort*} [∀ i, Setoid (α i)] : Seto /-- Given a function `f : Π i, Quotient (S i)`, returns the class of functions `Π i, α i` sending each `i` to an element of the class `f i`. -/ -noncomputable def Quotient.choice {ι : Type*} {α : ι → Type*} [S : ∀ i, Setoid (α i)] +noncomputable def Quotient.choice {ι : Type*} {α : ι → Type*} {S : ∀ i, Setoid (α i)} (f : ∀ i, Quotient (S i)) : @Quotient (∀ i, α i) (by infer_instance) := ⟦fun i ↦ (f i).out⟧ @[simp] -theorem Quotient.choice_eq {ι : Type*} {α : ι → Type*} [∀ i, Setoid (α i)] (f : ∀ i, α i) : - (Quotient.choice fun i ↦ ⟦f i⟧) = ⟦f⟧ := +theorem Quotient.choice_eq {ι : Type*} {α : ι → Type*} {S : ∀ i, Setoid (α i)} (f : ∀ i, α i) : + (Quotient.choice (S := S) fun i ↦ ⟦f i⟧) = ⟦f⟧ := Quotient.sound fun _ ↦ Quotient.mk_out _ @[elab_as_elim] -theorem Quotient.induction_on_pi {ι : Type*} {α : ι → Sort*} [s : ∀ i, Setoid (α i)] +theorem Quotient.induction_on_pi {ι : Type*} {α : ι → Sort*} {s : ∀ i, Setoid (α i)} {p : (∀ i, Quotient (s i)) → Prop} (f : ∀ i, Quotient (s i)) (h : ∀ a : ∀ i, α i, p fun i ↦ ⟦a i⟧) : p f := by rw [← (funext fun i ↦ Quotient.out_eq (f i) : (fun i ↦ ⟦(f i).out⟧) = f)] @@ -441,7 +449,6 @@ protected theorem lift_mk (f : α → β) (c) (a : α) : lift f c (mk a) = f a : rfl /-- Lift a constant function on `q : Trunc α`. -/ --- Porting note: removed `@[elab_as_elim]` because it gave "unexpected eliminator resulting type" -- porting note (#11083): removed `@[reducible]` because it caused extremely slow `simp` protected def liftOn (q : Trunc α) (f : α → β) (c : ∀ a b : α, f a = f b) : β := lift f c q @@ -550,9 +557,8 @@ theorem surjective_Quotient_mk'' : Function.Surjective (Quotient.mk'' : α → Q /-- A version of `Quotient.liftOn` taking `{s : Setoid α}` as an implicit argument instead of an instance argument. -/ --- Porting note: removed `@[elab_as_elim]` because it gave "unexpected eliminator resulting type" -- porting note (#11083): removed `@[reducible]` because it caused extremely slow `simp` -protected def liftOn' (q : Quotient s₁) (f : α → φ) (h : ∀ a b, @Setoid.r α s₁ a b → f a = f b) : +protected def liftOn' (q : Quotient s₁) (f : α → φ) (h : ∀ a b, s₁ a b → f a = f b) : φ := Quotient.liftOn q f h @@ -567,10 +573,9 @@ protected theorem liftOn'_mk'' (f : α → φ) (h) (x : α) : /-- A version of `Quotient.liftOn₂` taking `{s₁ : Setoid α} {s₂ : Setoid β}` as implicit arguments instead of instance arguments. -/ --- Porting note: removed `@[elab_as_elim]` because it gave "unexpected eliminator resulting type" -- porting note (#11083): removed `@[reducible]` because it caused extremely slow `simp` protected def liftOn₂' (q₁ : Quotient s₁) (q₂ : Quotient s₂) (f : α → β → γ) - (h : ∀ a₁ a₂ b₁ b₂, @Setoid.r α s₁ a₁ b₁ → @Setoid.r β s₂ a₂ b₂ → f a₁ a₂ = f b₁ b₂) : γ := + (h : ∀ a₁ a₂ b₁ b₂, s₁ a₁ b₁ → s₂ a₂ b₂ → f a₁ a₂ = f b₁ b₂) : γ := Quotient.liftOn₂ q₁ q₂ f h @[simp] @@ -682,19 +687,19 @@ theorem map₂'_mk'' (f : α → β → γ) (h) (x : α) : rfl theorem exact' {a b : α} : - (Quotient.mk'' a : Quotient s₁) = Quotient.mk'' b → @Setoid.r _ s₁ a b := + (Quotient.mk'' a : Quotient s₁) = Quotient.mk'' b → s₁ a b := Quotient.exact -theorem sound' {a b : α} : @Setoid.r _ s₁ a b → @Quotient.mk'' α s₁ a = Quotient.mk'' b := +theorem sound' {a b : α} : s₁ a b → @Quotient.mk'' α s₁ a = Quotient.mk'' b := Quotient.sound @[simp] -protected theorem eq' [s₁ : Setoid α] {a b : α} : - @Quotient.mk' α s₁ a = @Quotient.mk' α s₁ b ↔ @Setoid.r _ s₁ a b := +protected theorem eq' {s₁ : Setoid α} {a b : α} : + @Quotient.mk' α s₁ a = @Quotient.mk' α s₁ b ↔ s₁ a b := Quotient.eq @[simp] -protected theorem eq'' {a b : α} : @Quotient.mk'' α s₁ a = Quotient.mk'' b ↔ @Setoid.r _ s₁ a b := +protected theorem eq'' {a b : α} : @Quotient.mk'' α s₁ a = Quotient.mk'' b ↔ s₁ a b := Quotient.eq /-- A version of `Quotient.out` taking `{s₁ : Setoid α}` as an implicit argument instead of an @@ -706,12 +711,12 @@ noncomputable def out' (a : Quotient s₁) : α := theorem out_eq' (q : Quotient s₁) : Quotient.mk'' q.out' = q := q.out_eq -theorem mk_out' (a : α) : @Setoid.r α s₁ (Quotient.mk'' a : Quotient s₁).out' a := +theorem mk_out' (a : α) : s₁ (Quotient.mk'' a : Quotient s₁).out' a := Quotient.exact (Quotient.out_eq _) section -variable [s : Setoid α] +variable {s : Setoid α} protected theorem mk''_eq_mk : Quotient.mk'' = Quotient.mk s := rfl @@ -721,24 +726,24 @@ protected theorem liftOn'_mk (x : α) (f : α → β) (h) : (Quotient.mk s x).li rfl @[simp] -protected theorem liftOn₂'_mk [t : Setoid β] (f : α → β → γ) (h) (a : α) (b : β) : +protected theorem liftOn₂'_mk {t : Setoid β} (f : α → β → γ) (h) (a : α) (b : β) : Quotient.liftOn₂' (Quotient.mk s a) (Quotient.mk t b) f h = f a b := Quotient.liftOn₂'_mk'' _ _ _ _ @[simp] -theorem map'_mk [t : Setoid β] (f : α → β) (h) (x : α) : +theorem map'_mk {t : Setoid β} (f : α → β) (h) (x : α) : (Quotient.mk s x).map' f h = (Quotient.mk t (f x)) := rfl end -instance (q : Quotient s₁) (f : α → Prop) (h : ∀ a b, @Setoid.r α s₁ a b → f a = f b) +instance (q : Quotient s₁) (f : α → Prop) (h : ∀ a b, s₁ a b → f a = f b) [DecidablePred f] : Decidable (Quotient.liftOn' q f h) := Quotient.lift.decidablePred _ _ q instance (q₁ : Quotient s₁) (q₂ : Quotient s₂) (f : α → β → Prop) - (h : ∀ a₁ b₁ a₂ b₂, @Setoid.r α s₁ a₁ a₂ → @Setoid.r β s₂ b₁ b₂ → f a₁ b₁ = f a₂ b₂) + (h : ∀ a₁ b₁ a₂ b₂, s₁ a₁ a₂ → s₂ b₁ b₂ → f a₁ b₁ = f a₂ b₂) [∀ a, DecidablePred (f a)] : Decidable (Quotient.liftOn₂' q₁ q₂ f h) := Quotient.lift₂.decidablePred _ h _ _ diff --git a/Mathlib/Data/Rat/Cast/Defs.lean b/Mathlib/Data/Rat/Cast/Defs.lean index 643f4426c88c1..739dbc17cb0ce 100644 --- a/Mathlib/Data/Rat/Cast/Defs.lean +++ b/Mathlib/Data/Rat/Cast/Defs.lean @@ -19,10 +19,6 @@ import Mathlib.Data.Rat.Lemmas We define the canonical injection from ℚ into an arbitrary division ring and prove various casting lemmas showing the well-behavedness of this injection. -## Notations - -- `/.` is infix notation for `Rat.divInt`. - ## Tags rat, rationals, field, ℚ, numerator, denominator, num, denom, cast, coercion, casting diff --git a/Mathlib/Data/Rat/Lemmas.lean b/Mathlib/Data/Rat/Lemmas.lean index f684d39ce96de..0aa562b90bce1 100644 --- a/Mathlib/Data/Rat/Lemmas.lean +++ b/Mathlib/Data/Rat/Lemmas.lean @@ -53,7 +53,7 @@ theorem num_mk (n d : ℤ) : (n /. d).num = d.sign * n / n.gcd d := by have (m : ℕ) : Int.natAbs (m + 1) = m + 1 := by rw [← Nat.cast_one, ← Nat.cast_add, Int.natAbs_cast] rcases d with ((_ | _) | _) <;> - rw [← Int.div_eq_ediv_of_dvd] <;> + rw [← Int.tdiv_eq_ediv_of_dvd] <;> simp [divInt, mkRat, Rat.normalize, Nat.succPNat, Int.sign, Int.gcd, Int.zero_ediv, Int.ofNat_dvd_left, Nat.gcd_dvd_left, this] @@ -195,7 +195,7 @@ theorem div_int_inj {a b c d : ℤ} (hb0 : 0 < b) (hd0 : 0 < d) (h1 : Nat.Coprim theorem intCast_div_self (n : ℤ) : ((n / n : ℤ) : ℚ) = n / n := by by_cases hn : n = 0 · subst hn - simp only [Int.cast_zero, Int.zero_div, zero_div, Int.ediv_zero] + simp only [Int.cast_zero, Int.zero_tdiv, zero_div, Int.ediv_zero] · have : (n : ℚ) ≠ 0 := by rwa [← coe_int_inj] at hn simp only [Int.ediv_self hn, Int.cast_one, Ne, not_false_iff, div_self this] @@ -247,9 +247,9 @@ theorem inv_intCast_num (a : ℤ) : (a : ℚ)⁻¹.num = Int.sign a := by rcases lt_trichotomy a 0 with lt | rfl | gt · obtain ⟨a, rfl⟩ : ∃ b, -b = a := ⟨-a, a.neg_neg⟩ simp at lt - simp [Rat.inv_neg, inv_intCast_num_of_pos lt, (Int.sign_eq_one_iff_pos _).mpr lt] - · rfl - · simp [inv_intCast_num_of_pos gt, (Int.sign_eq_one_iff_pos _).mpr gt] + simp [Rat.inv_neg, inv_intCast_num_of_pos lt, Int.sign_eq_one_iff_pos.mpr lt] + · simp + · simp [inv_intCast_num_of_pos gt, Int.sign_eq_one_iff_pos.mpr gt] @[simp] theorem inv_natCast_num (a : ℕ) : (a : ℚ)⁻¹.num = Int.sign a := @@ -268,7 +268,7 @@ theorem inv_intCast_den (a : ℤ) : (a : ℚ)⁻¹.den = if a = 0 then 1 else a. rw [if_neg (by omega)] simp only [Int.cast_neg, Rat.inv_neg, neg_den, inv_intCast_den_of_pos lt, Int.natAbs_neg] exact Int.eq_natAbs_of_zero_le (by omega) - · rfl + · simp · rw [if_neg (by omega)] simp only [inv_intCast_den_of_pos gt] exact Int.eq_natAbs_of_zero_le (by omega) diff --git a/Mathlib/Data/Real/Archimedean.lean b/Mathlib/Data/Real/Archimedean.lean index 320d601909bab..5c7543769551c 100644 --- a/Mathlib/Data/Real/Archimedean.lean +++ b/Mathlib/Data/Real/Archimedean.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, Floris van Doorn -/ -import Mathlib.Algebra.Bounds import Mathlib.Algebra.Order.Archimedean.Basic +import Mathlib.Algebra.Order.Group.Pointwise.Bounds import Mathlib.Data.Real.Basic import Mathlib.Order.Interval.Set.Disjoint @@ -17,6 +17,7 @@ open scoped Classical open Pointwise CauSeq namespace Real +variable {ι : Sort*} {f : ι → ℝ} {s : Set ℝ} {a : ℝ} instance instArchimedean : Archimedean ℝ := archimedean_iff_rat_le.2 fun x => @@ -49,9 +50,9 @@ theorem exists_floor (x : ℝ) : ∃ ub : ℤ, (ub : ℝ) ≤ x ∧ ∀ z : ℤ, (let ⟨n, hn⟩ := exists_int_lt x ⟨n, le_of_lt hn⟩) -theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ x, IsLUB S x := by +theorem exists_isLUB (hne : s.Nonempty) (hbdd : BddAbove s) : ∃ x, IsLUB s x := by rcases hne, hbdd with ⟨⟨L, hL⟩, ⟨U, hU⟩⟩ - have : ∀ d : ℕ, BddAbove { m : ℤ | ∃ y ∈ S, (m : ℝ) ≤ y * d } := by + have : ∀ d : ℕ, BddAbove { m : ℤ | ∃ y ∈ s, (m : ℝ) ≤ y * d } := by cases' exists_int_gt U with k hk refine fun d => ⟨k * d, fun z h => ?_⟩ rcases h with ⟨y, yS, hy⟩ @@ -60,14 +61,14 @@ theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ exact mul_le_mul_of_nonneg_right ((hU yS).trans hk.le) d.cast_nonneg choose f hf using fun d : ℕ => Int.exists_greatest_of_bdd (this d) ⟨⌊L * d⌋, L, hL, Int.floor_le _⟩ - have hf₁ : ∀ n > 0, ∃ y ∈ S, ((f n / n : ℚ) : ℝ) ≤ y := fun n n0 => + have hf₁ : ∀ n > 0, ∃ y ∈ s, ((f n / n : ℚ) : ℝ) ≤ y := fun n n0 => let ⟨y, yS, hy⟩ := (hf n).1 ⟨y, yS, by simpa using (div_le_iff₀ (Nat.cast_pos.2 n0 : (_ : ℝ) < _)).2 hy⟩ - have hf₂ : ∀ n > 0, ∀ y ∈ S, (y - ((n : ℕ) : ℝ)⁻¹) < (f n / n : ℚ) := by + have hf₂ : ∀ n > 0, ∀ y ∈ s, (y - ((n : ℕ) : ℝ)⁻¹) < (f n / n : ℚ) := by intro n n0 y yS have := (Int.sub_one_lt_floor _).trans_le (Int.cast_le.2 <| (hf n).2 _ ⟨y, yS, Int.floor_le _⟩) simp only [Rat.cast_div, Rat.cast_intCast, Rat.cast_natCast, gt_iff_lt] - rwa [lt_div_iff (Nat.cast_pos.2 n0 : (_ : ℝ) < _), sub_mul, inv_mul_cancel₀] + rwa [lt_div_iff₀ (Nat.cast_pos.2 n0 : (_ : ℝ) < _), sub_mul, inv_mul_cancel₀] exact ne_of_gt (Nat.cast_pos.2 n0) have hg : IsCauSeq abs (fun n => f n / n : ℕ → ℚ) := by intro ε ε0 @@ -81,7 +82,7 @@ theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ have j0 := Nat.cast_pos.1 ((inv_pos.2 ε0).trans_le ij) have k0 := Nat.cast_pos.1 ((inv_pos.2 ε0).trans_le ik) rcases hf₁ _ j0 with ⟨y, yS, hy⟩ - refine lt_of_lt_of_le ((Rat.cast_lt (K := ℝ)).1 ?_) ((inv_le ε0 (Nat.cast_pos.2 k0)).1 ik) + refine lt_of_lt_of_le ((Rat.cast_lt (K := ℝ)).1 ?_) ((inv_le_comm₀ ε0 (Nat.cast_pos.2 k0)).1 ik) simpa using sub_lt_iff_lt_add'.2 (lt_of_le_of_lt hy <| sub_lt_iff_lt_add.1 <| hf₂ _ k0 _ yS) let g : CauSeq ℚ abs := ⟨fun n => f n / n, hg⟩ refine ⟨mk g, ⟨fun x xS => ?_, fun y h => ?_⟩⟩ @@ -92,7 +93,7 @@ theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ replace hK := hK.le.trans (Nat.cast_le.2 nK) have n0 : 0 < n := Nat.cast_pos.1 ((inv_pos.2 xz).trans_le hK) refine le_trans ?_ (hf₂ _ n0 _ xS).le - rwa [le_sub_comm, inv_le (Nat.cast_pos.2 n0 : (_ : ℝ) < _) xz] + rwa [le_sub_comm, inv_le_comm₀ (Nat.cast_pos.2 n0 : (_ : ℝ) < _) xz] · exact mk_le_of_forall_le ⟨1, fun n n1 => @@ -100,56 +101,52 @@ theorem exists_isLUB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddAbove S) : ∃ le_trans hx (h xS)⟩ /-- A nonempty, bounded below set of real numbers has a greatest lower bound. -/ -theorem exists_isGLB {S : Set ℝ} (hne : S.Nonempty) (hbdd : BddBelow S) : ∃ x, IsGLB S x := by - have hne' : (-S).Nonempty := Set.nonempty_neg.mpr hne - have hbdd' : BddAbove (-S) := bddAbove_neg.mpr hbdd +theorem exists_isGLB (hne : s.Nonempty) (hbdd : BddBelow s) : ∃ x, IsGLB s x := by + have hne' : (-s).Nonempty := Set.nonempty_neg.mpr hne + have hbdd' : BddAbove (-s) := bddAbove_neg.mpr hbdd use -Classical.choose (Real.exists_isLUB hne' hbdd') rw [← isLUB_neg] exact Classical.choose_spec (Real.exists_isLUB hne' hbdd') noncomputable instance : SupSet ℝ := - ⟨fun S => if h : S.Nonempty ∧ BddAbove S then Classical.choose (exists_isLUB h.1 h.2) else 0⟩ + ⟨fun s => if h : s.Nonempty ∧ BddAbove s then Classical.choose (exists_isLUB h.1 h.2) else 0⟩ -theorem sSup_def (S : Set ℝ) : - sSup S = if h : S.Nonempty ∧ BddAbove S then Classical.choose (exists_isLUB h.1 h.2) else 0 := +theorem sSup_def (s : Set ℝ) : + sSup s = if h : s.Nonempty ∧ BddAbove s then Classical.choose (exists_isLUB h.1 h.2) else 0 := rfl -protected theorem isLUB_sSup (S : Set ℝ) (h₁ : S.Nonempty) (h₂ : BddAbove S) : - IsLUB S (sSup S) := by +protected theorem isLUB_sSup (h₁ : s.Nonempty) (h₂ : BddAbove s) : IsLUB s (sSup s) := by simp only [sSup_def, dif_pos (And.intro h₁ h₂)] apply Classical.choose_spec noncomputable instance : InfSet ℝ := - ⟨fun S => -sSup (-S)⟩ + ⟨fun s => -sSup (-s)⟩ -theorem sInf_def (S : Set ℝ) : sInf S = -sSup (-S) := - rfl +theorem sInf_def (s : Set ℝ) : sInf s = -sSup (-s) := rfl -protected theorem is_glb_sInf (S : Set ℝ) (h₁ : S.Nonempty) (h₂ : BddBelow S) : - IsGLB S (sInf S) := by +protected theorem isGLB_sInf (h₁ : s.Nonempty) (h₂ : BddBelow s) : IsGLB s (sInf s) := by rw [sInf_def, ← isLUB_neg', neg_neg] - exact Real.isLUB_sSup _ h₁.neg h₂.neg - -noncomputable instance : ConditionallyCompleteLinearOrder ℝ := - { Real.linearOrder, Real.lattice with - sSup := SupSet.sSup - sInf := InfSet.sInf - le_csSup := fun s a hs ha => (Real.isLUB_sSup s ⟨a, ha⟩ hs).1 ha - csSup_le := fun s a hs ha => (Real.isLUB_sSup s hs ⟨a, ha⟩).2 ha - csInf_le := fun s a hs ha => (Real.is_glb_sInf s ⟨a, ha⟩ hs).1 ha - le_csInf := fun s a hs ha => (Real.is_glb_sInf s hs ⟨a, ha⟩).2 ha - csSup_of_not_bddAbove := fun s hs ↦ by simp [hs, sSup_def] - csInf_of_not_bddBelow := fun s hs ↦ by simp [hs, sInf_def, sSup_def] } - -theorem lt_sInf_add_pos {s : Set ℝ} (h : s.Nonempty) {ε : ℝ} (hε : 0 < ε) : - ∃ a ∈ s, a < sInf s + ε := + exact Real.isLUB_sSup h₁.neg h₂.neg + +@[deprecated (since := "2024-10-02")] alias is_glb_sInf := isGLB_sInf + +noncomputable instance : ConditionallyCompleteLinearOrder ℝ where + __ := Real.linearOrder + __ := Real.lattice + le_csSup s a hs ha := (Real.isLUB_sSup ⟨a, ha⟩ hs).1 ha + csSup_le s a hs ha := (Real.isLUB_sSup hs ⟨a, ha⟩).2 ha + csInf_le s a hs ha := (Real.isGLB_sInf ⟨a, ha⟩ hs).1 ha + le_csInf s a hs ha := (Real.isGLB_sInf hs ⟨a, ha⟩).2 ha + csSup_of_not_bddAbove s hs := by simp [hs, sSup_def] + csInf_of_not_bddBelow s hs := by simp [hs, sInf_def, sSup_def] + +theorem lt_sInf_add_pos (h : s.Nonempty) {ε : ℝ} (hε : 0 < ε) : ∃ a ∈ s, a < sInf s + ε := exists_lt_of_csInf_lt h <| lt_add_of_pos_right _ hε -theorem add_neg_lt_sSup {s : Set ℝ} (h : s.Nonempty) {ε : ℝ} (hε : ε < 0) : - ∃ a ∈ s, sSup s + ε < a := +theorem add_neg_lt_sSup (h : s.Nonempty) {ε : ℝ} (hε : ε < 0) : ∃ a ∈ s, sSup s + ε < a := exists_lt_of_lt_csSup h <| add_lt_iff_neg_left.2 hε -theorem sInf_le_iff {s : Set ℝ} (h : BddBelow s) (h' : s.Nonempty) {a : ℝ} : +theorem sInf_le_iff (h : BddBelow s) (h' : s.Nonempty) : sInf s ≤ a ↔ ∀ ε, 0 < ε → ∃ x ∈ s, x < a + ε := by rw [le_iff_forall_pos_lt_add] constructor <;> intro H ε ε_pos @@ -157,7 +154,7 @@ theorem sInf_le_iff {s : Set ℝ} (h : BddBelow s) (h' : s.Nonempty) {a : ℝ} : · rcases H ε ε_pos with ⟨x, x_in, hx⟩ exact csInf_lt_of_lt h x_in hx -theorem le_sSup_iff {s : Set ℝ} (h : BddAbove s) (h' : s.Nonempty) {a : ℝ} : +theorem le_sSup_iff (h : BddAbove s) (h' : s.Nonempty) : a ≤ sSup s ↔ ∀ ε, ε < 0 → ∃ x ∈ s, a + ε < x := by rw [le_iff_forall_pos_lt_add] refine ⟨fun H ε ε_neg => ?_, fun H ε ε_pos => ?_⟩ @@ -169,102 +166,128 @@ theorem le_sSup_iff {s : Set ℝ} (h : BddAbove s) (h' : s.Nonempty) {a : ℝ} : theorem sSup_empty : sSup (∅ : Set ℝ) = 0 := dif_neg <| by simp -@[simp] lemma iSup_of_isEmpty {α : Sort*} [IsEmpty α] (f : α → ℝ) : ⨆ i, f i = 0 := by +@[simp] lemma iSup_of_isEmpty [IsEmpty ι] (f : ι → ℝ) : ⨆ i, f i = 0 := by dsimp [iSup] convert Real.sSup_empty rw [Set.range_eq_empty_iff] infer_instance @[simp] -theorem ciSup_const_zero {α : Sort*} : ⨆ _ : α, (0 : ℝ) = 0 := by - cases isEmpty_or_nonempty α +theorem iSup_const_zero : ⨆ _ : ι, (0 : ℝ) = 0 := by + cases isEmpty_or_nonempty ι · exact Real.iSup_of_isEmpty _ · exact ciSup_const -theorem sSup_of_not_bddAbove {s : Set ℝ} (hs : ¬BddAbove s) : sSup s = 0 := - dif_neg fun h => hs h.2 - -theorem iSup_of_not_bddAbove {α : Sort*} {f : α → ℝ} (hf : ¬BddAbove (Set.range f)) : - ⨆ i, f i = 0 := - sSup_of_not_bddAbove hf +lemma sSup_of_not_bddAbove (hs : ¬BddAbove s) : sSup s = 0 := dif_neg fun h => hs h.2 +lemma iSup_of_not_bddAbove (hf : ¬BddAbove (Set.range f)) : ⨆ i, f i = 0 := sSup_of_not_bddAbove hf theorem sSup_univ : sSup (@Set.univ ℝ) = 0 := Real.sSup_of_not_bddAbove not_bddAbove_univ @[simp] theorem sInf_empty : sInf (∅ : Set ℝ) = 0 := by simp [sInf_def, sSup_empty] -@[simp] nonrec lemma iInf_of_isEmpty {α : Sort*} [IsEmpty α] (f : α → ℝ) : ⨅ i, f i = 0 := by +@[simp] nonrec lemma iInf_of_isEmpty [IsEmpty ι] (f : ι → ℝ) : ⨅ i, f i = 0 := by rw [iInf_of_isEmpty, sInf_empty] @[simp] -theorem ciInf_const_zero {α : Sort*} : ⨅ _ : α, (0 : ℝ) = 0 := by - cases isEmpty_or_nonempty α +theorem iInf_const_zero : ⨅ _ : ι, (0 : ℝ) = 0 := by + cases isEmpty_or_nonempty ι · exact Real.iInf_of_isEmpty _ · exact ciInf_const -theorem sInf_of_not_bddBelow {s : Set ℝ} (hs : ¬BddBelow s) : sInf s = 0 := +theorem sInf_of_not_bddBelow (hs : ¬BddBelow s) : sInf s = 0 := neg_eq_zero.2 <| sSup_of_not_bddAbove <| mt bddAbove_neg.1 hs -theorem iInf_of_not_bddBelow {α : Sort*} {f : α → ℝ} (hf : ¬BddBelow (Set.range f)) : - ⨅ i, f i = 0 := +theorem iInf_of_not_bddBelow (hf : ¬BddBelow (Set.range f)) : ⨅ i, f i = 0 := sInf_of_not_bddBelow hf -/-- -As `0` is the default value for `Real.sSup` of the empty set or sets which are not bounded above, it -suffices to show that `S` is bounded below by `0` to show that `0 ≤ sSup S`. --/ -theorem sSup_nonneg (S : Set ℝ) (hS : ∀ x ∈ S, (0 : ℝ) ≤ x) : 0 ≤ sSup S := by - rcases S.eq_empty_or_nonempty with (rfl | ⟨y, hy⟩) - · exact sSup_empty.ge - · apply dite _ (fun h => le_csSup_of_le h hy <| hS y hy) fun h => (sSup_of_not_bddAbove h).ge +/-- As `sSup s = 0` when `s` is an empty set of reals, it suffices to show that all elements of `s` +are at most some nonnegative number `a` to show that `sSup s ≤ a`. -/-- -As `0` is the default value for `Real.sSup` of the empty set or sets which are not bounded above, it -suffices to show that `f i` is nonnegative to show that `0 ≤ ⨆ i, f i`. --/ -protected theorem iSup_nonneg {ι : Sort*} {f : ι → ℝ} (hf : ∀ i, 0 ≤ f i) : 0 ≤ ⨆ i, f i := - sSup_nonneg _ <| Set.forall_mem_range.2 hf +See also `csSup_le`. -/ +protected lemma sSup_le (hs : ∀ x ∈ s, x ≤ a) (ha : 0 ≤ a) : sSup s ≤ a := by + obtain rfl | hs' := s.eq_empty_or_nonempty + exacts [sSup_empty.trans_le ha, csSup_le hs' hs] -/-- -As `0` is the default value for `Real.sSup` of the empty set or sets which are not bounded above, it -suffices to show that all elements of `S` are bounded by a nonnegative number to show that `sSup S` -is bounded by this number. --/ -protected theorem sSup_le {S : Set ℝ} {a : ℝ} (hS : ∀ x ∈ S, x ≤ a) (ha : 0 ≤ a) : sSup S ≤ a := by - rcases S.eq_empty_or_nonempty with (rfl | hS₂) - exacts [sSup_empty.trans_le ha, csSup_le hS₂ hS] +/-- As `⨆ i, f i = 0` when the domain of the real-valued function `f` is empty, it suffices to show +that all values of `f` are at most some nonnegative number `a` to show that `⨆ i, f i ≤ a`. -protected theorem iSup_le {ι : Sort*} {f : ι → ℝ} {a : ℝ} (hS : ∀ i, f i ≤ a) (ha : 0 ≤ a) : - ⨆ i, f i ≤ a := - Real.sSup_le (Set.forall_mem_range.2 hS) ha +See also `ciSup_le`. -/ +protected lemma iSup_le (hf : ∀ i, f i ≤ a) (ha : 0 ≤ a) : ⨆ i, f i ≤ a := + Real.sSup_le (Set.forall_mem_range.2 hf) ha -/-- As `0` is the default value for `Real.sSup` of the empty set, it suffices to show that `S` is -bounded above by `0` to show that `sSup S ≤ 0`. --/ -theorem sSup_nonpos (S : Set ℝ) (hS : ∀ x ∈ S, x ≤ (0 : ℝ)) : sSup S ≤ 0 := - Real.sSup_le hS le_rfl +/-- As `sInf s = 0` when `s` is an empty set of reals, it suffices to show that all elements of `s` +are at least some nonpositive number `a` to show that `a ≤ sInf s`. -/-- As `0` is the default value for `Real.sInf` of the empty set, it suffices to show that `S` is -bounded below by `0` to show that `0 ≤ sInf S`. --/ -theorem sInf_nonneg (S : Set ℝ) (hS : ∀ x ∈ S, (0 : ℝ) ≤ x) : 0 ≤ sInf S := by - rcases S.eq_empty_or_nonempty with (rfl | hS₂) - exacts [sInf_empty.ge, le_csInf hS₂ hS] +See also `le_csInf`. -/ +protected lemma le_sInf (hs : ∀ x ∈ s, a ≤ x) (ha : a ≤ 0) : a ≤ sInf s := by + obtain rfl | hs' := s.eq_empty_or_nonempty + exacts [ha.trans_eq sInf_empty.symm, le_csInf hs' hs] -/-- As `0` is the default value for `Real.sInf` of the empty set, it suffices to show that `f i` is -bounded below by `0` to show that `0 ≤ iInf f`. --/ -theorem iInf_nonneg {ι} {f : ι → ℝ} (hf : ∀ i, 0 ≤ f i) : 0 ≤ iInf f := - sInf_nonneg _ <| Set.forall_mem_range.2 hf +/-- As `⨅ i, f i = 0` when the domain of the real-valued function `f` is empty, it suffices to show +that all values of `f` are at least some nonpositive number `a` to show that `a ≤ ⨅ i, f i`. -/-- -As `0` is the default value for `Real.sInf` of the empty set or sets which are not bounded below, it -suffices to show that `S` is bounded above by `0` to show that `sInf S ≤ 0`. --/ -theorem sInf_nonpos (S : Set ℝ) (hS : ∀ x ∈ S, x ≤ (0 : ℝ)) : sInf S ≤ 0 := by - rcases S.eq_empty_or_nonempty with (rfl | ⟨y, hy⟩) +See also `le_ciInf`. -/ +protected lemma le_iInf (hf : ∀ i, a ≤ f i) (ha : a ≤ 0) : a ≤ ⨅ i, f i := + Real.le_sInf (Set.forall_mem_range.2 hf) ha + +/-- As `sSup s = 0` when `s` is an empty set of reals, it suffices to show that all elements of `s` +are nonpositive to show that `sSup s ≤ 0`. -/ +lemma sSup_nonpos (hs : ∀ x ∈ s, x ≤ 0) : sSup s ≤ 0 := Real.sSup_le hs le_rfl + +/-- As `⨆ i, f i = 0` when the domain of the real-valued function `f` is empty, +it suffices to show that all values of `f` are nonpositive to show that `⨆ i, f i ≤ 0`. -/ +lemma iSup_nonpos (hf : ∀ i, f i ≤ 0) : ⨆ i, f i ≤ 0 := Real.iSup_le hf le_rfl + +/-- As `sInf s = 0` when `s` is an empty set of reals, it suffices to show that all elements of `s` +are nonnegative to show that `0 ≤ sInf s`. -/ +lemma sInf_nonneg (hs : ∀ x ∈ s, 0 ≤ x) : 0 ≤ sInf s := Real.le_sInf hs le_rfl + +/-- As `⨅ i, f i = 0` when the domain of the real-valued function `f` is empty, +it suffices to show that all values of `f` are nonnegative to show that `0 ≤ ⨅ i, f i`. -/ +lemma iInf_nonneg (hf : ∀ i, 0 ≤ f i) : 0 ≤ iInf f := Real.le_iInf hf le_rfl + +/-- As `sSup s = 0` when `s` is a set of reals that's unbounded above, it suffices to show that `s` +contains a nonnegative element to show that `0 ≤ sSup s`. -/ +lemma sSup_nonneg' (hs : ∃ x ∈ s, 0 ≤ x) : 0 ≤ sSup s := by + obtain ⟨x, hxs, hx⟩ := hs + exact dite _ (fun h ↦ le_csSup_of_le h hxs hx) fun h ↦ (sSup_of_not_bddAbove h).ge + +/-- As `⨆ i, f i = 0` when the real-valued function `f` is unbounded above, +it suffices to show that `f` takes a nonnegative value to show that `0 ≤ ⨆ i, f i`. -/ +lemma iSup_nonneg' (hf : ∃ i, 0 ≤ f i) : 0 ≤ ⨆ i, f i := sSup_nonneg' <| Set.exists_range_iff.2 hf + +/-- As `sInf s = 0` when `s` is a set of reals that's unbounded below, it suffices to show that `s` +contains a nonpositive element to show that `sInf s ≤ 0`. -/ +lemma sInf_nonpos' (hs : ∃ x ∈ s, x ≤ 0) : sInf s ≤ 0 := by + obtain ⟨x, hxs, hx⟩ := hs + exact dite _ (fun h ↦ csInf_le_of_le h hxs hx) fun h ↦ (sInf_of_not_bddBelow h).le + +/-- As `⨅ i, f i = 0` when the real-valued function `f` is unbounded below, +it suffices to show that `f` takes a nonpositive value to show that `0 ≤ ⨅ i, f i`. -/ +lemma iInf_nonpos' (hf : ∃ i, f i ≤ 0) : ⨅ i, f i ≤ 0 := sInf_nonpos' <| Set.exists_range_iff.2 hf + +/-- As `sSup s = 0` when `s` is a set of reals that's either empty or unbounded above, +it suffices to show that all elements of `s` are nonnegative to show that `0 ≤ sSup s`. -/ +lemma sSup_nonneg (hs : ∀ x ∈ s, 0 ≤ x) : 0 ≤ sSup s := by + obtain rfl | ⟨x, hx⟩ := s.eq_empty_or_nonempty + · exact sSup_empty.ge + · exact sSup_nonneg' ⟨x, hx, hs _ hx⟩ + +/-- As `⨆ i, f i = 0` when the domain of the real-valued function `f` is empty or unbounded above, +it suffices to show that all values of `f` are nonnegative to show that `0 ≤ ⨆ i, f i`. -/ +lemma iSup_nonneg (hf : ∀ i, 0 ≤ f i) : 0 ≤ ⨆ i, f i := sSup_nonneg <| Set.forall_mem_range.2 hf + +/-- As `sInf s = 0` when `s` is a set of reals that's either empty or unbounded below, +it suffices to show that all elements of `s` are nonpositive to show that `sInf s ≤ 0`. -/ +lemma sInf_nonpos (hs : ∀ x ∈ s, x ≤ 0) : sInf s ≤ 0 := by + obtain rfl | ⟨x, hx⟩ := s.eq_empty_or_nonempty · exact sInf_empty.le - · apply dite _ (fun h => csInf_le_of_le h hy <| hS y hy) fun h => (sInf_of_not_bddBelow h).le + · exact sInf_nonpos' ⟨x, hx, hs _ hx⟩ + +/-- As `⨅ i, f i = 0` when the domain of the real-valued function `f` is empty or unbounded below, +it suffices to show that all values of `f` are nonpositive to show that `0 ≤ ⨅ i, f i`. -/ +lemma iInf_nonpos (hf : ∀ i, f i ≤ 0) : ⨅ i, f i ≤ 0 := sInf_nonpos <| Set.forall_mem_range.2 hf theorem sInf_le_sSup (s : Set ℝ) (h₁ : BddBelow s) (h₂ : BddAbove s) : sInf s ≤ sSup s := by rcases s.eq_empty_or_nonempty with (rfl | hne) @@ -272,12 +295,12 @@ theorem sInf_le_sSup (s : Set ℝ) (h₁ : BddBelow s) (h₂ : BddAbove s) : sIn · exact csInf_le_csSup h₁ h₂ hne theorem cauSeq_converges (f : CauSeq ℝ abs) : ∃ x, f ≈ const abs x := by - let S := { x : ℝ | const abs x < f } - have lb : ∃ x, x ∈ S := exists_lt f - have ub' : ∀ x, f < const abs x → ∀ y ∈ S, y ≤ x := fun x h y yS => + let s := {x : ℝ | const abs x < f} + have lb : ∃ x, x ∈ s := exists_lt f + have ub' : ∀ x, f < const abs x → ∀ y ∈ s, y ≤ x := fun x h y yS => le_of_lt <| const_lt.1 <| CauSeq.lt_trans yS h - have ub : ∃ x, ∀ y ∈ S, y ≤ x := (exists_gt f).imp ub' - refine ⟨sSup S, ((lt_total _ _).resolve_left fun h => ?_).resolve_right fun h => ?_⟩ + have ub : ∃ x, ∀ y ∈ s, y ≤ x := (exists_gt f).imp ub' + refine ⟨sSup s, ((lt_total _ _).resolve_left fun h => ?_).resolve_right fun h => ?_⟩ · rcases h with ⟨ε, ε0, i, ih⟩ refine (csSup_le lb (ub' _ ?_)).not_lt (sub_lt_self _ (half_pos ε0)) refine ⟨_, half_pos ε0, i, fun j ij => ?_⟩ @@ -336,8 +359,7 @@ theorem iInter_Iic_rat : ⋂ r : ℚ, Iic (r : ℝ) = ∅ := by exact iInter_Iic_eq_empty_iff.mpr not_bddBelow_coe /-- Exponentiation is eventually larger than linear growth. -/ -lemma exists_natCast_add_one_lt_pow_of_one_lt {a : ℝ} (ha : 1 < a) : - ∃ m : ℕ, (m + 1 : ℝ) < a ^ m := by +lemma exists_natCast_add_one_lt_pow_of_one_lt (ha : 1 < a) : ∃ m : ℕ, (m + 1 : ℝ) < a ^ m := by obtain ⟨k, posk, hk⟩ : ∃ k : ℕ, 0 < k ∧ 1 / k + 1 < a := by contrapose! ha refine le_of_forall_lt_rat_imp_le ?_ diff --git a/Mathlib/Data/Real/Basic.lean b/Mathlib/Data/Real/Basic.lean index 8de982a5ba82f..7cec019cb7dbe 100644 --- a/Mathlib/Data/Real/Basic.lean +++ b/Mathlib/Data/Real/Basic.lean @@ -600,3 +600,10 @@ def IsNonarchimedean {A : Type*} [Add A] (f : A → ℝ) : Prop := `f (r ^ n) = (f r) ^ n`. -/ def IsPowMul {R : Type*} [Pow R ℕ] (f : R → ℝ) := ∀ (a : R) {n : ℕ}, 1 ≤ n → f (a ^ n) = f a ^ n + +/-- A ring homomorphism `f : α →+* β` is bounded with respect to the functions `nα : α → ℝ` and + `nβ : β → ℝ` if there exists a positive constant `C` such that for all `x` in `α`, + `nβ (f x) ≤ C * nα x`. -/ +def RingHom.IsBoundedWrt {α : Type*} [Ring α] {β : Type*} [Ring β] (nα : α → ℝ) (nβ : β → ℝ) + (f : α →+* β) : Prop := + ∃ C : ℝ, 0 < C ∧ ∀ x : α, nβ (f x) ≤ C * nα x diff --git a/Mathlib/Data/Real/ConjExponents.lean b/Mathlib/Data/Real/ConjExponents.lean index 5323170031fd4..04bfc20da0ec1 100644 --- a/Mathlib/Data/Real/ConjExponents.lean +++ b/Mathlib/Data/Real/ConjExponents.lean @@ -18,6 +18,8 @@ analysis, especially when dealing with `L^p` spaces. * `Real.conjExponent`: Conjugate exponent of a real number. * `NNReal.IsConjExponent`: Predicate for two nonnegative real numbers to be conjugate. * `NNReal.conjExponent`: Conjugate exponent of a nonnegative real number. +* `ENNReal.IsConjExponent`: Predicate for two extended nonnegative real numbers to be conjugate. +* `ENNReal.conjExponent`: Conjugate exponent of an extended nonnegative real number. ## TODO @@ -27,7 +29,7 @@ analysis, especially when dealing with `L^p` spaces. noncomputable section -open scoped ENNReal +open scoped ENNReal NNReal namespace Real @@ -106,7 +108,7 @@ theorem inv_add_inv_conj_ennreal : (ENNReal.ofReal p)⁻¹ + (ENNReal.ofReal q) end protected lemma inv_inv (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) : a⁻¹.IsConjExponent b⁻¹ := - ⟨one_lt_inv ha <| by linarith, by simpa only [inv_inv]⟩ + ⟨(one_lt_inv₀ ha).2 <| by linarith, by simpa only [inv_inv]⟩ lemma inv_one_sub_inv (ha₀ : 0 < a) (ha₁ : a < 1) : a⁻¹.IsConjExponent (1 - a)⁻¹ := .inv_inv ha₀ (sub_pos_of_lt ha₁) <| add_tsub_cancel_of_le ha₁.le @@ -116,6 +118,8 @@ lemma one_sub_inv_inv (ha₀ : 0 < a) (ha₁ : a < 1) : (1 - a)⁻¹.IsConjExpon end IsConjExponent +lemma isConjExponent_comm : p.IsConjExponent q ↔ q.IsConjExponent p := ⟨.symm, .symm⟩ + lemma isConjExponent_iff_eq_conjExponent (hp : 1 < p) : p.IsConjExponent q ↔ q = p / (p - 1) := ⟨IsConjExponent.conj_eq, fun h ↦ ⟨hp, by field_simp [h]⟩⟩ @@ -195,7 +199,7 @@ end protected lemma inv_inv (ha : a ≠ 0) (hb : b ≠ 0) (hab : a + b = 1) : a⁻¹.IsConjExponent b⁻¹ := - ⟨one_lt_inv ha.bot_lt <| by rw [← hab]; exact lt_add_of_pos_right _ hb.bot_lt, by + ⟨(one_lt_inv₀ ha.bot_lt).2 <| by rw [← hab]; exact lt_add_of_pos_right _ hb.bot_lt, by simpa only [inv_inv] using hab⟩ lemma inv_one_sub_inv (ha₀ : a ≠ 0) (ha₁ : a < 1) : a⁻¹.IsConjExponent (1 - a)⁻¹ := @@ -206,6 +210,8 @@ lemma one_sub_inv_inv (ha₀ : a ≠ 0) (ha₁ : a < 1) : (1 - a)⁻¹.IsConjExp end IsConjExponent +lemma isConjExponent_comm : p.IsConjExponent q ↔ q.IsConjExponent p := ⟨.symm, .symm⟩ + lemma isConjExponent_iff_eq_conjExponent (h : 1 < p) : p.IsConjExponent q ↔ q = p / (p - 1) := by rw [← isConjExponent_coe, Real.isConjExponent_iff_eq_conjExponent (mod_cast h), ← coe_inj, NNReal.coe_div, NNReal.coe_sub h.le, coe_one] @@ -220,3 +226,120 @@ protected lemma Real.IsConjExponent.toNNReal {p q : ℝ} (hpq : p.IsConjExponent one_lt := by simpa using hpq.one_lt inv_add_inv_conj := by rw [← toNNReal_inv, ← toNNReal_inv, ← toNNReal_add hpq.inv_nonneg hpq.symm.inv_nonneg, hpq.inv_add_inv_conj, toNNReal_one] + +namespace ENNReal + +/-- Two extended nonnegative real exponents `p, q` are conjugate and satisfy the equality +`1/p + 1/q = 1`. This condition shows up in many theorems in analysis, notably related to `L^p` +norms. Note that we permit one of the exponents to be `∞` and the other `1`. -/ +@[mk_iff] +structure IsConjExponent (p q : ℝ≥0∞) : Prop where + inv_add_inv_conj : p⁻¹ + q⁻¹ = 1 + +/-- The conjugate exponent of `p` is `q = 1 + (p - 1)⁻¹`, so that `1/p + 1/q = 1`. -/ +noncomputable def conjExponent (p : ℝ≥0∞) : ℝ≥0∞ := 1 + (p - 1)⁻¹ + +lemma coe_conjExponent {p : ℝ≥0} (hp : 1 < p) : p.conjExponent = conjExponent p := by + rw [NNReal.conjExponent, conjExponent] + norm_cast + rw [← coe_inv (tsub_pos_of_lt hp).ne'] + norm_cast + field_simp [(tsub_pos_of_lt hp).ne'] + rw [tsub_add_cancel_of_le hp.le] + +variable {a b p q : ℝ≥0∞} (h : p.IsConjExponent q) + +@[simp, norm_cast] lemma isConjExponent_coe {p q : ℝ≥0} : + IsConjExponent p q ↔ p.IsConjExponent q := by + simp only [isConjExponent_iff, NNReal.isConjExponent_iff] + refine ⟨fun h ↦ ⟨?_, ?_⟩, ?_⟩ + · simpa using (ENNReal.lt_add_right (fun hp ↦ by simp [hp] at h) <| by simp).trans_eq h + · rw [← coe_inv, ← coe_inv] at h + · norm_cast at h + all_goals rintro rfl; simp at h + · rintro ⟨hp, h⟩ + rw [← coe_inv (zero_lt_one.trans hp).ne', ← coe_inv, ← coe_add, h, coe_one] + rintro rfl + simp [hp.ne'] at h + +alias ⟨_, _root_.NNReal.IsConjExponent.coe_ennreal⟩ := isConjExponent_coe + +namespace IsConjExponent + +protected lemma conjExponent (hp : 1 ≤ p) : p.IsConjExponent (conjExponent p) := by + have : p ≠ 0 := (zero_lt_one.trans_le hp).ne' + rw [isConjExponent_iff, conjExponent, add_comm] + refine (AddLECancellable.eq_tsub_iff_add_eq_of_le (α := ℝ≥0∞) (by simpa) (by simpa)).1 ?_ + rw [inv_eq_iff_eq_inv] + obtain rfl | hp₁ := hp.eq_or_lt + · simp + obtain rfl | hp := eq_or_ne p ∞ + · simp + calc + 1 + (p - 1)⁻¹ = (p - 1 + 1) / (p - 1) := by + rw [ENNReal.add_div, ENNReal.div_self ((tsub_pos_of_lt hp₁).ne') (sub_ne_top hp), one_div] + _ = (1 - p⁻¹)⁻¹ := by + rw [tsub_add_cancel_of_le, ← inv_eq_iff_eq_inv, div_eq_mul_inv, ENNReal.mul_inv, inv_inv, + ENNReal.mul_sub, ENNReal.inv_mul_cancel, mul_one] <;> simp [*] + +section +include h + +@[symm] +protected lemma symm : q.IsConjExponent p where + inv_add_inv_conj := by simpa [add_comm] using h.inv_add_inv_conj + +lemma one_le : 1 ≤ p := ENNReal.inv_le_one.1 <| by + rw [← add_zero p⁻¹, ← h.inv_add_inv_conj]; gcongr; positivity + +lemma pos : 0 < p := zero_lt_one.trans_le h.one_le +lemma ne_zero : p ≠ 0 := h.pos.ne' + +lemma one_sub_inv : 1 - p⁻¹ = q⁻¹ := + ENNReal.sub_eq_of_eq_add_rev' one_ne_top h.inv_add_inv_conj.symm + +lemma conjExponent_eq : conjExponent p = q := by + have hp : 1 ≤ p := h.one_le + have : p⁻¹ ≠ ∞ := by simpa using h.ne_zero + simpa [ENNReal.add_right_inj, *] using + (IsConjExponent.conjExponent hp).inv_add_inv_conj.trans h.inv_add_inv_conj.symm + +lemma conj_eq : q = 1 + (p - 1)⁻¹ := h.conjExponent_eq.symm + +lemma mul_eq_add : p * q = p + q := by + obtain rfl | hp := eq_or_ne p ∞ + · simp [h.symm.ne_zero] + obtain rfl | hq := eq_or_ne q ∞ + · simp [h.ne_zero] + rw [← mul_one (_ * _), ← h.inv_add_inv_conj, mul_add, mul_right_comm, + ENNReal.mul_inv_cancel h.ne_zero hp, one_mul, mul_assoc, + ENNReal.mul_inv_cancel h.symm.ne_zero hq, mul_one, add_comm] + +lemma div_conj_eq_sub_one : p / q = p - 1 := by + obtain rfl | hq := eq_or_ne q ∞ + · simp [h.symm.conj_eq] + refine ENNReal.eq_sub_of_add_eq one_ne_top ?_ + rw [← ENNReal.div_self h.symm.ne_zero hq, ← ENNReal.add_div, ← h.mul_eq_add, mul_div_assoc, + ENNReal.div_self h.symm.ne_zero hq, mul_one] + +end + +protected lemma inv_inv (hab : a + b = 1) : a⁻¹.IsConjExponent b⁻¹ where + inv_add_inv_conj := by simpa only [inv_inv] using hab + +lemma inv_one_sub_inv (ha : a ≤ 1) : a⁻¹.IsConjExponent (1 - a)⁻¹ := + .inv_inv <| add_tsub_cancel_of_le ha + +lemma one_sub_inv_inv (ha : a ≤ 1) : (1 - a)⁻¹.IsConjExponent a⁻¹ := (inv_one_sub_inv ha).symm + +lemma top_one : IsConjExponent ∞ 1 := ⟨by simp⟩ +lemma one_top : IsConjExponent 1 ∞ := ⟨by simp⟩ + +end IsConjExponent + +lemma isConjExponent_comm : p.IsConjExponent q ↔ q.IsConjExponent p := ⟨.symm, .symm⟩ + +lemma isConjExponent_iff_eq_conjExponent (hp : 1 ≤ p) : p.IsConjExponent q ↔ q = 1 + (p - 1)⁻¹ := + ⟨fun h ↦ h.conj_eq, by rintro rfl; exact .conjExponent hp⟩ + +end ENNReal diff --git a/Mathlib/Data/Real/GoldenRatio.lean b/Mathlib/Data/Real/GoldenRatio.lean index 7165e37237c30..42e9c2559ca88 100644 --- a/Mathlib/Data/Real/GoldenRatio.lean +++ b/Mathlib/Data/Real/GoldenRatio.lean @@ -109,7 +109,7 @@ theorem goldConj_ne_zero : ψ ≠ 0 := theorem neg_one_lt_goldConj : -1 < ψ := by rw [neg_lt, ← inv_gold] - exact inv_lt_one one_lt_gold + exact inv_lt_one_of_one_lt₀ one_lt_gold /-! ## Irrationality diff --git a/Mathlib/Data/Real/Hyperreal.lean b/Mathlib/Data/Real/Hyperreal.lean index 68aee623dbde7..4b5d781f4224b 100644 --- a/Mathlib/Data/Real/Hyperreal.lean +++ b/Mathlib/Data/Real/Hyperreal.lean @@ -403,7 +403,7 @@ theorem InfiniteNeg.not_infinitesimal {x : ℝ*} (h : InfiniteNeg x) : ¬Infinit theorem infinitePos_iff_infinite_and_pos {x : ℝ*} : InfinitePos x ↔ Infinite x ∧ 0 < x := ⟨fun hip => ⟨Or.inl hip, hip 0⟩, fun ⟨hi, hp⟩ => - hi.casesOn (fun hip => hip) fun hin => False.elim (not_lt_of_lt hp (hin 0))⟩ + hi.casesOn id fun hin => False.elim (not_lt_of_lt hp (hin 0))⟩ theorem infiniteNeg_iff_infinite_and_neg {x : ℝ*} : InfiniteNeg x ↔ Infinite x ∧ x < 0 := ⟨fun hip => ⟨Or.inr hip, hip 0⟩, fun ⟨hi, hp⟩ => @@ -599,12 +599,12 @@ theorem infinitePos_iff_infinitesimal_inv_pos {x : ℝ*} : ⟨fun hip => ⟨infinitesimal_def.mpr fun r hr => ⟨lt_trans (coe_lt_coe.2 (neg_neg_of_pos hr)) (inv_pos.2 (hip 0)), - (inv_lt (coe_lt_coe.2 hr) (hip 0)).mp (by convert hip r⁻¹)⟩, + inv_lt_of_inv_lt₀ (coe_lt_coe.2 hr) (by convert hip r⁻¹)⟩, inv_pos.2 <| hip 0⟩, fun ⟨hi, hp⟩ r => @_root_.by_cases (r = 0) (↑r < x) (fun h => Eq.substr h (inv_pos.mp hp)) fun h => lt_of_le_of_lt (coe_le_coe.2 (le_abs_self r)) - ((inv_lt_inv (inv_pos.mp hp) (coe_lt_coe.2 (abs_pos.2 h))).mp + ((inv_lt_inv₀ (inv_pos.mp hp) (coe_lt_coe.2 (abs_pos.2 h))).mp ((infinitesimal_def.mp hi) |r|⁻¹ (inv_pos.2 (abs_pos.2 h))).2)⟩ theorem infiniteNeg_iff_infinitesimal_inv_neg {x : ℝ*} : diff --git a/Mathlib/Data/Real/Irrational.lean b/Mathlib/Data/Real/Irrational.lean index 3a8c9b0473110..666201507c599 100644 --- a/Mathlib/Data/Real/Irrational.lean +++ b/Mathlib/Data/Real/Irrational.lean @@ -79,7 +79,7 @@ theorem irrational_nrt_of_n_not_dvd_multiplicity {x : ℝ} (n : ℕ) {m : ℤ} ( rw [← Int.cast_pow, Int.cast_inj] at hxr subst m have : y ≠ 0 := by rintro rfl; rw [zero_pow hnpos.ne'] at hm; exact hm rfl - erw [multiplicity.pow' (Nat.prime_iff_prime_int.1 hp.1) (finite_int_iff.2 ⟨hp.1.ne_one, this⟩), + rw [multiplicity.pow' (Nat.prime_iff_prime_int.1 hp.1) (finite_int_iff.2 ⟨hp.1.ne_one, this⟩), Nat.mul_mod_right] at hv exact hv rfl diff --git a/Mathlib/Data/Real/Pi/Bounds.lean b/Mathlib/Data/Real/Pi/Bounds.lean index 53573cbcf7b0b..131af1b4136f2 100644 --- a/Mathlib/Data/Real/Pi/Bounds.lean +++ b/Mathlib/Data/Real/Pi/Bounds.lean @@ -23,7 +23,7 @@ namespace Real theorem pi_gt_sqrtTwoAddSeries (n : ℕ) : 2 ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) < π := by have : √(2 - sqrtTwoAddSeries 0 n) / 2 * 2 ^ (n + 2) < π := by - rw [← lt_div_iff, ← sin_pi_over_two_pow_succ] + rw [← lt_div_iff₀, ← sin_pi_over_two_pow_succ] focus apply sin_lt apply div_pos pi_pos @@ -34,13 +34,13 @@ theorem pi_gt_sqrtTwoAddSeries (n : ℕ) : 2 ^ (n + 1) * √(2 - sqrtTwoAddSerie theorem pi_lt_sqrtTwoAddSeries (n : ℕ) : π < 2 ^ (n + 1) * √(2 - sqrtTwoAddSeries 0 n) + 1 / 4 ^ n := by have : π < (√(2 - sqrtTwoAddSeries 0 n) / 2 + 1 / (2 ^ n) ^ 3 / 4) * (2 : ℝ) ^ (n + 2) := by - rw [← div_lt_iff (by norm_num), ← sin_pi_over_two_pow_succ] + rw [← div_lt_iff₀ (by norm_num), ← sin_pi_over_two_pow_succ] refine lt_of_lt_of_le (lt_add_of_sub_right_lt (sin_gt_sub_cube ?_ ?_)) ?_ · apply div_pos pi_pos; apply pow_pos; norm_num · rw [div_le_iff₀'] · refine le_trans pi_le_four ?_ simp only [show (4 : ℝ) = (2 : ℝ) ^ 2 by norm_num, mul_one] - apply pow_le_pow_right (by norm_num) + apply pow_right_mono₀ (by norm_num) apply le_add_of_nonneg_left; apply Nat.zero_le · apply pow_pos; norm_num apply add_le_add_left; rw [div_le_div_right (by norm_num)] diff --git a/Mathlib/Data/Real/Pi/Irrational.lean b/Mathlib/Data/Real/Pi/Irrational.lean new file mode 100644 index 0000000000000..e3884b774698d --- /dev/null +++ b/Mathlib/Data/Real/Pi/Irrational.lean @@ -0,0 +1,306 @@ +/- +Copyright (c) 2022 Bhavik Mehta. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bhavik Mehta +-/ +import Mathlib.Analysis.SpecialFunctions.Integrals +import Mathlib.Data.Real.Irrational +import Mathlib.Topology.Algebra.Order.Floor + +/-! +# `Real.pi` is irrational + +The main result of this file is `irrational_pi`. + +The proof is adapted from https://en.wikipedia.org/wiki/Proof_that_%CF%80_is_irrational#Cartwright's_proof. + +The proof idea is as follows. +* Define a sequence of integrals `I n θ = ∫ x in (-1)..1, (1 - x ^ 2) ^ n * cos (x * θ)`. +* Give a recursion formula for `I (n + 2) θ * θ ^ 2` in terms of `I n θ` and `I (n + 1) θ`. + Note we do not find it helpful to define `J` as in the above proof, and instead work directly + with `I`. +* Define polynomials with integer coefficients `sinPoly n` and `cosPoly n` such that + `I n θ * θ ^ (2 * n + 1) = n ! * (sinPoly n θ * sin θ + cosPoly n θ * cos θ)`. + Note that in the informal proof, these polynomials are not defined explicitly, but we find it + useful to define them by recursion. +* Show that both these polynomials have degree bounded by `n`. +* Show that `0 < I n (π / 2) ≤ 2` for all `n`. +* Now we can finish: if `π / 2` is rational, write it as `a / b` with `a, b > 0`. Then + `b ^ (2 * n + 1) * sinPoly n (a / b)` is a positive integer by the degree bound. But it is equal + to `a ^ (2 * n + 1) / n ! * I n (π / 2) ≤ 2 * a * (2 * n + 1) / n !`, which converges to 0 as + `n → ∞`. + +-/ + +noncomputable section + +open intervalIntegral MeasureTheory.MeasureSpace Set Polynomial Real +open scoped Nat + +/-- The sequence of integrals used for Cartwright's proof of irrationality of `π`. -/ +private def I (n : ℕ) (θ : ℝ) : ℝ := ∫ x in (-1)..1, (1 - x ^ 2) ^ n * cos (x * θ) + +variable {n : ℕ} {θ : ℝ} + +private lemma I_zero : I 0 θ * θ = 2 * sin θ := by + rw [mul_comm, I] + simp [mul_integral_comp_mul_right, two_mul] + +/-- +Auxiliary for the proof that `π` is irrational. +While it is most natural to give the recursive formula for `I (n + 2) θ`, as well as give the second +base case of `I 1 θ`, it is in fact more convenient to give the recursive formula for `I (n + 1) θ` +in terms of `I n θ` and `I (n - 1) θ` (note the natural subtraction!). +Despite the usually inconvenient subtraction, this in fact allows deducing both of the above facts +with significantly fewer analysis computations. +In addition, note the `0 ^ n` on the right hand side - this is intentional, and again allows +combining the proof of the "usual" recursion formula and the base case `I 1 θ`. +-/ +private lemma recursion' (n : ℕ) : + I (n + 1) θ * θ ^ 2 = - (2 * 2 * ((n + 1) * (0 ^ n * cos θ))) + + 2 * (n + 1) * (2 * n + 1) * I n θ - 4 * (n + 1) * n * I (n - 1) θ := by + rw [I] + let f (x : ℝ) : ℝ := 1 - x ^ 2 + let u₁ (x : ℝ) : ℝ := f x ^ (n + 1) + let u₁' (x : ℝ) : ℝ := - (2 * (n + 1) * x * f x ^ n) + let v₁ (x : ℝ) : ℝ := sin (x * θ) + let v₁' (x : ℝ) : ℝ := cos (x * θ) * θ + let u₂ (x : ℝ) : ℝ := x * (f x) ^ n + let u₂' (x : ℝ) : ℝ := (f x) ^ n - 2 * n * x ^ 2 * (f x) ^ (n - 1) + let v₂ (x : ℝ) : ℝ := cos (x * θ) + let v₂' (x : ℝ) : ℝ := -sin (x * θ) * θ + have hfd : Continuous f := by fun_prop + have hu₁d : Continuous u₁' := by fun_prop + have hv₁d : Continuous v₁' := by fun_prop + have hu₂d : Continuous u₂' := by fun_prop + have hv₂d : Continuous v₂' := by fun_prop + have hu₁_eval_one : u₁ 1 = 0 := by simp only [u₁, f]; simp + have hu₁_eval_neg_one : u₁ (-1) = 0 := by simp only [u₁, f]; simp + have t : u₂ 1 * v₂ 1 - u₂ (-1) * v₂ (-1) = 2 * (0 ^ n * cos θ) := by simp [u₂, v₂, f, ← two_mul] + have hf (x) : HasDerivAt f (- 2 * x) x := by + convert (hasDerivAt_pow 2 x).const_sub 1 using 1 + simp + have hu₁ (x) : HasDerivAt u₁ (u₁' x) x := by + convert (hf x).pow _ using 1 + simp only [Nat.add_succ_sub_one, u₁', Nat.cast_add_one] + ring + have hv₁ (x) : HasDerivAt v₁ (v₁' x) x := (hasDerivAt_mul_const θ).sin + have hu₂ (x) : HasDerivAt u₂ (u₂' x) x := by + convert (hasDerivAt_id' x).mul ((hf x).pow _) using 1 + simp only [u₂'] + ring + have hv₂ (x) : HasDerivAt v₂ (v₂' x) x := (hasDerivAt_mul_const θ).cos + convert_to (∫ (x : ℝ) in (-1)..1, u₁ x * v₁' x) * θ = _ using 1 + · simp_rw [u₁, v₁', ← intervalIntegral.integral_mul_const, sq θ, mul_assoc] + rw [integral_mul_deriv_eq_deriv_mul (fun x _ => hu₁ x) (fun x _ => hv₁ x) + (hu₁d.intervalIntegrable _ _) (hv₁d.intervalIntegrable _ _), hu₁_eval_one, hu₁_eval_neg_one, + zero_mul, zero_mul, sub_zero, zero_sub, ← integral_neg, ← integral_mul_const] + convert_to ((-2 : ℝ) * (n + 1)) * ∫ (x : ℝ) in (-1)..1, (u₂ x * v₂' x) = _ using 1 + · rw [← integral_const_mul] + congr 1 with x + dsimp [u₁', v₁, u₂, v₂'] + ring + rw [integral_mul_deriv_eq_deriv_mul (fun x _ => hu₂ x) (fun x _ => hv₂ x) + (hu₂d.intervalIntegrable _ _) (hv₂d.intervalIntegrable _ _), + mul_sub, t, neg_mul, neg_mul, neg_mul, sub_neg_eq_add] + have (x) : u₂' x = (2 * n + 1) * f x ^ n - 2 * n * f x ^ (n - 1) := by + cases n with + | zero => simp [u₂'] + | succ n => ring! + simp_rw [this, sub_mul, mul_assoc _ _ (v₂ _)] + have : Continuous v₂ := by fun_prop + rw [mul_mul_mul_comm, integral_sub, mul_sub, add_sub_assoc] + · congr 1 + simp_rw [integral_const_mul] + ring! + all_goals exact Continuous.intervalIntegrable (by fun_prop) _ _ + +/-- +Auxiliary for the proof that `π` is irrational. +The recursive formula for `I (n + 2) θ * θ ^ 2` in terms of `I n θ` and `I (n + 1) θ`. +-/ +private lemma recursion (n : ℕ) : + I (n + 2) θ * θ ^ 2 = + 2 * (n + 2) * (2 * n + 3) * I (n + 1) θ - 4 * (n + 2) * (n + 1) * I n θ := by + rw [recursion' (n + 1)] + simp + ring! + +/-- +Auxiliary for the proof that `π` is irrational. +The second base case for the induction on `n`, giving an explicit formula for `I 1 θ`. +-/ +private lemma I_one : I 1 θ * θ ^ 3 = 4 * sin θ - 4 * θ * cos θ := by + rw [_root_.pow_succ, ← mul_assoc, recursion' 0, sub_mul, add_mul, mul_assoc _ (I 0 θ), I_zero] + ring + +/-- +Auxiliary for the proof that `π` is irrational. +The first of the two integer-coefficient polynomials that describe the behaviour of the +sequence of integrals `I`. +While not given in the informal proof, these are easy to deduce from the recursion formulae. +-/ +private def sinPoly : ℕ → ℤ[X] + | 0 => C 2 + | 1 => C 4 + | (n+2) => ((2 : ℤ) * (2 * n + 3)) • sinPoly (n + 1) + monomial 2 (-4) * sinPoly n + +/-- +Auxiliary for the proof that `π` is irrational. +The second of the two integer-coefficient polynomials that describe the behaviour of the +sequence of integrals `I`. +While not given in the informal proof, these are easy to deduce from the recursion formulae. +-/ +private def cosPoly : ℕ → ℤ[X] + | 0 => 0 + | 1 => monomial 1 (-4) + | (n+2) => ((2 : ℤ) * (2 * n + 3)) • cosPoly (n + 1) + monomial 2 (-4) * cosPoly n + +/-- +Auxiliary for the proof that `π` is irrational. +Prove a degree bound for `sinPoly n` by induction. Note this is where we find the value in an +explicit description of `sinPoly`. +-/ +private lemma sinPoly_natDegree_le : ∀ n : ℕ, (sinPoly n).natDegree ≤ n + | 0 => by simp [sinPoly] + | 1 => by simp only [natDegree_C, mul_one, zero_le', sinPoly] + | n + 2 => by + rw [sinPoly] + refine natDegree_add_le_of_degree_le ((natDegree_smul_le _ _).trans ?_) ?_ + · exact (sinPoly_natDegree_le (n + 1)).trans (by simp) + refine natDegree_mul_le.trans ?_ + simpa [add_comm 2] using sinPoly_natDegree_le n + +/-- +Auxiliary for the proof that `π` is irrational. +Prove a degree bound for `cosPoly n` by induction. Note this is where we find the value in an +explicit description of `cosPoly`. +-/ +private lemma cosPoly_natDegree_le : ∀ n : ℕ, (cosPoly n).natDegree ≤ n + | 0 => by simp [cosPoly] + | 1 => (natDegree_monomial_le _).trans (by simp) + | n + 2 => by + rw [cosPoly] + refine natDegree_add_le_of_degree_le ((natDegree_smul_le _ _).trans ?_) ?_ + · exact (cosPoly_natDegree_le (n + 1)).trans (by simp) + exact natDegree_mul_le.trans (by simp [add_comm 2, cosPoly_natDegree_le n]) + +/-- +Auxiliary for the proof that `π` is irrational. +The key lemma: the sequence of integrals `I` can be written as a linear combination of `sin` and +`cos`, with coefficients given by the polynomials `sinPoly` and `cosPoly`. +-/ +private lemma sinPoly_add_cosPoly_eval (θ : ℝ) : + ∀ n : ℕ, + I n θ * θ ^ (2 * n + 1) = n ! * ((sinPoly n).eval₂ (Int.castRingHom _) θ * sin θ + + (cosPoly n).eval₂ (Int.castRingHom _) θ * cos θ) + | 0 => by simp [sinPoly, cosPoly, I_zero] + | 1 => by simp [I_one, sinPoly, cosPoly, sub_eq_add_neg] + | n + 2 => by + calc I (n + 2) θ * θ ^ (2 * (n + 2) + 1) = I (n + 2) θ * θ ^ 2 * θ ^ (2 * n + 3) := by ring + _ = 2 * (n + 2) * (2 * n + 3) * (I (n + 1) θ * θ ^ (2 * (n + 1) + 1)) - + 4 * (n + 2) * (n + 1) * θ ^ 2 * (I n θ * θ ^ (2 * n + 1)) := by rw [recursion]; ring + _ = _ := by simp [sinPoly_add_cosPoly_eval, sinPoly, cosPoly, Nat.factorial_succ]; ring + +/-- +Auxiliary for the proof that `π` is irrational. +For a polynomial `p` with natural degree `≤ k` and integer coefficients, evaluating `p` at a +rational `a / b` gives a rational of the form `z / b ^ k`. +TODO: should this be moved elsewhere? It uses none of the pi-specific definitions. +-/ +private lemma is_integer {p : ℤ[X]} (a b : ℤ) {k : ℕ} (hp : p.natDegree ≤ k) : + ∃ z : ℤ, p.eval₂ (Int.castRingHom ℝ) (a / b) * b ^ k = z := by + rcases eq_or_ne b 0 with rfl | hb + · rcases k.eq_zero_or_pos with rfl | hk + · exact ⟨p.coeff 0, by simp⟩ + exact ⟨0, by simp [hk.ne']⟩ + refine ⟨∑ i in p.support, p.coeff i * a ^ i * b ^ (k - i), ?_⟩ + conv => lhs; rw [← sum_monomial_eq p] + rw [eval₂_sum, sum, Finset.sum_mul, Int.cast_sum] + simp only [eval₂_monomial, eq_intCast, div_pow, Int.cast_mul, Int.cast_pow] + refine Finset.sum_congr rfl (fun i hi => ?_) + have ik := (le_natDegree_of_mem_supp i hi).trans hp + rw [mul_assoc, div_mul_comm, ← Int.cast_pow, ← Int.cast_pow, ← Int.cast_pow, + ← pow_sub_mul_pow b ik, ← Int.cast_div_charZero, Int.mul_ediv_cancel _ (pow_ne_zero _ hb), + ← mul_assoc, mul_right_comm, ← Int.cast_pow] + exact dvd_mul_left _ _ + +open Filter + +/-- +Auxiliary for the proof that `π` is irrational. +The integrand in the definition of `I` is nonnegative and takes a positive value at least one point, +so the integral is positive. +-/ +private lemma I_pos : 0 < I n (π / 2) := by + refine integral_pos (by norm_num) (Continuous.continuousOn (by continuity)) ?_ ⟨0, by simp⟩ + refine fun x hx => mul_nonneg (pow_nonneg ?_ _) ?_ + · rw [sub_nonneg, sq_le_one_iff_abs_le_one, abs_le] + exact ⟨hx.1.le, hx.2⟩ + refine cos_nonneg_of_neg_pi_div_two_le_of_le ?_ ?_ <;> + nlinarith [hx.1, hx.2, pi_pos] + +/-- +Auxiliary for the proof that `π` is irrational. +The integrand in the definition of `I` is bounded by 1 and the interval has length 2, so the +integral is bounded above by `2`. +-/ +private lemma I_le (n : ℕ) : I n (π / 2) ≤ 2 := by + rw [← norm_of_nonneg I_pos.le] + refine (norm_integral_le_of_norm_le_const ?_).trans (show (1 : ℝ) * _ ≤ _ by norm_num) + intros x hx + simp only [uIoc_of_le, neg_le_self_iff, zero_le_one, mem_Ioc] at hx + rw [norm_eq_abs, abs_mul, abs_pow] + refine mul_le_one₀ (pow_le_one₀ (abs_nonneg _) ?_) (abs_nonneg _) (abs_cos_le_one _) + rw [abs_le] + constructor <;> nlinarith + +/-- +Auxiliary for the proof that `π` is irrational. +For any real `a`, we have that `a ^ (2n+1) / n!` tends to `0` as `n → ∞`. This is just a +reformulation of tendsto_pow_div_factorial_atTop, which asserts the same for `a ^ n / n!` +-/ +private lemma tendsto_pow_div_factorial_at_top_aux (a : ℝ) : + Tendsto (fun n => (a : ℝ) ^ (2 * n + 1) / n !) atTop (nhds 0) := by + rw [← mul_zero a] + refine ((FloorSemiring.tendsto_pow_div_factorial_atTop (a ^ 2)).const_mul a).congr (fun x => ?_) + rw [← pow_mul, mul_div_assoc', _root_.pow_succ'] + +/-- If `x` is rational, it can be written as `a / b` with `a : ℤ` and `b : ℕ` satisfying `b > 0`. -/ +private lemma not_irrational_exists_rep {x : ℝ} : + ¬Irrational x → ∃ (a : ℤ) (b : ℕ), 0 < b ∧ x = a / b := by + rw [Irrational, not_not, mem_range] + rintro ⟨q, rfl⟩ + exact ⟨q.num, q.den, q.pos, by exact_mod_cast (Rat.num_div_den _).symm⟩ + +@[simp] theorem irrational_pi : Irrational π := by + apply Irrational.of_div_nat 2 + rw [Nat.cast_two] + by_contra h' + obtain ⟨a, b, hb, h⟩ := not_irrational_exists_rep h' + have ha : (0 : ℝ) < a := by + have : 0 < (a : ℝ) / b := h ▸ pi_div_two_pos + rwa [lt_div_iff₀ (by positivity), zero_mul] at this + have k (n : ℕ) : 0 < (a : ℝ) ^ (2 * n + 1) / n ! := by positivity + have j : ∀ᶠ n : ℕ in atTop, (a : ℝ) ^ (2 * n + 1) / n ! * I n (π / 2) < 1 := by + have := eventually_lt_of_tendsto_lt (show (0 : ℝ) < 1 / 2 by norm_num) + (tendsto_pow_div_factorial_at_top_aux a) + filter_upwards [this] with n hn + rw [lt_div_iff₀ (zero_lt_two : (0 : ℝ) < 2)] at hn + exact hn.trans_le' (mul_le_mul_of_nonneg_left (I_le _) (by positivity)) + obtain ⟨n, hn⟩ := j.exists + have hn' : 0 < a ^ (2 * n + 1) / n ! * I n (π / 2) := mul_pos (k _) I_pos + obtain ⟨z, hz⟩ : ∃ z : ℤ, (sinPoly n).eval₂ (Int.castRingHom ℝ) (a / b) * b ^ (2 * n + 1) = z := + is_integer a b ((sinPoly_natDegree_le _).trans (by linarith)) + have e := sinPoly_add_cosPoly_eval (π / 2) n + rw [cos_pi_div_two, sin_pi_div_two, mul_zero, mul_one, add_zero] at e + have : a ^ (2 * n + 1) / n ! * I n (π / 2) = + eval₂ (Int.castRingHom ℝ) (π / 2) (sinPoly n) * b ^ (2 * n + 1) := by + nth_rw 2 [h] at e + field_simp at e ⊢ + linear_combination e + have : (0 : ℝ) < z ∧ (z : ℝ) < 1 := by simp [← hz, ← h, ← this, hn', hn] + norm_cast at this + omega + +end diff --git a/Mathlib/Data/Seq/Computation.lean b/Mathlib/Data/Seq/Computation.lean index 2f8667ca00005..9ff96e3dd47ef 100644 --- a/Mathlib/Data/Seq/Computation.lean +++ b/Mathlib/Data/Seq/Computation.lean @@ -503,8 +503,8 @@ theorem length_thinkN (s : Computation α) [_h : Terminates s] (n) : theorem eq_thinkN {s : Computation α} {a n} (h : Results s a n) : s = thinkN (pure a) n := by revert s - induction n with | zero => _ | succ n IH => _ - all_goals intro s; apply recOn s (fun a' => _) fun s => _ <;> intro a h + induction n with | zero => _ | succ n IH => _ <;> + (intro s; apply recOn s (fun a' => _) fun s => _) <;> intro a h · rw [← eq_of_pure_mem h.mem] rfl · cases' of_results_think h with n h @@ -695,7 +695,7 @@ theorem length_bind (s : Computation α) (f : α → Computation β) [_T1 : Term theorem of_results_bind {s : Computation α} {f : α → Computation β} {b k} : Results (bind s f) b k → ∃ a m n, Results s a m ∧ Results (f a) b n ∧ k = n + m := by induction k generalizing s with | zero => _ | succ n IH => _ - all_goals apply recOn s (fun a => _) fun s' => _ <;> intro e h + <;> apply recOn s (fun a => _) fun s' => _ <;> intro e h · simp only [ret_bind] at h exact ⟨e, _, _, results_pure _, h, rfl⟩ · have := congr_arg head (eq_thinkN h) diff --git a/Mathlib/Data/Seq/Seq.lean b/Mathlib/Data/Seq/Seq.lean index e1c08ea1f9bdc..d8dfa6e7ed037 100644 --- a/Mathlib/Data/Seq/Seq.lean +++ b/Mathlib/Data/Seq/Seq.lean @@ -512,8 +512,6 @@ def zipWith (f : α → β → γ) (s₁ : Seq α) (s₂ : Seq β) : Seq γ := ⟨fun n => Option.map₂ f (s₁.get? n) (s₂.get? n), fun {_} hn => Option.map₂_eq_none_iff.2 <| (Option.map₂_eq_none_iff.1 hn).imp s₁.2 s₂.2⟩ -variable {s : Seq α} {s' : Seq β} {n : ℕ} - @[simp] theorem get?_zipWith (f : α → β → γ) (s s' n) : (zipWith f s s').get? n = Option.map₂ f (s.get? n) (s'.get? n) := diff --git a/Mathlib/Data/Seq/WSeq.lean b/Mathlib/Data/Seq/WSeq.lean index 8a167a30145c9..4817d9024ec51 100644 --- a/Mathlib/Data/Seq/WSeq.lean +++ b/Mathlib/Data/Seq/WSeq.lean @@ -717,12 +717,9 @@ theorem head_terminates_of_head_tail_terminates (s : WSeq α) [T : Terminates (h Terminates (head s) := (head_terminates_iff _).2 <| by rcases (head_terminates_iff _).1 T with ⟨⟨a, h⟩⟩ - simp? [tail] at h says simp only [tail, destruct_flatten] at h + simp? [tail] at h says simp only [tail, destruct_flatten, bind_map_left] at h rcases exists_of_mem_bind h with ⟨s', h1, _⟩ - unfold Functor.map at h1 - exact - let ⟨t, h3, _⟩ := Computation.exists_of_mem_map h1 - Computation.terminates_of_mem h3 + exact terminates_of_mem h1 theorem destruct_some_of_destruct_tail_some {s : WSeq α} {a} (h : some a ∈ destruct (tail s)) : ∃ a', some a' ∈ destruct s := by diff --git a/Mathlib/Data/Set/Accumulate.lean b/Mathlib/Data/Set/Accumulate.lean index fcbe0ea222997..ffa9845a9ad40 100644 --- a/Mathlib/Data/Set/Accumulate.lean +++ b/Mathlib/Data/Set/Accumulate.lean @@ -12,7 +12,7 @@ The function `Accumulate` takes a set `s` and returns `⋃ y ≤ x, s y`. -/ -variable {α β γ : Type*} {s : α → Set β} {t : α → Set γ} +variable {α β : Type*} {s : α → Set β} namespace Set diff --git a/Mathlib/Data/Set/Basic.lean b/Mathlib/Data/Set/Basic.lean index 5a4257688c30d..691836860b538 100644 --- a/Mathlib/Data/Set/Basic.lean +++ b/Mathlib/Data/Set/Basic.lean @@ -1958,7 +1958,7 @@ open Set namespace Function -variable {ι : Sort*} {α : Type*} {β : Type*} {f : α → β} +variable {α : Type*} {β : Type*} theorem Injective.nonempty_apply_iff {f : Set α → Set β} (hf : Injective f) (h2 : f ∅ = ∅) {s : Set α} : (f s).Nonempty ↔ s.Nonempty := by @@ -2141,7 +2141,7 @@ end Monotone /-! ### Disjoint sets -/ -variable {α β : Type*} {s t u : Set α} {f : α → β} +variable {α : Type*} {s t u : Set α} namespace Disjoint diff --git a/Mathlib/Data/Set/Card.lean b/Mathlib/Data/Set/Card.lean index 21257aebdf8f0..57aba3430a761 100644 --- a/Mathlib/Data/Set/Card.lean +++ b/Mathlib/Data/Set/Card.lean @@ -1050,7 +1050,4 @@ theorem ncard_eq_three : s.ncard = 3 ↔ ∃ x y z, x ≠ y ∧ x ≠ z ∧ y simp [h] end ncard - -@[deprecated (since := "2023-12-27")] alias ncard_le_of_subset := ncard_le_ncard - end Set diff --git a/Mathlib/Data/Set/Finite.lean b/Mathlib/Data/Set/Finite.lean index 3807e40b76e3c..cf7a2bfbb02d2 100644 --- a/Mathlib/Data/Set/Finite.lean +++ b/Mathlib/Data/Set/Finite.lean @@ -3,8 +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, Kyle Miller -/ -import Mathlib.Data.Finset.Basic import Mathlib.Data.Finite.Basic +import Mathlib.Data.Finset.Max import Mathlib.Data.Set.Functor import Mathlib.Data.Set.Lattice @@ -897,7 +897,7 @@ theorem exists_subset_image_finite_and {f : α → β} {s : Set α} {p : Set β (∃ t ⊆ f '' s, t.Finite ∧ p t) ↔ ∃ t ⊆ s, t.Finite ∧ p (f '' t) := by classical simp_rw [@and_comm (_ ⊆ _), and_assoc, exists_finite_iff_finset, @and_comm (p _), - Finset.subset_image_iff] + Finset.subset_set_image_iff] aesop section Pi @@ -1528,6 +1528,7 @@ protected theorem bddBelow [SemilatticeInf α] [Nonempty α] (s : Finset α) : B end Finset +section LinearOrder variable [LinearOrder α] {s : Set α} /-- If a linear order does not contain any triple of elements `x < y < z`, then this type @@ -1568,4 +1569,19 @@ theorem DirectedOn.exists_mem_subset_of_finset_subset_biUnion {α ι : Type*} {f haveI := hn.coe_sort simpa using (directed_comp.2 hc.directed_val).exists_mem_subset_of_finset_subset_biUnion hs +end LinearOrder + +namespace List +variable (α) [Finite α] (n : ℕ) + +lemma finite_length_eq : {l : List α | l.length = n}.Finite := Vector.finite + +lemma finite_length_lt : {l : List α | l.length < n}.Finite := by + convert (Finset.range n).finite_toSet.biUnion fun i _ ↦ finite_length_eq α i; ext; simp + +lemma finite_length_le : {l : List α | l.length ≤ n}.Finite := by + simpa [Nat.lt_succ_iff] using finite_length_lt α (n + 1) + +end List + set_option linter.style.longFile 1700 diff --git a/Mathlib/Data/Set/Function.lean b/Mathlib/Data/Set/Function.lean index e421706c65305..0ae9780c502d9 100644 --- a/Mathlib/Data/Set/Function.lean +++ b/Mathlib/Data/Set/Function.lean @@ -166,8 +166,7 @@ end restrict /-! ### Equality on a set -/ section equality -variable {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {p : Set γ} {f f₁ f₂ f₃ : α → β} {g g₁ g₂ : β → γ} - {f' f₁' f₂' : β → α} {g' : γ → β} {a : α} {b : β} +variable {s s₁ s₂ : Set α} {f₁ f₂ f₃ : α → β} {g : β → γ} {a : α} @[simp] theorem eqOn_empty (f₁ f₂ : α → β) : EqOn f₁ f₂ ∅ := fun _ => False.elim @@ -233,78 +232,7 @@ alias ⟨EqOn.comp_eq, _⟩ := eqOn_range end equality -/-! ### Congruence lemmas for monotonicity and antitonicity -/ -section Order - -variable {s : Set α} {f₁ f₂ : α → β} [Preorder α] [Preorder β] - -theorem _root_.MonotoneOn.congr (h₁ : MonotoneOn f₁ s) (h : s.EqOn f₁ f₂) : MonotoneOn f₂ s := by - intro a ha b hb hab - rw [← h ha, ← h hb] - exact h₁ ha hb hab - -theorem _root_.AntitoneOn.congr (h₁ : AntitoneOn f₁ s) (h : s.EqOn f₁ f₂) : AntitoneOn f₂ s := - h₁.dual_right.congr h - -theorem _root_.StrictMonoOn.congr (h₁ : StrictMonoOn f₁ s) (h : s.EqOn f₁ f₂) : - StrictMonoOn f₂ s := by - intro a ha b hb hab - rw [← h ha, ← h hb] - exact h₁ ha hb hab - -theorem _root_.StrictAntiOn.congr (h₁ : StrictAntiOn f₁ s) (h : s.EqOn f₁ f₂) : StrictAntiOn f₂ s := - h₁.dual_right.congr h - -theorem EqOn.congr_monotoneOn (h : s.EqOn f₁ f₂) : MonotoneOn f₁ s ↔ MonotoneOn f₂ s := - ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ - -theorem EqOn.congr_antitoneOn (h : s.EqOn f₁ f₂) : AntitoneOn f₁ s ↔ AntitoneOn f₂ s := - ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ - -theorem EqOn.congr_strictMonoOn (h : s.EqOn f₁ f₂) : StrictMonoOn f₁ s ↔ StrictMonoOn f₂ s := - ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ - -theorem EqOn.congr_strictAntiOn (h : s.EqOn f₁ f₂) : StrictAntiOn f₁ s ↔ StrictAntiOn f₂ s := - ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ - -end Order - -/-! ### Monotonicity lemmas -/ -section Mono - -variable {s s₁ s₂ : Set α} {f f₁ f₂ : α → β} [Preorder α] [Preorder β] - -theorem _root_.MonotoneOn.mono (h : MonotoneOn f s) (h' : s₂ ⊆ s) : MonotoneOn f s₂ := - fun _ hx _ hy => h (h' hx) (h' hy) - -theorem _root_.AntitoneOn.mono (h : AntitoneOn f s) (h' : s₂ ⊆ s) : AntitoneOn f s₂ := - fun _ hx _ hy => h (h' hx) (h' hy) - -theorem _root_.StrictMonoOn.mono (h : StrictMonoOn f s) (h' : s₂ ⊆ s) : StrictMonoOn f s₂ := - fun _ hx _ hy => h (h' hx) (h' hy) - -theorem _root_.StrictAntiOn.mono (h : StrictAntiOn f s) (h' : s₂ ⊆ s) : StrictAntiOn f s₂ := - fun _ hx _ hy => h (h' hx) (h' hy) - -protected theorem _root_.MonotoneOn.monotone (h : MonotoneOn f s) : - Monotone (f ∘ Subtype.val : s → β) := - fun x y hle => h x.coe_prop y.coe_prop hle - -protected theorem _root_.AntitoneOn.monotone (h : AntitoneOn f s) : - Antitone (f ∘ Subtype.val : s → β) := - fun x y hle => h x.coe_prop y.coe_prop hle - -protected theorem _root_.StrictMonoOn.strictMono (h : StrictMonoOn f s) : - StrictMono (f ∘ Subtype.val : s → β) := - fun x y hlt => h x.coe_prop y.coe_prop hlt - -protected theorem _root_.StrictAntiOn.strictAnti (h : StrictAntiOn f s) : - StrictAnti (f ∘ Subtype.val : s → β) := - fun x y hlt => h x.coe_prop y.coe_prop hlt - -end Mono - -variable {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {p : Set γ} {f f₁ f₂ f₃ : α → β} {g g₁ g₂ : β → γ} +variable {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {p : Set γ} {f f₁ f₂ : α → β} {g g₁ g₂ : β → γ} {f' f₁' f₂' : β → α} {g' : γ → β} {a : α} {b : β} section MapsTo @@ -344,7 +272,7 @@ theorem MapsTo.range_restrict (f : α → β) (s : Set α) (t : Set β) (h : Map theorem mapsTo_iff_exists_map_subtype : MapsTo f s t ↔ ∃ g : s → t, ∀ x : s, f x = g x := ⟨fun h => ⟨h.restrict f s t, fun _ => rfl⟩, fun ⟨g, hg⟩ x hx => by - erw [hg ⟨x, hx⟩] + rw [hg ⟨x, hx⟩] apply Subtype.coe_prop⟩ theorem mapsTo' : MapsTo f s t ↔ f '' s ⊆ t := @@ -456,11 +384,6 @@ theorem mapsTo_image_iff {f : α → β} {g : γ → α} {s : Set γ} {t : Set MapsTo f (g '' s) t ↔ MapsTo (f ∘ g) s t := ⟨fun h c hc => h ⟨c, hc, rfl⟩, fun h _ ⟨_, hc⟩ => hc.2 ▸ h hc.1⟩ -@[deprecated (since := "2023-12-25")] -lemma maps_image_to (f : α → β) (g : γ → α) (s : Set γ) (t : Set β) : - MapsTo f (g '' s) t ↔ MapsTo (f ∘ g) s t := - mapsTo_image_iff - lemma MapsTo.comp_left (g : β → γ) (hf : MapsTo f s t) : MapsTo (g ∘ f) s (g '' t) := fun x hx ↦ ⟨f x, hf hx, rfl⟩ @@ -471,10 +394,6 @@ lemma MapsTo.comp_right {s : Set β} {t : Set γ} (hg : MapsTo g s t) (f : α lemma mapsTo_univ_iff : MapsTo f univ t ↔ ∀ x, f x ∈ t := ⟨fun h _ => h (mem_univ _), fun h x _ => h x⟩ -@[deprecated (since := "2023-12-25")] -theorem maps_univ_to (f : α → β) (s : Set β) : MapsTo f univ s ↔ ∀ a, f a ∈ s := - mapsTo_univ_iff - @[simp] lemma mapsTo_range_iff {g : ι → α} : MapsTo f (range g) t ↔ ∀ i, f (g i) ∈ t := forall_mem_range @@ -521,8 +440,6 @@ theorem preimage_restrictPreimage {u : Set t} : rw [← preimage_preimage (g := f) (f := Subtype.val), ← image_val_preimage_restrictPreimage, preimage_image_eq _ Subtype.val_injective] -variable {U : ι → Set β} - lemma restrictPreimage_injective (hf : Injective f) : Injective (t.restrictPreimage f) := fun _ _ e => Subtype.coe_injective <| hf <| Subtype.mk.inj e @@ -708,8 +625,15 @@ theorem InjOn.imageFactorization_injective (h : InjOn f s) : end injOn section graphOn +variable {x : α × β} + +@[simp] lemma mem_graphOn : x ∈ s.graphOn f ↔ x.1 ∈ s ∧ f x.1 = x.2 := by aesop (add simp graphOn) @[simp] lemma graphOn_empty (f : α → β) : graphOn f ∅ = ∅ := image_empty _ +@[simp] lemma graphOn_eq_empty : graphOn f s = ∅ ↔ s = ∅ := image_eq_empty +@[simp] lemma graphOn_nonempty : (s.graphOn f).Nonempty ↔ s.Nonempty := image_nonempty + +protected alias ⟨_, Nonempty.graphOn⟩ := graphOn_nonempty @[simp] lemma graphOn_union (f : α → β) (s t : Set α) : graphOn f (s ∪ t) = graphOn f s ∪ graphOn f t := @@ -728,6 +652,24 @@ lemma graphOn_insert (f : α → β) (x : α) (s : Set α) : lemma image_fst_graphOn (f : α → β) (s : Set α) : Prod.fst '' graphOn f s = s := by simp [graphOn, image_image] +@[simp] lemma image_snd_graphOn (f : α → β) : Prod.snd '' s.graphOn f = f '' s := by ext x; simp + +lemma fst_injOn_graph : (s.graphOn f).InjOn Prod.fst := by aesop (add simp InjOn) + +lemma graphOn_comp (s : Set α) (f : α → β) (g : β → γ) : + s.graphOn (g ∘ f) = (fun x ↦ (x.1, g x.2)) '' s.graphOn f := by + simpa using image_comp (fun x ↦ (x.1, g x.2)) (fun x ↦ (x, f x)) _ + +lemma graphOn_univ_eq_range : univ.graphOn f = range fun x ↦ (x, f x) := image_univ + +@[simp] lemma graphOn_inj {g : α → β} : s.graphOn f = s.graphOn g ↔ s.EqOn f g := by + simp [Set.ext_iff, funext_iff, forall_swap, EqOn] + +lemma graphOn_univ_inj {g : α → β} : univ.graphOn f = univ.graphOn g ↔ f = g := by simp + +lemma graphOn_univ_injective : Injective (univ.graphOn : (α → β) → Set (α × β)) := + fun _f _g ↦ graphOn_univ_inj.1 + lemma exists_eq_graphOn_image_fst [Nonempty β] {s : Set (α × β)} : (∃ f : α → β, s = graphOn f (Prod.fst '' s)) ↔ InjOn Prod.fst s := by refine ⟨?_, fun h ↦ ?_⟩ @@ -1331,23 +1273,6 @@ lemma bijOn_comm {g : β → α} (h : InvOn f g t s) : BijOn f s t ↔ BijOn g t end Set -/-! ### Monotone -/ -namespace Monotone - -variable [Preorder α] [Preorder β] {f : α → β} - -protected theorem restrict (h : Monotone f) (s : Set α) : Monotone (s.restrict f) := fun _ _ hxy => - h hxy - -protected theorem codRestrict (h : Monotone f) {s : Set β} (hs : ∀ x, f x ∈ s) : - Monotone (s.codRestrict f hs) := - h - -protected theorem rangeFactorization (h : Monotone f) : Monotone (Set.rangeFactorization f) := - h - -end Monotone - /-! ### Piecewise defined function -/ namespace Set @@ -1370,10 +1295,6 @@ theorem piecewise_insert_self {j : α} [∀ i, Decidable (i ∈ insert j s)] : variable [∀ j, Decidable (j ∈ s)] --- TODO: move! -instance Compl.decidableMem (j : α) : Decidable (j ∈ sᶜ) := - instDecidableNot - theorem piecewise_insert [DecidableEq α] (j : α) [∀ i, Decidable (i ∈ insert j s)] : (insert j s).piecewise f g = Function.update (s.piecewise f g) j (f j) := by simp (config := { unfoldPartialApp := true }) only [piecewise, mem_insert_iff] @@ -1414,11 +1335,14 @@ theorem le_piecewise {δ : α → Type*} [∀ i, Preorder (δ i)] {s : Set α} [ g ≤ s.piecewise f₁ f₂ := @piecewise_le α (fun i => (δ i)ᵒᵈ) _ s _ _ _ _ h₁ h₂ -theorem piecewise_le_piecewise {δ : α → Type*} [∀ i, Preorder (δ i)] {s : Set α} +@[gcongr] +theorem piecewise_mono {δ : α → Type*} [∀ i, Preorder (δ i)] {s : Set α} [∀ j, Decidable (j ∈ s)] {f₁ f₂ g₁ g₂ : ∀ i, δ i} (h₁ : ∀ i ∈ s, f₁ i ≤ g₁ i) (h₂ : ∀ i ∉ s, f₂ i ≤ g₂ i) : s.piecewise f₁ f₂ ≤ s.piecewise g₁ g₂ := by apply piecewise_le <;> intros <;> simp [*] +@[deprecated (since := "2024-10-06")] alias piecewise_le_piecewise := piecewise_mono + @[simp] theorem piecewise_insert_of_ne {i j : α} (h : i ≠ j) [∀ i, Decidable (i ∈ insert j s)] : (insert j s).piecewise f g i = s.piecewise f g i := by simp [piecewise, h] @@ -1513,46 +1437,6 @@ theorem univ_pi_piecewise_univ {ι : Type*} {α : ι → Type*} (s : Set ι) (t end Set -section strictMono - -theorem StrictMonoOn.injOn [LinearOrder α] [Preorder β] {f : α → β} {s : Set α} - (H : StrictMonoOn f s) : s.InjOn f := fun x hx y hy hxy => - show Ordering.eq.Compares x y from (H.compares hx hy).1 hxy - -theorem StrictAntiOn.injOn [LinearOrder α] [Preorder β] {f : α → β} {s : Set α} - (H : StrictAntiOn f s) : s.InjOn f := - @StrictMonoOn.injOn α βᵒᵈ _ _ f s H - -theorem StrictMonoOn.comp [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} {f : α → β} {s : Set α} - {t : Set β} (hg : StrictMonoOn g t) (hf : StrictMonoOn f s) (hs : Set.MapsTo f s t) : - StrictMonoOn (g ∘ f) s := fun _x hx _y hy hxy => hg (hs hx) (hs hy) <| hf hx hy hxy - -theorem StrictMonoOn.comp_strictAntiOn [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} - {f : α → β} {s : Set α} {t : Set β} (hg : StrictMonoOn g t) (hf : StrictAntiOn f s) - (hs : Set.MapsTo f s t) : StrictAntiOn (g ∘ f) s := fun _x hx _y hy hxy => - hg (hs hy) (hs hx) <| hf hx hy hxy - -theorem StrictAntiOn.comp [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} {f : α → β} {s : Set α} - {t : Set β} (hg : StrictAntiOn g t) (hf : StrictAntiOn f s) (hs : Set.MapsTo f s t) : - StrictMonoOn (g ∘ f) s := fun _x hx _y hy hxy => hg (hs hy) (hs hx) <| hf hx hy hxy - -theorem StrictAntiOn.comp_strictMonoOn [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} - {f : α → β} {s : Set α} {t : Set β} (hg : StrictAntiOn g t) (hf : StrictMonoOn f s) - (hs : Set.MapsTo f s t) : StrictAntiOn (g ∘ f) s := fun _x hx _y hy hxy => - hg (hs hx) (hs hy) <| hf hx hy hxy - -@[simp] -theorem strictMono_restrict [Preorder α] [Preorder β] {f : α → β} {s : Set α} : - StrictMono (s.restrict f) ↔ StrictMonoOn f s := by simp [Set.restrict, StrictMono, StrictMonoOn] - -alias ⟨_root_.StrictMono.of_restrict, _root_.StrictMonoOn.restrict⟩ := strictMono_restrict - -theorem StrictMono.codRestrict [Preorder α] [Preorder β] {f : α → β} (hf : StrictMono f) - {s : Set β} (hs : ∀ x, f x ∈ s) : StrictMono (Set.codRestrict f s hs) := - hf - -end strictMono - namespace Function open Set @@ -1640,22 +1524,6 @@ theorem update_comp_eq_of_not_mem_range {α : Sort*} {β : Type*} {γ : Sort*} [ theorem insert_injOn (s : Set α) : sᶜ.InjOn fun a => insert a s := fun _a ha _ _ => (insert_inj ha).1 -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 - rcases le_total (ψ x) (ψ y) with (ψxy|ψyx) - · exact ψxy - · have := hφ (ψts ys) (ψts xs) ψyx - rw [φψs.eq ys, φψs.eq xs] at this - induction le_antisymm l this - exact le_refl _ - -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 - lemma apply_eq_of_range_eq_singleton {f : α → β} {b : β} (h : range f = {b}) (a : α) : f a = b := by simpa only [h, mem_singleton_iff] using mem_range_self (f := f) a @@ -1765,4 +1633,4 @@ lemma bijOn_swap (ha : a ∈ s) (hb : b ∈ s) : BijOn (swap a b) s s := end Equiv -set_option linter.style.longFile 1900 +set_option linter.style.longFile 1800 diff --git a/Mathlib/Data/Set/Image.lean b/Mathlib/Data/Set/Image.lean index a7b8fb2b64c6d..83a5f73df751d 100644 --- a/Mathlib/Data/Set/Image.lean +++ b/Mathlib/Data/Set/Image.lean @@ -817,9 +817,8 @@ theorem range_quot_lift {r : ι → ι → Prop} (hf : ∀ x y, r x y → f x = range (Quot.lift f hf) = range f := ext fun _ => (surjective_quot_mk _).exists --- Porting note: the `Setoid α` instance is not being filled in @[simp] -theorem range_quotient_mk [sa : Setoid α] : (range (α := Quotient sa) fun x : α => ⟦x⟧) = univ := +theorem range_quotient_mk {s : Setoid α} : range (Quotient.mk s) = univ := range_quot_mk _ @[simp] @@ -1090,6 +1089,9 @@ theorem Injective.image_injective (hf : Injective f) : Injective (image f) := by intro s t h rw [← preimage_image_eq s hf, ← preimage_image_eq t hf, h] +lemma Injective.image_strictMono (inj : Function.Injective f) : StrictMono (image f) := + monotone_image.strictMono_of_injective inj.image_injective + theorem Surjective.preimage_subset_preimage_iff {s t : Set β} (hf : Surjective f) : f ⁻¹' s ⊆ f ⁻¹' t ↔ s ⊆ t := by apply Set.preimage_subset_preimage_iff @@ -1100,13 +1102,17 @@ theorem Surjective.range_comp {ι' : Sort*} {f : ι → ι'} (hf : Surjective f) range (g ∘ f) = range g := ext fun y => (@Surjective.exists _ _ _ hf fun x => g x = y).symm -theorem Injective.mem_range_iff_exists_unique (hf : Injective f) {b : β} : +theorem Injective.mem_range_iff_existsUnique (hf : Injective f) {b : β} : b ∈ range f ↔ ∃! a, f a = b := ⟨fun ⟨a, h⟩ => ⟨a, h, fun _ ha => hf (ha.trans h.symm)⟩, ExistsUnique.exists⟩ -theorem Injective.exists_unique_of_mem_range (hf : Injective f) {b : β} (hb : b ∈ range f) : - ∃! a, f a = b := - hf.mem_range_iff_exists_unique.mp hb +alias ⟨Injective.existsUnique_of_mem_range, _⟩ := Injective.mem_range_iff_existsUnique + +@[deprecated (since := "2024-09-25")] +alias Injective.mem_range_iff_exists_unique := Injective.mem_range_iff_existsUnique + +@[deprecated (since := "2024-09-25")] +alias Injective.exists_unique_of_mem_range := Injective.existsUnique_of_mem_range theorem Injective.compl_image_eq (hf : Injective f) (s : Set α) : (f '' s)ᶜ = f '' sᶜ ∪ (range f)ᶜ := by diff --git a/Mathlib/Data/Set/Lattice.lean b/Mathlib/Data/Set/Lattice.lean index fbff041791382..b6f29fa406fdf 100644 --- a/Mathlib/Data/Set/Lattice.lean +++ b/Mathlib/Data/Set/Lattice.lean @@ -1243,6 +1243,14 @@ theorem image_sInter_subset (S : Set (Set α)) (f : α → β) : f '' ⋂₀ S rw [sInter_eq_biInter] apply image_iInter₂_subset +theorem image2_sInter_right_subset (t : Set α) (S : Set (Set β)) (f : α → β → γ) : + image2 f t (⋂₀ S) ⊆ ⋂ s ∈ S, image2 f t s := by + aesop + +theorem image2_sInter_left_subset (S : Set (Set α)) (t : Set β) (f : α → β → γ) : + image2 f (⋂₀ S) t ⊆ ⋂ s ∈ S, image2 f s t := by + aesop + /-! ### `restrictPreimage` -/ @@ -1575,6 +1583,14 @@ theorem image2_iUnion_right (s : Set α) (t : ι → Set β) : image2 f s (⋃ i, t i) = ⋃ i, image2 f s (t i) := by simp only [← image_prod, prod_iUnion, image_iUnion] +theorem image2_sUnion_left (S : Set (Set α)) (t : Set β) : + image2 f (⋃₀ S) t = ⋃ s ∈ S, image2 f s t := by + aesop + +theorem image2_sUnion_right (s : Set α) (T : Set (Set β)) : + image2 f s (⋃₀ T) = ⋃ t ∈ T, image2 f s t := by + aesop + /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ /- ./././Mathport/Syntax/Translate/Expr.lean:107:6: warning: expanding binder group (i j) -/ theorem image2_iUnion₂_left (s : ∀ i, κ i → Set α) (t : Set β) : @@ -1610,6 +1626,16 @@ theorem image2_iInter₂_subset_right (s : Set α) (t : ∀ i, κ i → Set β) simp_rw [image2_subset_iff, mem_iInter] exact fun x hx y hy i j => mem_image2_of_mem hx (hy _ _) +theorem image2_sInter_subset_left (S : Set (Set α)) (t : Set β) : + image2 f (⋂₀ S) t ⊆ ⋂ s ∈ S, image2 f s t := by + rw [sInter_eq_biInter] + exact image2_iInter₂_subset_left .. + +theorem image2_sInter_subset_right (s : Set α) (T : Set (Set β)) : + image2 f s (⋂₀ T) ⊆ ⋂ t ∈ T, image2 f s t := by + rw [sInter_eq_biInter] + exact image2_iInter₂_subset_right .. + theorem prod_eq_biUnion_left : s ×ˢ t = ⋃ a ∈ s, (fun b => (a, b)) '' t := by rw [iUnion_image_left, image2_mk_eq_prod] diff --git a/Mathlib/Data/Set/MemPartition.lean b/Mathlib/Data/Set/MemPartition.lean index 25b578031b0f6..5a13d62ad7baf 100644 --- a/Mathlib/Data/Set/MemPartition.lean +++ b/Mathlib/Data/Set/MemPartition.lean @@ -118,7 +118,6 @@ lemma memPartitionSet_succ (f : ℕ → Set α) (n : ℕ) (a : α) [Decidable (a memPartitionSet f (n + 1) a = if a ∈ f n then memPartitionSet f n a ∩ f n else memPartitionSet f n a \ f n := by simp [memPartitionSet] - congr lemma memPartitionSet_mem (f : ℕ → Set α) (n : ℕ) (a : α) : memPartitionSet f n a ∈ memPartition f n := by diff --git a/Mathlib/Data/Set/Monotone.lean b/Mathlib/Data/Set/Monotone.lean new file mode 100644 index 0000000000000..5bd60bb9fb1c5 --- /dev/null +++ b/Mathlib/Data/Set/Monotone.lean @@ -0,0 +1,193 @@ +/- +Copyright (c) 2014 Jeremy Avigad. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jeremy Avigad, Andrew Zipperer, Haitao Zhang, Minchao Wu, Yury Kudryashov +-/ +import Mathlib.Data.Set.Function + +/-! +# Monotone functions over sets +-/ + +variable {α β γ : Type*} + +open Equiv Equiv.Perm Function + +namespace Set + + +/-! ### Congruence lemmas for monotonicity and antitonicity -/ +section Order + +variable {s : Set α} {f₁ f₂ : α → β} [Preorder α] [Preorder β] + +theorem _root_.MonotoneOn.congr (h₁ : MonotoneOn f₁ s) (h : s.EqOn f₁ f₂) : MonotoneOn f₂ s := by + intro a ha b hb hab + rw [← h ha, ← h hb] + exact h₁ ha hb hab + +theorem _root_.AntitoneOn.congr (h₁ : AntitoneOn f₁ s) (h : s.EqOn f₁ f₂) : AntitoneOn f₂ s := + h₁.dual_right.congr h + +theorem _root_.StrictMonoOn.congr (h₁ : StrictMonoOn f₁ s) (h : s.EqOn f₁ f₂) : + StrictMonoOn f₂ s := by + intro a ha b hb hab + rw [← h ha, ← h hb] + exact h₁ ha hb hab + +theorem _root_.StrictAntiOn.congr (h₁ : StrictAntiOn f₁ s) (h : s.EqOn f₁ f₂) : StrictAntiOn f₂ s := + h₁.dual_right.congr h + +theorem EqOn.congr_monotoneOn (h : s.EqOn f₁ f₂) : MonotoneOn f₁ s ↔ MonotoneOn f₂ s := + ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ + +theorem EqOn.congr_antitoneOn (h : s.EqOn f₁ f₂) : AntitoneOn f₁ s ↔ AntitoneOn f₂ s := + ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ + +theorem EqOn.congr_strictMonoOn (h : s.EqOn f₁ f₂) : StrictMonoOn f₁ s ↔ StrictMonoOn f₂ s := + ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ + +theorem EqOn.congr_strictAntiOn (h : s.EqOn f₁ f₂) : StrictAntiOn f₁ s ↔ StrictAntiOn f₂ s := + ⟨fun h₁ => h₁.congr h, fun h₂ => h₂.congr h.symm⟩ + +end Order + +/-! ### Monotonicity lemmas -/ +section Mono + +variable {s s₂ : Set α} {f : α → β} [Preorder α] [Preorder β] + +theorem _root_.MonotoneOn.mono (h : MonotoneOn f s) (h' : s₂ ⊆ s) : MonotoneOn f s₂ := + fun _ hx _ hy => h (h' hx) (h' hy) + +theorem _root_.AntitoneOn.mono (h : AntitoneOn f s) (h' : s₂ ⊆ s) : AntitoneOn f s₂ := + fun _ hx _ hy => h (h' hx) (h' hy) + +theorem _root_.StrictMonoOn.mono (h : StrictMonoOn f s) (h' : s₂ ⊆ s) : StrictMonoOn f s₂ := + fun _ hx _ hy => h (h' hx) (h' hy) + +theorem _root_.StrictAntiOn.mono (h : StrictAntiOn f s) (h' : s₂ ⊆ s) : StrictAntiOn f s₂ := + fun _ hx _ hy => h (h' hx) (h' hy) + +protected theorem _root_.MonotoneOn.monotone (h : MonotoneOn f s) : + Monotone (f ∘ Subtype.val : s → β) := + fun x y hle => h x.coe_prop y.coe_prop hle + +protected theorem _root_.AntitoneOn.monotone (h : AntitoneOn f s) : + Antitone (f ∘ Subtype.val : s → β) := + fun x y hle => h x.coe_prop y.coe_prop hle + +protected theorem _root_.StrictMonoOn.strictMono (h : StrictMonoOn f s) : + StrictMono (f ∘ Subtype.val : s → β) := + fun x y hlt => h x.coe_prop y.coe_prop hlt + +protected theorem _root_.StrictAntiOn.strictAnti (h : StrictAntiOn f s) : + StrictAnti (f ∘ Subtype.val : s → β) := + fun x y hlt => h x.coe_prop y.coe_prop hlt + +lemma MonotoneOn_insert_iff {a : α} : + MonotoneOn f (insert a s) ↔ + (∀ b ∈ s, b ≤ a → f b ≤ f a) ∧ (∀ b ∈ s, a ≤ b → f a ≤ f b) ∧ MonotoneOn f s := by + simp [MonotoneOn, forall_and] + +lemma AntitoneOn_insert_iff {a : α} : + AntitoneOn f (insert a s) ↔ + (∀ b ∈ s, b ≤ a → f a ≤ f b) ∧ (∀ b ∈ s, a ≤ b → f b ≤ f a) ∧ AntitoneOn f s := + @MonotoneOn_insert_iff α βᵒᵈ _ _ _ _ _ + +end Mono + +end Set + + + +open Function + +/-! ### Monotone -/ +namespace Monotone + +variable [Preorder α] [Preorder β] {f : α → β} + +protected theorem restrict (h : Monotone f) (s : Set α) : Monotone (s.restrict f) := fun _ _ hxy => + h hxy + +protected theorem codRestrict (h : Monotone f) {s : Set β} (hs : ∀ x, f x ∈ s) : + Monotone (s.codRestrict f hs) := + h + +protected theorem rangeFactorization (h : Monotone f) : Monotone (Set.rangeFactorization f) := + h + +end Monotone + +section strictMono + +theorem StrictMonoOn.injOn [LinearOrder α] [Preorder β] {f : α → β} {s : Set α} + (H : StrictMonoOn f s) : s.InjOn f := fun x hx y hy hxy => + show Ordering.eq.Compares x y from (H.compares hx hy).1 hxy + +theorem StrictAntiOn.injOn [LinearOrder α] [Preorder β] {f : α → β} {s : Set α} + (H : StrictAntiOn f s) : s.InjOn f := + @StrictMonoOn.injOn α βᵒᵈ _ _ f s H + +theorem StrictMonoOn.comp [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} {f : α → β} {s : Set α} + {t : Set β} (hg : StrictMonoOn g t) (hf : StrictMonoOn f s) (hs : Set.MapsTo f s t) : + StrictMonoOn (g ∘ f) s := fun _x hx _y hy hxy => hg (hs hx) (hs hy) <| hf hx hy hxy + +theorem StrictMonoOn.comp_strictAntiOn [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} + {f : α → β} {s : Set α} {t : Set β} (hg : StrictMonoOn g t) (hf : StrictAntiOn f s) + (hs : Set.MapsTo f s t) : StrictAntiOn (g ∘ f) s := fun _x hx _y hy hxy => + hg (hs hy) (hs hx) <| hf hx hy hxy + +theorem StrictAntiOn.comp [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} {f : α → β} {s : Set α} + {t : Set β} (hg : StrictAntiOn g t) (hf : StrictAntiOn f s) (hs : Set.MapsTo f s t) : + StrictMonoOn (g ∘ f) s := fun _x hx _y hy hxy => hg (hs hy) (hs hx) <| hf hx hy hxy + +theorem StrictAntiOn.comp_strictMonoOn [Preorder α] [Preorder β] [Preorder γ] {g : β → γ} + {f : α → β} {s : Set α} {t : Set β} (hg : StrictAntiOn g t) (hf : StrictMonoOn f s) + (hs : Set.MapsTo f s t) : StrictAntiOn (g ∘ f) s := fun _x hx _y hy hxy => + hg (hs hx) (hs hy) <| hf hx hy hxy + +@[simp] +theorem strictMono_restrict [Preorder α] [Preorder β] {f : α → β} {s : Set α} : + StrictMono (s.restrict f) ↔ StrictMonoOn f s := by simp [Set.restrict, StrictMono, StrictMonoOn] + +alias ⟨_root_.StrictMono.of_restrict, _root_.StrictMonoOn.restrict⟩ := strictMono_restrict + +theorem StrictMono.codRestrict [Preorder α] [Preorder β] {f : α → β} (hf : StrictMono f) + {s : Set β} (hs : ∀ x, f x ∈ s) : StrictMono (Set.codRestrict f s hs) := + hf + +lemma strictMonoOn_insert_iff [Preorder α] [Preorder β] {f : α → β} {s : Set α} {a : α} : + StrictMonoOn f (insert a s) ↔ + (∀ b ∈ s, b < a → f b < f a) ∧ (∀ b ∈ s, a < b → f a < f b) ∧ StrictMonoOn f s := by + simp [StrictMonoOn, forall_and] + +lemma strictAntiOn_insert_iff [Preorder α] [Preorder β] {f : α → β} {s : Set α} {a : α} : + StrictAntiOn f (insert a s) ↔ + (∀ b ∈ s, b < a → f a < f b) ∧ (∀ b ∈ s, a < b → f b < f a) ∧ StrictAntiOn f s := + @strictMonoOn_insert_iff α βᵒᵈ _ _ _ _ _ + +end strictMono + +namespace Function + +open Set + +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 + rcases le_total (ψ x) (ψ y) with (ψxy|ψyx) + · exact ψxy + · have := hφ (ψts ys) (ψts xs) ψyx + rw [φψs.eq ys, φψs.eq xs] at this + induction le_antisymm l this + exact le_refl _ + +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 + +end Function diff --git a/Mathlib/Data/Set/Pointwise/BigOperators.lean b/Mathlib/Data/Set/Pointwise/BigOperators.lean index 2cc66bb66f328..7772e8e35548f 100644 --- a/Mathlib/Data/Set/Pointwise/BigOperators.lean +++ b/Mathlib/Data/Set/Pointwise/BigOperators.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Algebra.BigOperators.Group.Finset -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic /-! # Results about pointwise operations on sets and big operators. diff --git a/Mathlib/Data/Set/Pointwise/BoundedMul.lean b/Mathlib/Data/Set/Pointwise/BoundedMul.lean index 0472b092e5f72..2d630b685665e 100644 --- a/Mathlib/Data/Set/Pointwise/BoundedMul.lean +++ b/Mathlib/Data/Set/Pointwise/BoundedMul.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 KudryashovJ -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.Monoid.Defs /-! diff --git a/Mathlib/Data/Set/Pointwise/Finite.lean b/Mathlib/Data/Set/Pointwise/Finite.lean index dc7f3efc64c90..370ad1550f6b6 100644 --- a/Mathlib/Data/Set/Pointwise/Finite.lean +++ b/Mathlib/Data/Set/Pointwise/Finite.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.Group.Action.Basic -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Data.Set.Finite /-! # Finiteness lemmas for pointwise operations on sets -/ @@ -26,16 +26,6 @@ theorem finite_one : (1 : Set α).Finite := end One -section InvolutiveInv - -variable [InvolutiveInv α] {s : Set α} - -@[to_additive] -theorem Finite.inv (hs : s.Finite) : s⁻¹.Finite := - hs.preimage inv_injective.injOn - -end InvolutiveInv - section Mul variable [Mul α] {s t : Set α} @@ -109,20 +99,52 @@ section Cancel variable [Mul α] [IsLeftCancelMul α] [IsRightCancelMul α] {s t : Set α} @[to_additive] -theorem infinite_mul : (s * t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := - infinite_image2 (fun _ _ => (mul_left_injective _).injOn) fun _ _ => - (mul_right_injective _).injOn +lemma finite_mul : (s * t).Finite ↔ s.Finite ∧ t.Finite ∨ s = ∅ ∨ t = ∅ := + finite_image2 (fun _ _ ↦ (mul_left_injective _).injOn) fun _ _ ↦ (mul_right_injective _).injOn @[to_additive] -lemma finite_mul : (s * t).Finite ↔ s.Finite ∧ t.Finite ∨ s = ∅ ∨ t = ∅ := - finite_image2 (fun _ _ ↦ (mul_left_injective _).injOn) - fun _ _ ↦ (mul_right_injective _).injOn +lemma infinite_mul : (s * t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := + infinite_image2 (fun _ _ => (mul_left_injective _).injOn) fun _ _ => (mul_right_injective _).injOn end Cancel +section InvolutiveInv +variable [InvolutiveInv α] {s : Set α} + +@[to_additive (attr := simp)] lemma finite_inv : s⁻¹.Finite ↔ s.Finite := by + rw [← image_inv, finite_image_iff inv_injective.injOn] + +@[to_additive (attr := simp)] lemma infinite_inv : s⁻¹.Infinite ↔ s.Infinite := finite_inv.not + +@[to_additive] alias ⟨Finite.of_inv, Finite.inv⟩ := finite_inv + +end InvolutiveInv + +section Div +variable [Div α] {s t : Set α} + +@[to_additive] lemma Finite.div : s.Finite → t.Finite → (s / t).Finite := .image2 _ + +/-- Division preserves finiteness. -/ +@[to_additive "Subtraction preserves finiteness."] +def fintypeDiv [DecidableEq α] (s t : Set α) [Fintype s] [Fintype t] : Fintype (s / t) := + Set.fintypeImage2 _ _ _ + +end Div + section Group -variable [Group α] [MulAction α β] {a : α} {s : Set β} +variable [Group α] {s t : Set α} + +@[to_additive] +lemma finite_div : (s / t).Finite ↔ s.Finite ∧ t.Finite ∨ s = ∅ ∨ t = ∅ := + finite_image2 (fun _ _ ↦ div_left_injective.injOn) fun _ _ ↦ div_right_injective.injOn + +@[to_additive] +lemma infinite_div : (s / t).Infinite ↔ s.Infinite ∧ t.Nonempty ∨ t.Infinite ∧ s.Nonempty := + infinite_image2 (fun _ _ ↦ div_left_injective.injOn) fun _ _ ↦ div_right_injective.injOn + +variable [MulAction α β] {a : α} {s : Set β} @[to_additive (attr := simp)] theorem finite_smul_set : (a • s).Finite ↔ s.Finite := @@ -132,11 +154,8 @@ theorem finite_smul_set : (a • s).Finite ↔ s.Finite := theorem infinite_smul_set : (a • s).Infinite ↔ s.Infinite := infinite_image_iff (MulAction.injective _).injOn -alias ⟨Finite.of_smul_set, _⟩ := finite_smul_set - -alias ⟨_, Infinite.smul_set⟩ := infinite_smul_set - -attribute [to_additive] Finite.of_smul_set Infinite.smul_set +@[to_additive] alias ⟨Finite.of_smul_set, _⟩ := finite_smul_set +@[to_additive] alias ⟨_, Infinite.smul_set⟩ := infinite_smul_set end Group diff --git a/Mathlib/Data/Set/Pointwise/Interval.lean b/Mathlib/Data/Set/Pointwise/Interval.lean index 291fcb810c4c8..96c008f454acd 100644 --- a/Mathlib/Data/Set/Pointwise/Interval.lean +++ b/Mathlib/Data/Set/Pointwise/Interval.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Yury Kudryashov. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov, Patrick Massot -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Order.Group.MinMax import Mathlib.Algebra.Order.Interval.Set.Monoid @@ -509,12 +509,12 @@ variable [LinearOrderedField α] {a : α} @[simp] theorem preimage_mul_const_Iio (a : α) {c : α} (h : 0 < c) : (fun x => x * c) ⁻¹' Iio a = Iio (a / c) := - ext fun _x => (lt_div_iff h).symm + ext fun _x => (lt_div_iff₀ h).symm @[simp] theorem preimage_mul_const_Ioi (a : α) {c : α} (h : 0 < c) : (fun x => x * c) ⁻¹' Ioi a = Ioi (a / c) := - ext fun _x => (div_lt_iff h).symm + ext fun _x => (div_lt_iff₀ h).symm @[simp] theorem preimage_mul_const_Iic (a : α) {c : α} (h : 0 < c) : @@ -582,11 +582,11 @@ theorem preimage_mul_const_Icc_of_neg (a b : α) {c : α} (h : c < 0) : @[simp] theorem preimage_const_mul_Iio (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' Iio a = Iio (a / c) := - ext fun _x => (lt_div_iff' h).symm + ext fun _x => (lt_div_iff₀' h).symm @[simp] theorem preimage_const_mul_Ioi (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' Ioi a = Ioi (a / c) := - ext fun _x => (div_lt_iff' h).symm + ext fun _x => (div_lt_iff₀' h).symm @[simp] theorem preimage_const_mul_Iic (a : α) {c : α} (h : 0 < c) : (c * ·) ⁻¹' Iic a = Iic (a / c) := @@ -718,9 +718,9 @@ theorem image_mul_left_Ioo {a : α} (h : 0 < a) (b c : α) : theorem inv_Ioo_0_left {a : α} (ha : 0 < a) : (Ioo 0 a)⁻¹ = Ioi a⁻¹ := by ext x exact - ⟨fun h => inv_inv x ▸ (inv_lt_inv ha h.1).2 h.2, fun h => + ⟨fun h => inv_inv x ▸ (inv_lt_inv₀ ha h.1).2 h.2, fun h => ⟨inv_pos.2 <| (inv_pos.2 ha).trans h, - inv_inv a ▸ (inv_lt_inv ((inv_pos.2 ha).trans h) + inv_inv a ▸ (inv_lt_inv₀ ((inv_pos.2 ha).trans h) (inv_pos.2 ha)).2 h⟩⟩ theorem inv_Ioi {a : α} (ha : 0 < a) : (Ioi a)⁻¹ = Ioo 0 a⁻¹ := by diff --git a/Mathlib/Data/Set/Pointwise/ListOfFn.lean b/Mathlib/Data/Set/Pointwise/ListOfFn.lean index 309b0b70bb701..120059da9dfca 100644 --- a/Mathlib/Data/Set/Pointwise/ListOfFn.lean +++ b/Mathlib/Data/Set/Pointwise/ListOfFn.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Wieser -/ import Mathlib.Algebra.BigOperators.Group.List -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Data.List.OfFn /-! @@ -15,8 +15,7 @@ This file proves some lemmas about pointwise algebraic operations with lists of namespace Set -variable {F α β γ : Type*} -variable [Monoid α] {s t : Set α} {a : α} {m n : ℕ} +variable {α : Type*} [Monoid α] {s : Set α} {n : ℕ} open Pointwise diff --git a/Mathlib/Data/Set/Pointwise/SMul.lean b/Mathlib/Data/Set/Pointwise/SMul.lean index 7e53675dbbac8..e3ed79c944b46 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.Group.Pi.Basic -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.GroupWithZero.Action.Basic import Mathlib.Algebra.Module.Defs import Mathlib.Data.Set.Pairwise.Basic diff --git a/Mathlib/Data/Set/Prod.lean b/Mathlib/Data/Set/Prod.lean index acc80442bafa7..d147798baa0d9 100644 --- a/Mathlib/Data/Set/Prod.lean +++ b/Mathlib/Data/Set/Prod.lean @@ -9,13 +9,15 @@ import Mathlib.Data.SProd /-! # Sets in product and pi types -This file defines the product of sets in `α × β` and in `Π i, α i` along with the diagonal of a -type. +This file proves basic properties of product of sets in `α × β` and in `Π i, α i`, and of the +diagonal of a type. ## Main declarations +This file contains basic results on the following notions, which are defined in `Set.Operations`. + * `Set.prod`: Binary product of sets. For `s : Set α`, `t : Set β`, we have - `s.prod t : Set (α × β)`. + `s.prod t : Set (α × β)`. Denoted by `s ×ˢ t`. * `Set.diagonal`: Diagonal of a type. `Set.diagonal α = {(x, x) | x : α}`. * `Set.offDiag`: Off-diagonal. `s ×ˢ s` without the diagonal. * `Set.pi`: Arbitrary product of sets. @@ -299,6 +301,9 @@ theorem fst_image_prod (s : Set β) {t : Set α} (ht : t.Nonempty) : Prod.fst '' let ⟨x, hx⟩ := ht ⟨(y, x), ⟨hy, hx⟩, rfl⟩ +lemma mapsTo_fst_prod {s : Set α} {t : Set β} : MapsTo Prod.fst (s ×ˢ t) s := + fun _ hx ↦ (mem_prod.1 hx).1 + theorem prod_subset_preimage_snd (s : Set α) (t : Set β) : s ×ˢ t ⊆ Prod.snd ⁻¹' t := inter_subset_right @@ -310,6 +315,9 @@ theorem snd_image_prod {s : Set α} (hs : s.Nonempty) (t : Set β) : Prod.snd '' let ⟨x, x_in⟩ := hs ⟨(x, y), ⟨x_in, y_in⟩, rfl⟩ +lemma mapsTo_snd_prod {s : Set α} {t : Set β} : MapsTo Prod.snd (s ×ˢ t) t := + fun _ hx ↦ (mem_prod.1 hx).2 + theorem prod_diff_prod : s ×ˢ t \ s₁ ×ˢ t₁ = s ×ˢ (t \ t₁) ∪ (s \ s₁) ×ˢ t := by ext x by_cases h₁ : x.1 ∈ s₁ <;> by_cases h₂ : x.2 ∈ t₁ <;> simp [*] @@ -678,15 +686,6 @@ theorem disjoint_pi : Disjoint (s.pi t₁) (s.pi t₂) ↔ ∃ i ∈ s, Disjoint end Nonempty --- Porting note: Removing `simp` - LHS does not simplify -theorem range_dcomp (f : ∀ i, α i → β i) : - (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by - refine Subset.antisymm ?_ fun x hx => ?_ - · rintro _ ⟨x, rfl⟩ i - - exact ⟨x i, rfl⟩ - · choose y hy using hx - exact ⟨fun i => y i trivial, funext fun i => hy i trivial⟩ - @[simp] theorem insert_pi (i : ι) (s : Set ι) (t : ∀ i, Set (α i)) : pi (insert i s) t = eval i ⁻¹' t i ∩ pi s t := by @@ -801,8 +800,8 @@ theorem eval_image_univ_pi (ht : (pi univ t).Nonempty) : (fun f : ∀ i, α i => f i) '' pi univ t = t i := eval_image_pi (mem_univ i) ht -theorem dcomp_image_pi {f : ∀ i, α i → β i} (hf : ∀ i ∉ s, Surjective (f i)) (t : ∀ i, Set (α i)) : - (f _ ∘' ·) '' s.pi t = s.pi fun i ↦ f i '' t i := by +theorem piMap_image_pi {f : ∀ i, α i → β i} (hf : ∀ i ∉ s, Surjective (f i)) (t : ∀ i, Set (α i)) : + Pi.map f '' s.pi t = s.pi fun i ↦ f i '' t i := by refine Subset.antisymm (image_subset_iff.2 fun a ha i hi ↦ mem_image_of_mem _ (ha _ hi)) ?_ intro b hb have : ∀ i, ∃ a, f i a = b i ∧ (i ∈ s → a ∈ t i) := by @@ -814,9 +813,19 @@ theorem dcomp_image_pi {f : ∀ i, α i → β i} (hf : ∀ i ∉ s, Surjective choose a hab hat using this exact ⟨a, hat, funext hab⟩ -theorem dcomp_image_univ_pi (f : ∀ i, α i → β i) (t : ∀ i, Set (α i)) : - (f _ ∘' ·) '' univ.pi t = univ.pi fun i ↦ f i '' t i := - dcomp_image_pi (by simp) t +@[deprecated (since := "2024-10-06")] alias dcomp_image_pi := piMap_image_pi + +theorem piMap_image_univ_pi (f : ∀ i, α i → β i) (t : ∀ i, Set (α i)) : + Pi.map f '' univ.pi t = univ.pi fun i ↦ f i '' t i := + piMap_image_pi (by simp) t + +@[deprecated (since := "2024-10-06")] alias dcomp_image_univ_pi := piMap_image_univ_pi + +@[simp] +theorem range_piMap (f : ∀ i, α i → β i) : range (Pi.map f) = pi univ fun i ↦ range (f i) := by + simp only [← image_univ, ← piMap_image_univ_pi, pi_univ] + +@[deprecated (since := "2024-10-06")] alias range_dcomp := range_piMap theorem pi_subset_pi_iff : pi s t₁ ⊆ pi s t₂ ↔ (∀ i ∈ s, t₁ i ⊆ t₂ i) ∨ pi s t₁ = ∅ := by refine diff --git a/Mathlib/Data/Set/Semiring.lean b/Mathlib/Data/Set/Semiring.lean index 65db6ecc8dee6..e6ff5cf305201 100644 --- a/Mathlib/Data/Set/Semiring.lean +++ b/Mathlib/Data/Set/Semiring.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Floris van Doorn. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.Algebra.Order.Kleene import Mathlib.Algebra.Order.Ring.Canonical diff --git a/Mathlib/Data/SetLike/Basic.lean b/Mathlib/Data/SetLike/Basic.lean index fa52573699827..2a07db5d06280 100644 --- a/Mathlib/Data/SetLike/Basic.lean +++ b/Mathlib/Data/SetLike/Basic.lean @@ -28,7 +28,7 @@ boilerplate for every `SetLike`: a `coe_sort`, a `coe` to set, a A typical subobject should be declared as: ``` -structure MySubobject (X : Type*) [ObjectTypeclass X] := +structure MySubobject (X : Type*) [ObjectTypeclass X] where (carrier : Set X) (op_mem' : ∀ {x : X}, x ∈ carrier → sorry ∈ carrier) @@ -60,7 +60,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 α β where (ext_iff : ∀ {s t : β}, s = t ↔ ∀ (x : α), x ∈ s ↔ x ∈ t) ``` While this is equivalent, `SetLike` conveniently uses a carrier set projection directly. @@ -121,9 +121,9 @@ uses the `SetLike.instMembership` instance. -/ def delabSubtypeSetLike : Delab := whenPPOption getPPNotation do let #[_, .lam n _ body _] := (← getExpr).getAppArgs | failure guard <| body.isAppOf ``Membership.mem - let #[_, _, inst, .bvar 0, _] := body.getAppArgs | failure + let #[_, _, inst, _, .bvar 0] := body.getAppArgs | failure guard <| inst.isAppOfArity ``instMembership 3 - let S ← withAppArg <| withBindingBody n <| withNaryArg 4 delab + let S ← withAppArg <| withBindingBody n <| withNaryArg 3 delab `(↥$S) end Delab @@ -191,17 +191,15 @@ instance (priority := 100) instPartialOrder : PartialOrder A := theorem le_def {S T : A} : S ≤ T ↔ ∀ ⦃x : B⦄, x ∈ S → x ∈ T := Iff.rfl -@[simp, norm_cast] -theorem coe_subset_coe {S T : A} : (S : Set B) ⊆ T ↔ S ≤ T := - Iff.rfl +@[simp, norm_cast] lemma coe_subset_coe {S T : A} : (S : Set B) ⊆ T ↔ S ≤ T := .rfl +@[simp, norm_cast] lemma coe_ssubset_coe {S T : A} : (S : Set B) ⊂ T ↔ S < T := .rfl + +@[gcongr] protected alias ⟨_, GCongr.coe_subset_coe⟩ := coe_subset_coe +@[gcongr] protected alias ⟨_, GCongr.coe_ssubset_coe⟩ := coe_ssubset_coe @[mono] theorem coe_mono : Monotone (SetLike.coe : A → Set B) := fun _ _ => coe_subset_coe.mpr -@[simp, norm_cast] -theorem coe_ssubset_coe {S T : A} : (S : Set B) ⊂ T ↔ S < T := - Iff.rfl - @[mono] theorem coe_strictMono : StrictMono (SetLike.coe : A → Set B) := fun _ _ => coe_ssubset_coe.mpr diff --git a/Mathlib/Data/Setoid/Basic.lean b/Mathlib/Data/Setoid/Basic.lean index ca1d0ac665068..8734d5bf5b8d2 100644 --- a/Mathlib/Data/Setoid/Basic.lean +++ b/Mathlib/Data/Setoid/Basic.lean @@ -91,7 +91,7 @@ def ker (f : α → β) : Setoid α := theorem ker_mk_eq (r : Setoid α) : ker (@Quotient.mk'' _ r) = r := ext' fun _ _ => Quotient.eq -theorem ker_apply_mk_out {f : α → β} (a : α) : f (haveI := Setoid.ker f; ⟦a⟧.out) = f a := +theorem ker_apply_mk_out {f : α → β} (a : α) : f (⟦a⟧ : Quotient (Setoid.ker f)).out = f a := @Quotient.mk_out _ (Setoid.ker f) a theorem ker_apply_mk_out' {f : α → β} (a : α) : @@ -111,6 +111,49 @@ protected def prod (r : Setoid α) (s : Setoid β) : ⟨fun x => ⟨r.refl' x.1, s.refl' x.2⟩, fun h => ⟨r.symm' h.1, s.symm' h.2⟩, fun h₁ h₂ => ⟨r.trans' h₁.1 h₂.1, s.trans' h₁.2 h₂.2⟩⟩ +lemma prod_apply {r : Setoid α} {s : Setoid β} {x₁ x₂ : α} {y₁ y₂ : β} : + @Setoid.r _ (r.prod s) (x₁, y₁) (x₂, y₂) ↔ (@Setoid.r _ r x₁ x₂ ∧ @Setoid.r _ s y₁ y₂) := + Iff.rfl + +lemma piSetoid_apply {ι : Sort*} {α : ι → Sort*} {r : ∀ i, Setoid (α i)} {x y : ∀ i, α i} : + @Setoid.r _ (@piSetoid _ _ r) x y ↔ ∀ i, @Setoid.r _ (r i) (x i) (y i) := + Iff.rfl + +/-- A bijection between the product of two quotients and the quotient by the product of the +equivalence relations. -/ +@[simps] +def prodQuotientEquiv (r : Setoid α) (s : Setoid β) : + Quotient r × Quotient s ≃ Quotient (r.prod s) where + toFun := fun (x, y) ↦ Quotient.map₂' Prod.mk (fun _ _ hx _ _ hy ↦ ⟨hx, hy⟩) x y + invFun := fun q ↦ Quotient.liftOn' q (fun xy ↦ (Quotient.mk'' xy.1, Quotient.mk'' xy.2)) + fun x y hxy ↦ Prod.ext (by simpa using hxy.1) (by simpa using hxy.2) + left_inv := fun q ↦ by + rcases q with ⟨qa, qb⟩ + exact Quotient.inductionOn₂' qa qb fun _ _ ↦ rfl + right_inv := fun q ↦ by + simp only + refine Quotient.inductionOn' q fun _ ↦ rfl + +/-- A bijection between an indexed product of quotients and the quotient by the product of the +equivalence relations. -/ +@[simps] +noncomputable def piQuotientEquiv {ι : Sort*} {α : ι → Sort*} (r : ∀ i, Setoid (α i)) : + (∀ i, Quotient (r i)) ≃ Quotient (@piSetoid _ _ r) where + toFun := fun x ↦ Quotient.mk'' fun i ↦ (x i).out' + invFun := fun q ↦ Quotient.liftOn' q (fun x i ↦ Quotient.mk'' (x i)) fun x y hxy ↦ by + ext i + simpa using hxy i + left_inv := fun q ↦ by + ext i + simp + right_inv := fun q ↦ by + refine Quotient.inductionOn' q fun _ ↦ ?_ + simp only [Quotient.liftOn'_mk'', Quotient.eq''] + intro i + change Setoid.r _ _ + rw [← Quotient.eq''] + simp + /-- The infimum of two equivalence relations. -/ instance : Inf (Setoid α) := ⟨fun r s => @@ -420,7 +463,7 @@ def sigmaQuotientEquivOfLe {r s : Setoid α} (hle : r ≤ s) : (Σ q : Quotient s, Quotient (r.comap (Subtype.val : Quotient.mk s ⁻¹' {q} → α))) ≃ Quotient r := .trans (.symm <| .sigmaCongrRight fun _ ↦ .subtypeQuotientEquivQuotientSubtype - (s₁ := r) (s₂ := r.comap Subtype.val) _ (fun _ ↦ Iff.rfl) fun _ _ ↦ Iff.rfl) + (s₁ := r) (s₂ := r.comap Subtype.val) _ _ (fun _ ↦ Iff.rfl) fun _ _ ↦ Iff.rfl) (.sigmaFiberEquiv fun a ↦ a.lift (Quotient.mk s) fun _ _ h ↦ Quotient.sound <| hle h) end Setoid diff --git a/Mathlib/Data/Setoid/Partition.lean b/Mathlib/Data/Setoid/Partition.lean index 1cc028237c179..7813b2de0bebe 100644 --- a/Mathlib/Data/Setoid/Partition.lean +++ b/Mathlib/Data/Setoid/Partition.lean @@ -156,8 +156,8 @@ theorem sUnion_classes (r : Setoid α) : ⋃₀ r.classes = Set.univ := /-- The equivalence between the quotient by an equivalence relation and its type of equivalence classes. -/ noncomputable def quotientEquivClasses (r : Setoid α) : Quotient r ≃ Setoid.classes r := by - let f (a : α) : Setoid.classes r := ⟨{ x | Setoid.r x a }, Setoid.mem_classes r a⟩ - have f_respects_relation (a b : α) (a_rel_b : Setoid.r a b) : f a = f b := by + let f (a : α) : Setoid.classes r := ⟨{ x | r x a }, Setoid.mem_classes r a⟩ + have f_respects_relation (a b : α) (a_rel_b : r a b) : f a = f b := by rw [Subtype.mk.injEq] exact Setoid.eq_of_mem_classes (Setoid.mem_classes r a) (Setoid.symm a_rel_b) (Setoid.mem_classes r b) (Setoid.refl b) @@ -168,7 +168,7 @@ noncomputable def quotientEquivClasses (r : Setoid α) : Quotient r ≃ Setoid.c induction' q_b using Quotient.ind with b simp only [Subtype.ext_iff, Quotient.lift_mk, Subtype.ext_iff] at h_eq apply Quotient.sound - show a ∈ { x | Setoid.r x b } + show a ∈ { x | r x b } rw [← h_eq] exact Setoid.refl a · rw [Quot.surjective_lift] diff --git a/Mathlib/Data/Sigma/Lex.lean b/Mathlib/Data/Sigma/Lex.lean index 6b5e6be4f0f6d..db66010da8c5d 100644 --- a/Mathlib/Data/Sigma/Lex.lean +++ b/Mathlib/Data/Sigma/Lex.lean @@ -137,7 +137,7 @@ end Sigma namespace PSigma -variable {ι : Sort*} {α : ι → Sort*} {r r₁ r₂ : ι → ι → Prop} {s s₁ s₂ : ∀ i, α i → α i → Prop} +variable {ι : Sort*} {α : ι → Sort*} {r : ι → ι → Prop} {s : ∀ i, α i → α i → Prop} theorem lex_iff {a b : Σ' i, α i} : Lex r s a b ↔ r a.1 b.1 ∨ ∃ h : a.1 = b.1, s b.1 (h.rec a.2) b.2 := by diff --git a/Mathlib/Data/Stream/Defs.lean b/Mathlib/Data/Stream/Defs.lean index ce2dc694fd4fc..787e4441675ac 100644 --- a/Mathlib/Data/Stream/Defs.lean +++ b/Mathlib/Data/Stream/Defs.lean @@ -94,7 +94,7 @@ infixl:65 " ⋈ " => interleave /-- Elements of a stream with even indices. -/ def even (s : Stream' α) : Stream' α := - corec (fun s => head s) (fun s => tail (tail s)) s + corec head (fun s => tail (tail s)) s /-- Elements of a stream with odd indices. -/ def odd (s : Stream' α) : Stream' α := diff --git a/Mathlib/Data/Subtype.lean b/Mathlib/Data/Subtype.lean index 48aaa0d08f165..0583ba40e98cc 100644 --- a/Mathlib/Data/Subtype.lean +++ b/Mathlib/Data/Subtype.lean @@ -207,7 +207,7 @@ end Subtype namespace Subtype /-! Some facts about sets, which require that `α` is a type. -/ -variable {α β γ : Type*} {p : α → Prop} +variable {α : Type*} @[simp] theorem coe_prop {S : Set α} (a : { a // a ∈ S }) : ↑a ∈ S := diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 9da00e98e9adb..d65e9ce7874fe 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -35,7 +35,7 @@ theorem sum_rec_congr (P : α ⊕ β → Sort*) (f : ∀ i, P (inl i)) (g : ∀ section get -variable {x y : α ⊕ β} +variable {x : α ⊕ β} theorem eq_left_iff_getLeft_eq {a : α} : x = inl a ↔ ∃ h, x.getLeft h = a := by cases x <;> simp diff --git a/Mathlib/Data/Vector/Defs.lean b/Mathlib/Data/Vector/Defs.lean index 81ec5ceb94570..8c08c0254b502 100644 --- a/Mathlib/Data/Vector/Defs.lean +++ b/Mathlib/Data/Vector/Defs.lean @@ -119,7 +119,7 @@ def take (i : ℕ) : Vector α n → Vector α (min i n) /-- Remove the element at position `i` from a vector of length `n`. -/ def eraseIdx (i : Fin n) : Vector α n → Vector α (n - 1) - | ⟨l, p⟩ => ⟨List.eraseIdx l i.1, by rw [l.length_eraseIdx] <;> rw [p]; exact i.2⟩ + | ⟨l, p⟩ => ⟨List.eraseIdx l i.1, by rw [l.length_eraseIdx_of_lt] <;> rw [p]; exact i.2⟩ @[deprecated (since := "2024-05-04")] alias removeNth := eraseIdx diff --git a/Mathlib/Data/W/Cardinal.lean b/Mathlib/Data/W/Cardinal.lean index 911d370ca2ef1..5841bc9d66bd1 100644 --- a/Mathlib/Data/W/Cardinal.lean +++ b/Mathlib/Data/W/Cardinal.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ import Mathlib.Data.W.Basic -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic /-! # Cardinality of W-types diff --git a/Mathlib/Data/ZMod/Basic.lean b/Mathlib/Data/ZMod/Basic.lean index 587f8afc8aa50..ba4a441a9fdfe 100644 --- a/Mathlib/Data/ZMod/Basic.lean +++ b/Mathlib/Data/ZMod/Basic.lean @@ -826,6 +826,17 @@ theorem eq_iff_modEq_nat (n : ℕ) {a b : ℕ} : (a : ZMod n) = b ↔ a ≡ b [M · rw [Fin.ext_iff, Nat.ModEq, ← val_natCast, ← val_natCast] exact Iff.rfl +theorem eq_zero_iff_even {n : ℕ} : (n : ZMod 2) = 0 ↔ Even n := + (CharP.cast_eq_zero_iff (ZMod 2) 2 n).trans even_iff_two_dvd.symm + +theorem eq_one_iff_odd {n : ℕ} : (n : ZMod 2) = 1 ↔ Odd n := by + rw [← @Nat.cast_one (ZMod 2), ZMod.eq_iff_modEq_nat, Nat.odd_iff, Nat.ModEq] + +theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by + constructor <;> + · contrapose + simp [eq_zero_iff_even] + theorem coe_mul_inv_eq_one {n : ℕ} (x : ℕ) (h : Nat.Coprime x n) : ((x : ZMod n) * (x : ZMod n)⁻¹) = 1 := by rw [Nat.Coprime, Nat.gcd_comm, Nat.gcd_rec] at h @@ -1005,7 +1016,7 @@ theorem val_eq_one : ∀ {n : ℕ} (_ : 1 < n) (a : ZMod n), a.val = 1 ↔ a = 1 theorem neg_eq_self_iff {n : ℕ} (a : ZMod n) : -a = a ↔ a = 0 ∨ 2 * a.val = n := by rw [neg_eq_iff_add_eq_zero, ← two_mul] cases n - · erw [@mul_eq_zero ℤ, @mul_eq_zero ℕ, val_eq_zero] + · rw [@mul_eq_zero ℤ, @mul_eq_zero ℕ, val_eq_zero] exact ⟨fun h => h.elim (by simp) Or.inl, fun h => Or.inr (h.elim id fun h => h.elim (by simp) id)⟩ @@ -1014,7 +1025,7 @@ theorem neg_eq_self_iff {n : ℕ} (a : ZMod n) : -a = a ↔ a = 0 ∨ 2 * a.val constructor · rintro ⟨m, he⟩ cases' m with m - · erw [mul_zero, mul_eq_zero] at he + · rw [mul_zero, mul_eq_zero] at he rcases he with (⟨⟨⟩⟩ | he) exact Or.inl (a.val_eq_zero.1 he) cases m @@ -1207,7 +1218,7 @@ theorem valMinAbs_eq_zero {n : ℕ} (x : ZMod n) : x.valMinAbs = 0 ↔ x = 0 := theorem natCast_natAbs_valMinAbs {n : ℕ} [NeZero n] (a : ZMod n) : (a.valMinAbs.natAbs : ZMod n) = if a.val ≤ (n : ℕ) / 2 then a else -a := by have : (a.val : ℤ) - n ≤ 0 := by - erw [sub_nonpos, Int.ofNat_le] + rw [sub_nonpos, Int.ofNat_le] exact a.val_le rw [valMinAbs_def_pos] split_ifs diff --git a/Mathlib/Data/ZMod/Defs.lean b/Mathlib/Data/ZMod/Defs.lean index 324dec3252219..76e27012548a5 100644 --- a/Mathlib/Data/ZMod/Defs.lean +++ b/Mathlib/Data/ZMod/Defs.lean @@ -5,6 +5,7 @@ Authors: Eric Rodriguez -/ import Mathlib.Algebra.Group.Fin.Basic import Mathlib.Algebra.NeZero +import Mathlib.Algebra.Ring.Int import Mathlib.Data.Nat.ModEq import Mathlib.Data.Fintype.Card @@ -103,7 +104,7 @@ namespace ZMod instance instUnique : Unique (ZMod 1) := Fin.uniqueFinOne instance fintype : ∀ (n : ℕ) [NeZero n], Fintype (ZMod n) - | 0, h => (h.ne rfl).elim + | 0, h => (h.ne _ rfl).elim | n + 1, _ => Fin.fintype (n + 1) instance infinite : Infinite (ZMod 0) := diff --git a/Mathlib/Data/ZMod/Parity.lean b/Mathlib/Data/ZMod/Parity.lean deleted file mode 100644 index b6686f1e23ec5..0000000000000 --- a/Mathlib/Data/ZMod/Parity.lean +++ /dev/null @@ -1,33 +0,0 @@ -/- -Copyright (c) 2020 Kyle Miller. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kyle Miller --/ -import Mathlib.Algebra.Order.Ring.Abs -import Mathlib.Data.ZMod.Basic - -/-! -# Relating parity to natural numbers mod 2 - -This module provides lemmas relating `ZMod 2` to `Even` and `Odd`. - -## Tags - -parity, zmod, even, odd --/ - - -namespace ZMod - -theorem eq_zero_iff_even {n : ℕ} : (n : ZMod 2) = 0 ↔ Even n := - (CharP.cast_eq_zero_iff (ZMod 2) 2 n).trans even_iff_two_dvd.symm - -theorem eq_one_iff_odd {n : ℕ} : (n : ZMod 2) = 1 ↔ Odd n := by - rw [← @Nat.cast_one (ZMod 2), ZMod.eq_iff_modEq_nat, Nat.odd_iff, Nat.ModEq] - -theorem ne_zero_iff_odd {n : ℕ} : (n : ZMod 2) ≠ 0 ↔ Odd n := by - constructor <;> - · contrapose - simp [eq_zero_iff_even] - -end ZMod diff --git a/Mathlib/Deprecated/Group.lean b/Mathlib/Deprecated/Group.lean index d2d59cec9f5b0..539782f49e725 100644 --- a/Mathlib/Deprecated/Group.lean +++ b/Mathlib/Deprecated/Group.lean @@ -359,7 +359,7 @@ end Units namespace IsUnit -variable {M : Type*} {N : Type*} [Monoid M] [Monoid N] {x : M} +variable {M : Type*} {N : Type*} [Monoid M] [Monoid N] theorem map' {f : M → N} (hf : IsMonoidHom f) {x : M} (h : IsUnit x) : IsUnit (f x) := h.map (MonoidHom.of hf) diff --git a/Mathlib/Deprecated/Ring.lean b/Mathlib/Deprecated/Ring.lean index 5cc4f4a17e1ca..fc34ab12c07ee 100644 --- a/Mathlib/Deprecated/Ring.lean +++ b/Mathlib/Deprecated/Ring.lean @@ -27,7 +27,7 @@ IsSemiringHom, IsRingHom -/ -universe u v w +universe u v variable {α : Type u} @@ -45,7 +45,7 @@ structure IsSemiringHom {α : Type u} {β : Type v} [Semiring α] [Semiring β] namespace IsSemiringHom variable {β : Type v} [Semiring α] [Semiring β] -variable {f : α → β} (hf : IsSemiringHom f) {x y : α} +variable {f : α → β} /-- The identity map is a semiring homomorphism. -/ theorem id : IsSemiringHom (@id α) := by constructor <;> intros <;> rfl @@ -85,7 +85,7 @@ variable {β : Type v} [Ring α] [Ring β] theorem of_semiring {f : α → β} (H : IsSemiringHom f) : IsRingHom f := { H with } -variable {f : α → β} (hf : IsRingHom f) {x y : α} +variable {f : α → β} {x y : α} /-- Ring homomorphisms map zero to zero. -/ theorem map_zero (hf : IsRingHom f) : f 0 = 0 := @@ -122,7 +122,7 @@ theorem to_isAddGroupHom (hf : IsRingHom f) : IsAddGroupHom f := end IsRingHom -variable {β : Type v} {γ : Type w} {rα : Semiring α} {rβ : Semiring β} +variable {β : Type v} {rα : Semiring α} {rβ : Semiring β} namespace RingHom diff --git a/Mathlib/Deprecated/Subgroup.lean b/Mathlib/Deprecated/Subgroup.lean index b7c3f4795f8ec..f30ed0f0e3ca3 100644 --- a/Mathlib/Deprecated/Subgroup.lean +++ b/Mathlib/Deprecated/Subgroup.lean @@ -453,7 +453,8 @@ theorem closure_subgroup {s : Set G} (hs : IsSubgroup s) : closure s = s := @[to_additive] theorem exists_list_of_mem_closure {s : Set G} {a : G} (h : a ∈ closure s) : ∃ l : List G, (∀ x ∈ l, x ∈ s ∨ x⁻¹ ∈ s) ∧ l.prod = a := - InClosure.recOn h (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, one_mul _⟩) + InClosure.recOn h + (fun {x} hxs => ⟨[x], List.forall_mem_singleton.2 <| Or.inl hxs, List.prod_singleton⟩) ⟨[], List.forall_mem_nil _, rfl⟩ (fun {x} _ ⟨L, HL1, HL2⟩ => ⟨L.reverse.map Inv.inv, fun x hx => diff --git a/Mathlib/Deprecated/Subring.lean b/Mathlib/Deprecated/Subring.lean index 7c267c4d4f513..20fc691ea4b93 100644 --- a/Mathlib/Deprecated/Subring.lean +++ b/Mathlib/Deprecated/Subring.lean @@ -97,7 +97,8 @@ theorem exists_list_of_mem_closure {a : R} (h : a ∈ closure s) : ∃ L : List (List R), (∀ l ∈ L, ∀ x ∈ l, x ∈ s ∨ x = (-1 : R)) ∧ (L.map List.prod).sum = a := AddGroup.InClosure.recOn h fun {x} hx ↦ match x, Monoid.exists_list_of_mem_closure hx with - | _, ⟨L, h1, rfl⟩ => ⟨[L], List.forall_mem_singleton.2 fun r hr ↦ Or.inl (h1 r hr), zero_add _⟩ + | _, ⟨L, h1, rfl⟩ => + ⟨[L], List.forall_mem_singleton.2 fun r hr ↦ Or.inl (h1 r hr), List.sum_singleton⟩ ⟨[], List.forall_mem_nil _, rfl⟩ fun {b} _ ih ↦ match b, ih with | _, ⟨L1, h1, rfl⟩ => diff --git a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean index a47e9d3145ffb..bf93db2355a6d 100644 --- a/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean +++ b/Mathlib/Dynamics/Circle/RotationNumber/TranslationNumber.lean @@ -852,8 +852,8 @@ theorem semiconj_of_group_action_of_forall_translationNumber_eq {G : Type*} [Gro have hF₁ : ∀ g, ⇑(F₁ g) = f₁ g := fun _ => rfl have hF₂ : ∀ g, ⇑(F₂ g) = f₂ g := fun _ => rfl -- Now we apply `csSup_div_semiconj` and go back to `f₁` and `f₂`. - refine ⟨⟨⟨_, fun x y hxy => ?_⟩, fun x => ?_⟩, csSup_div_semiconj F₂ F₁ fun x => ?_⟩ <;> - simp only [hF₁, hF₂, ← map_inv, coe_mk] + refine ⟨⟨⟨fun x ↦ ⨆ g', (F₂ g')⁻¹ (F₁ g' x), fun x y hxy => ?_⟩, fun x => ?_⟩, + csSup_div_semiconj F₂ F₁ fun x => ?_⟩ <;> simp only [hF₁, hF₂, ← map_inv, coe_mk] · exact ciSup_mono (this y) fun g => mono _ (mono _ hxy) · simp only [map_add_one] exact (Monotone.map_ciSup_of_continuousAt (continuousAt_id.add continuousAt_const) diff --git a/Mathlib/Dynamics/PeriodicPts.lean b/Mathlib/Dynamics/PeriodicPts.lean index 3f47192c4cc47..160a6606f5e0f 100644 --- a/Mathlib/Dynamics/PeriodicPts.lean +++ b/Mathlib/Dynamics/PeriodicPts.lean @@ -338,7 +338,7 @@ theorem not_isPeriodicPt_of_pos_of_lt_minimalPeriod : theorem IsPeriodicPt.minimalPeriod_dvd (hx : IsPeriodicPt f n x) : minimalPeriod f x ∣ n := (eq_or_lt_of_le <| n.zero_le).elim (fun hn0 => hn0 ▸ dvd_zero _) fun hn0 => -- Porting note: `Nat.dvd_iff_mod_eq_zero` gained explicit arguments - (Nat.dvd_iff_mod_eq_zero _ _).2 <| + Nat.dvd_iff_mod_eq_zero.2 <| (hx.mod <| isPeriodicPt_minimalPeriod f x).eq_zero_of_lt_minimalPeriod <| Nat.mod_lt _ <| hx.minimalPeriod_pos hn0 @@ -433,7 +433,7 @@ theorem periodicOrbit_length : (periodicOrbit f x).length = minimalPeriod f x := @[simp] theorem periodicOrbit_eq_nil_iff_not_periodic_pt : periodicOrbit f x = Cycle.nil ↔ x ∉ periodicPts f := by - simp only [periodicOrbit.eq_1, Cycle.coe_eq_nil, List.map_eq_nil, List.range_eq_nil] + simp only [periodicOrbit.eq_1, Cycle.coe_eq_nil, List.map_eq_nil_iff, List.range_eq_nil] exact minimalPeriod_eq_zero_iff_nmem_periodicPts theorem periodicOrbit_eq_nil_of_not_periodic_pt (h : x ∉ periodicPts f) : diff --git a/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean index 0333f199aa230..2b8f40fded2bf 100644 --- a/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean +++ b/Mathlib/Dynamics/TopologicalEntropy/CoverEntropy.lean @@ -19,7 +19,7 @@ A notable choice is that we define the topological entropy of a subset `F` of th Usually, one defines the entropy of an invariant subset `F` as the entropy of the restriction of the transformation to `F`. We avoid the latter definition as it would involve frequent manipulation of subtypes. Our version directly gives a meaning to the topological entropy of a subsystem, and a -single theorem (`subset_restriction_entropy` in `TopologicalEntropy.Morphism`) will give the +single theorem (`subset_restriction_entropy` in `TopologicalEntropy.Semiconj`) will give the equivalence between both versions. Another choice is to give a meaning to the entropy of `∅` (it must be `-∞` to stay coherent) and to @@ -28,11 +28,11 @@ reals `[-∞, +∞]`. The consequence is that we use `ℕ∞`, `ℝ≥0∞` and ## Main definitions - `IsDynCoverOf`: property that dynamical balls centered on a subset `s` cover a subset `F`. -- `coverMincard`: minimal cardinal of a dynamical cover. Takes values in `ℕ∞`. -- `coverEntropyInfEnt`/`coverEntropyEnt`: exponential growth of `coverMincard`. The former is -defined with a `liminf`, the later with a `limsup`. Take values in `EReal`. -- `coverEntropyInf`/`coverEntropy`: supremum of `coverEntropyInfEnt`/`coverEntropyEnt` over -all entourages (or limit as the entourages go to the diagonal). These are Bowen-Dinaburg's +- `coverMincard`: minimal cardinality of a dynamical cover. Takes values in `ℕ∞`. +- `coverEntropyInfEntourage`/`coverEntropyEntourage`: exponential growth of `coverMincard`. +The former is defined with a `liminf`, the later with a `limsup`. Take values in `EReal`. +- `coverEntropyInf`/`coverEntropy`: supremum of `coverEntropyInfEntourage`/`coverEntropyEntourage` +over all entourages (or limit as the entourages go to the diagonal). These are Bowen-Dinaburg's versions of the topological entropy with covers. Take values in `EReal`. ## Implementation notes @@ -46,8 +46,8 @@ using only `coverEntropy`. ## Main results - `IsDynCoverOf.iterate_le_pow`: given a dynamical cover at time `n`, creates dynamical covers at all iterates `n * m` with controlled cardinality. -- `IsDynCoverOf.coverEntropyEnt_le_log_card_div`: upper bound on `coverEntropyEnt` given any -dynamical cover. +- `IsDynCoverOf.coverEntropyEntourage_le_log_card_div`: upper bound on `coverEntropyEntourage` +given any dynamical cover. - `coverEntropyInf_eq_coverEntropy`: equality between the notions of topological entropy defined with a `liminf` and a `limsup`. @@ -56,11 +56,11 @@ cover, entropy ## TODO The most painful part of many manipulations involving topological entropy is going from -`coverMincard` to `coverEntropyInfEnt`/`coverEntropyEnt`. It involves a logarithm, a division, a -`liminf`/`limsup`, and multiple coercions. The best thing to do would be to write a file on -"exponential growth" to make a clean pathway from estimates on `coverMincard` to estimates on -`coverEntropyInf`/`coverEntropy`. It would also be useful in other similar contexts, including the -definition of entropy using nets. +`coverMincard` to `coverEntropyInfEntourage`/`coverEntropyEntourage`. It involves a logarithm, +a division, a `liminf`/`limsup`, and multiple coercions. The best thing to do would be to write +a file on "exponential growth" to make a clean pathway from estimates on `coverMincard` +to estimates on `coverEntropyInf`/`coverEntropy`. It would also be useful +in other similar contexts, including the definition of entropy using nets. Get versions of the topological entropy on (pseudo-e)metric spaces. -/ @@ -133,8 +133,8 @@ lemma IsDynCoverOf.nonempty_inter {T : X → X} {F : Set X} {U : Set (X × X)} { /-- From a dynamical cover `s` with entourage `U` and time `m`, we construct covers with entourage `U ○ U` and any multiple `m * n` of `m` with controlled cardinality. This lemma is the first step in a submultiplicative-like property of `coverMincard`, with consequences such as explicit bounds -for the topological entropy (`coverEntropyInfEnt_le_card_div`) and an equality between two notions -of topological entropy (`coverEntropyInf_eq_coverEntropySup_of_inv`).-/ +for the topological entropy (`coverEntropyInfEntourage_le_card_div`) and an equality between +two notions of topological entropy (`coverEntropyInf_eq_coverEntropySup_of_inv`).-/ lemma IsDynCoverOf.iterate_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {m : ℕ} (n : ℕ) {s : Finset X} (h : IsDynCoverOf T F U m s) : ∃ t : Finset X, IsDynCoverOf T F (U ○ U) (m * n) t ∧ t.card ≤ s.card ^ n := by @@ -234,8 +234,8 @@ lemma exists_isDynCoverOf_of_isCompact_invariant [UniformSpace X] {T : X → X} noncomputable def coverMincard (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : ℕ∞ := ⨅ (s : Finset X) (_ : IsDynCoverOf T F U n s), (s.card : ℕ∞) -lemma coverMincard_le_card {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} {s : Finset X} - (h : IsDynCoverOf T F U n s) : +lemma IsDynCoverOf.coverMincard_le_card {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} + {s : Finset X} (h : IsDynCoverOf T F U n s) : coverMincard T F U n ≤ s.card := iInf₂_le s h lemma coverMincard_monotone_time (T : X → X) (F : Set X) (U : Set (X × X)) : @@ -290,7 +290,7 @@ lemma coverMincard_zero (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X rcases h with ⟨x, _⟩ have := isDynCoverOf_zero T F U (singleton_nonempty x) rw [← Finset.coe_singleton] at this - apply le_of_le_of_eq (coverMincard_le_card this) + apply this.coverMincard_le_card.trans_eq rw [Finset.card_singleton, Nat.cast_one] lemma coverMincard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : @@ -299,7 +299,7 @@ lemma coverMincard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : rcases h with ⟨x, _⟩ have := isDynCoverOf_univ T F n (singleton_nonempty x) rw [← Finset.coe_singleton] at this - apply le_of_le_of_eq (coverMincard_le_card this) + apply this.coverMincard_le_card.trans_eq rw [Finset.card_singleton, Nat.cast_one] lemma coverMincard_mul_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} @@ -310,16 +310,16 @@ lemma coverMincard_mul_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) { rcases n.eq_zero_or_pos with rfl | n_pos · rw [mul_zero, coverMincard_zero T F_nonempty (U ○ U), pow_zero] rcases eq_top_or_lt_top (coverMincard T F U m) with h | h - · exact h ▸ le_of_le_of_eq (le_top (α := ℕ∞)) (ENat.top_pow n_pos).symm + · exact h ▸ (le_top (α := ℕ∞)).trans_eq (ENat.top_pow n_pos).symm · rcases (coverMincard_finite_iff T F U m).1 h with ⟨s, s_cover, s_coverMincard⟩ rcases s_cover.iterate_le_pow F_inv U_symm n with ⟨t, t_cover, t_le_sn⟩ rw [← s_coverMincard] - exact (coverMincard_le_card t_cover).trans (WithTop.coe_le_coe.2 t_le_sn) + exact t_cover.coverMincard_le_card.trans (WithTop.coe_le_coe.2 t_le_sn) lemma coverMincard_le_pow {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {m : ℕ} (m_pos : 0 < m) (n : ℕ) : coverMincard T F (U ○ U) n ≤ coverMincard T F U m ^ (n / m + 1) := - (coverMincard_monotone_time T F (U ○ U) (le_of_lt (Nat.lt_mul_div_succ n m_pos))).trans + (coverMincard_monotone_time T F (U ○ U) (Nat.lt_mul_div_succ n m_pos).le).trans (coverMincard_mul_le_pow F_inv U_symm m (n / m + 1)) lemma coverMincard_finite_of_isCompact_uniformContinuous [UniformSpace X] {T : X → X} @@ -327,13 +327,13 @@ lemma coverMincard_finite_of_isCompact_uniformContinuous [UniformSpace X] {T : X (n : ℕ) : coverMincard T F U n < ⊤ := by rcases exists_isDynCoverOf_of_isCompact_uniformContinuous F_comp h U_uni n with ⟨s, s_cover⟩ - exact (coverMincard_le_card s_cover).trans_lt (WithTop.coe_lt_top s.card) + exact s_cover.coverMincard_le_card.trans_lt (WithTop.coe_lt_top s.card) lemma coverMincard_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} (F_comp : IsCompact F) (F_inv : MapsTo T F F) {U : Set (X × X)} (U_uni : U ∈ 𝓤 X) (n : ℕ) : coverMincard T F U n < ⊤ := by rcases exists_isDynCoverOf_of_isCompact_invariant F_comp F_inv U_uni n with ⟨s, s_cover⟩ - exact (coverMincard_le_card s_cover).trans_lt (WithTop.coe_lt_top s.card) + exact s_cover.coverMincard_le_card.trans_lt (WithTop.coe_lt_top s.card) /-- All dynamical balls of a minimal dynamical cover of `F` intersect `F`. This lemma is the key to relate Bowen-Dinaburg's definition of topological entropy with covers and their definition @@ -356,7 +356,7 @@ lemma nonempty_inter_of_coverMincard {T : X → X} {F : Set X} {U : Set (X × X) rw [← ball_empt] rw [z_x] at hz exact mem_inter y_F hz - apply not_lt_of_le (coverMincard_le_card smaller_cover) + apply smaller_cover.coverMincard_le_card.not_lt rw [← h'] exact_mod_cast Finset.card_erase_lt_of_mem x_s @@ -391,83 +391,82 @@ lemma log_coverMincard_le_add {T : X → X} {F : Set X} (F_inv : MapsTo T F F) have h_nm : (0 : EReal) ≤ (n / m : ℕ) := Nat.cast_nonneg' (n / m) have h_log := log_coverMincard_nonneg T F_nemp U m have n_div_n := EReal.div_self (natCast_ne_bot n) (natCast_ne_top n) - (ne_of_gt (Nat.cast_pos'.2 n_pos)) + (Nat.cast_pos'.2 n_pos).ne.symm apply le_trans <| div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (log_monotone (ENat.toENNReal_le.2 (coverMincard_le_pow F_inv U_symm m_pos n))) rw [ENat.toENNReal_pow, log_pow, Nat.cast_add, Nat.cast_one, right_distrib_of_nonneg h_nm zero_le_one, one_mul, div_right_distrib_of_nonneg (Left.mul_nonneg h_nm h_log) h_log, mul_comm, ← EReal.mul_div, div_eq_mul_inv _ (m : EReal)] apply add_le_add_right (mul_le_mul_of_nonneg_left _ h_log) - apply le_of_le_of_eq <| div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (natCast_div_le n m) + apply (div_le_div_right_of_nonneg (Nat.cast_pos'.2 n_pos).le (natCast_div_le n m)).trans_eq rw [EReal.div_div, mul_comm, ← EReal.div_div, n_div_n, one_div (m : EReal)] /-! ### Cover entropy of entourages -/ open Filter -/-- The entropy of an entourage `U` (`Ent` stands for "entourage"), defined as the exponential rate - of growth of the size of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of - extended real numbers `[-∞, +∞]`. This first version uses a `limsup`, and is chosen as the - default definition.-/ -noncomputable def coverEntropyEnt (T : X → X) (F : Set X) (U : Set (X × X)) := +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size + of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of extended real numbers + `[-∞, +∞]`. This first version uses a `limsup`, and is chosen as the default definition.-/ +noncomputable def coverEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := atTop.limsup fun n : ℕ ↦ log (coverMincard T F U n) / n -/-- The entropy of an entourage `U` (`Ent` stands for "entourage"), defined as the exponential rate - of growth of the size of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of - extended real numbers `[-∞, +∞]`. This second version uses a `liminf`, and is chosen as an - alternative definition.-/ -noncomputable def coverEntropyInfEnt (T : X → X) (F : Set X) (U : Set (X × X)) := +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size + of the smallest `(U, n)`-refined cover of `F`. Takes values in the space of extended real numbers + `[-∞, +∞]`. This second version uses a `liminf`, and is chosen as an alternative definition.-/ +noncomputable def coverEntropyInfEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := atTop.liminf fun n : ℕ ↦ log (coverMincard T F U n) / n -lemma coverEntropyInfEnt_antitone (T : X → X) (F : Set X) : - Antitone (fun U : Set (X × X) ↦ coverEntropyInfEnt T F U) := +lemma coverEntropyInfEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ coverEntropyInfEntourage T F U) := fun _ _ U_V ↦ (liminf_le_liminf) <| Eventually.of_forall fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) <| log_monotone (ENat.toENNReal_mono (coverMincard_antitone T F n U_V)) -lemma coverEntropyEnt_antitone (T : X → X) (F : Set X) : - Antitone (fun U : Set (X × X) ↦ coverEntropyEnt T F U) := +lemma coverEntropyEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ coverEntropyEntourage T F U) := fun _ _ U_V ↦ (limsup_le_limsup) <| Eventually.of_forall fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) <| log_monotone (ENat.toENNReal_mono (coverMincard_antitone T F n U_V)) -lemma coverEntropyInfEnt_le_coverEntropyEnt (T : X → X) (F : Set X) (U : Set (X × X)) : - coverEntropyInfEnt T F U ≤ coverEntropyEnt T F U := liminf_le_limsup +lemma coverEntropyInfEntourage_le_coverEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) : + coverEntropyInfEntourage T F U ≤ coverEntropyEntourage T F U := liminf_le_limsup @[simp] -lemma coverEntropyEnt_empty {T : X → X} {U : Set (X × X)} : - coverEntropyEnt T ∅ U = ⊥ := by +lemma coverEntropyEntourage_empty {T : X → X} {U : Set (X × X)} : + coverEntropyEntourage T ∅ U = ⊥ := by suffices h : ∀ᶠ n : ℕ in atTop, log (coverMincard T ∅ U n) / n = ⊥ by - rw [coverEntropyEnt] + rw [coverEntropyEntourage] exact limsup_congr h ▸ limsup_const ⊥ · simp only [coverMincard_empty, ENat.toENNReal_zero, log_zero, eventually_atTop] exact ⟨1, fun n n_pos ↦ bot_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)⟩ @[simp] -lemma coverEntropyInfEnt_empty {T : X → X} {U : Set (X × X)} : - coverEntropyInfEnt T ∅ U = ⊥ := - eq_bot_mono (coverEntropyInfEnt_le_coverEntropyEnt T ∅ U) coverEntropyEnt_empty +lemma coverEntropyInfEntourage_empty {T : X → X} {U : Set (X × X)} : + coverEntropyInfEntourage T ∅ U = ⊥ := + eq_bot_mono (coverEntropyInfEntourage_le_coverEntropyEntourage T ∅ U) coverEntropyEntourage_empty -lemma coverEntropyInfEnt_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : - 0 ≤ coverEntropyInfEnt T F U := +lemma coverEntropyInfEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ coverEntropyInfEntourage T F U := (le_iInf fun n ↦ div_nonneg (log_coverMincard_nonneg T h U n) (Nat.cast_nonneg' n)).trans iInf_le_liminf -lemma coverEntropyEnt_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : - 0 ≤ coverEntropyEnt T F U := - (coverEntropyInfEnt_nonneg T h U).trans (coverEntropyInfEnt_le_coverEntropyEnt T F U) +lemma coverEntropyEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ coverEntropyEntourage T F U := + (coverEntropyInfEntourage_nonneg T h U).trans + (coverEntropyInfEntourage_le_coverEntropyEntourage T F U) -lemma coverEntropyEnt_univ (T : X → X) {F : Set X} (h : F.Nonempty) : - coverEntropyEnt T F univ = 0 := by - simp [coverEntropyEnt, coverMincard_univ T h] +lemma coverEntropyEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + coverEntropyEntourage T F univ = 0 := by + simp [coverEntropyEntourage, coverMincard_univ T h] -lemma coverEntropyInfEnt_univ (T : X → X) {F : Set X} (h : F.Nonempty) : - coverEntropyInfEnt T F univ = 0 := by - simp [coverEntropyInfEnt, coverMincard_univ T h] +lemma coverEntropyInfEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + coverEntropyInfEntourage T F univ = 0 := by + simp [coverEntropyInfEntourage, coverMincard_univ T h] -lemma coverEntropyEnt_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) +lemma coverEntropyEntourage_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) : - coverEntropyEnt T F (U ○ U) ≤ log (coverMincard T F U n) / n := by + coverEntropyEntourage T F (U ○ U) ≤ log (coverMincard T F U n) / n := by -- Deal with the edge cases: `F = ∅` or `F` has no finite cover. rcases eq_or_ne (log (coverMincard T F U n)) ⊥ with logm_bot | logm_nneg · rw [log_eq_bot_iff, ← ENat.toENNReal_zero, ENat.toENNReal_coe_eq_iff, @@ -487,46 +486,48 @@ lemma coverEntropyEnt_le_log_coverMincard_div {T : X → X} {F : Set X} (F_inv : have := @limsup_add_le_add_limsup ℕ atTop u v rw [h, add_zero] at this specialize this (Or.inr EReal.zero_ne_top) (Or.inr EReal.zero_ne_bot) - exact le_of_le_of_eq this (limsup_const (log (coverMincard T F U n) / n)) + exact this.trans_eq (limsup_const (log (coverMincard T F U n) / n)) exact Tendsto.limsup_eq (EReal.tendsto_const_div_atTop_nhds_zero_nat logm_nneg logm_fin) -lemma IsDynCoverOf.coverEntropyEnt_le_log_card_div {T : X → X} {F : Set X} (F_inv : MapsTo T F F) - {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) {s : Finset X} - (h : IsDynCoverOf T F U n s) : - coverEntropyEnt T F (U ○ U) ≤ log s.card / n := by - apply (coverEntropyEnt_le_log_coverMincard_div F_inv U_symm n_pos).trans +lemma IsDynCoverOf.coverEntropyEntourage_le_log_card_div {T : X → X} {F : Set X} + (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) {n : ℕ} (n_pos : 0 < n) + {s : Finset X} (h : IsDynCoverOf T F U n s) : + coverEntropyEntourage T F (U ○ U) ≤ log s.card / n := by + apply (coverEntropyEntourage_le_log_coverMincard_div F_inv U_symm n_pos).trans apply monotone_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) exact_mod_cast coverMincard_le_card h -lemma coverEntropyEnt_le_coverEntropyInfEnt {T : X → X} {F : Set X} (F_inv : MapsTo T F F) - {U : Set (X × X)} (U_symm : SymmetricRel U) : - coverEntropyEnt T F (U ○ U) ≤ coverEntropyInfEnt T F U := +lemma coverEntropyEntourage_le_coverEntropyInfEntourage {T : X → X} {F : Set X} + (F_inv : MapsTo T F F) {U : Set (X × X)} (U_symm : SymmetricRel U) : + coverEntropyEntourage T F (U ○ U) ≤ coverEntropyInfEntourage T F U := (le_liminf_of_le) (eventually_atTop.2 - ⟨1, fun m m_pos ↦ coverEntropyEnt_le_log_coverMincard_div F_inv U_symm m_pos⟩) + ⟨1, fun m m_pos ↦ coverEntropyEntourage_le_log_coverMincard_div F_inv U_symm m_pos⟩) -lemma coverEntropyEnt_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} +lemma coverEntropyEntourage_finite_of_isCompact_invariant [UniformSpace X] {T : X → X} {F : Set X} (F_comp : IsCompact F) (F_inv : MapsTo T F F) {U : Set (X × X)} (U_uni : U ∈ 𝓤 X) : - coverEntropyEnt T F U < ⊤ := by + coverEntropyEntourage T F U < ⊤ := by rcases comp_symm_mem_uniformity_sets U_uni with ⟨V, V_uni, V_symm, V_U⟩ rcases exists_isDynCoverOf_of_isCompact_invariant F_comp F_inv V_uni 1 with ⟨s, s_cover⟩ - apply (coverEntropyEnt_antitone T F V_U).trans_lt - apply (s_cover.coverEntropyEnt_le_log_card_div F_inv V_symm zero_lt_one).trans_lt + apply (coverEntropyEntourage_antitone T F V_U).trans_lt + apply (s_cover.coverEntropyEntourage_le_log_card_div F_inv V_symm zero_lt_one).trans_lt rw [Nat.cast_one, div_one, log_lt_top_iff, ← ENat.toENNReal_top] exact_mod_cast Ne.lt_top (ENat.coe_ne_top (Finset.card s)) /-! ### Cover entropy -/ -/-- The entropy of `T` restricted to `F`, obtained by taking the supremum over entourages. - Note that this supremum is approached by taking small entourages. This first version uses a - `limsup`, and is chosen as the default definition for topological entropy.-/ +/-- The entropy of `T` restricted to `F`, obtained by taking the supremum + of `coverEntropyEntourage` over entourages. Note that this supremum is approached by taking small + entourages. This first version uses a `limsup`, and is chosen as the default definition + for topological entropy.-/ noncomputable def coverEntropy [UniformSpace X] (T : X → X) (F : Set X) := - ⨆ U ∈ 𝓤 X, coverEntropyEnt T F U + ⨆ U ∈ 𝓤 X, coverEntropyEntourage T F U -/-- The entropy of `T` restricted to `F`, obtained by taking the supremum over entourages. - Note that this supremum is approached by taking small entourages. This second version uses a - `liminf`, and is chosen as an alternative definition for topological entropy.-/ +/-- The entropy of `T` restricted to `F`, obtained by taking the supremum + of `coverEntropyInfEntourage` over entourages. Note that this supremum is approached by taking + small entourages. This second version uses a `liminf`, and is chosen as an alternative + definition for topological entropy.-/ noncomputable def coverEntropyInf [UniformSpace X] (T : X → X) (F : Set X) := - ⨆ U ∈ 𝓤 X, coverEntropyInfEnt T F U + ⨆ U ∈ 𝓤 X, coverEntropyInfEntourage T F U lemma coverEntropyInf_antitone (T : X → X) (F : Set X) : Antitone fun (u : UniformSpace X) ↦ @coverEntropyInf X u T F := @@ -538,49 +539,51 @@ lemma coverEntropy_antitone (T : X → X) (F : Set X) : variable [UniformSpace X] -lemma coverEntropyEnt_le_coverEntropy (T : X → X) (F : Set X) {U : Set (X × X)} (h : U ∈ 𝓤 X) : - coverEntropyEnt T F U ≤ coverEntropy T F := - le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyEnt T F U) U h +lemma coverEntropyEntourage_le_coverEntropy (T : X → X) (F : Set X) {U : Set (X × X)} + (h : U ∈ 𝓤 X) : + coverEntropyEntourage T F U ≤ coverEntropy T F := + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyEntourage T F U) U h -lemma coverEntropyInfEnt_le_coverEntropyInf (T : X → X) (F : Set X) {U : Set (X × X)} +lemma coverEntropyInfEntourage_le_coverEntropyInf (T : X → X) (F : Set X) {U : Set (X × X)} (h : U ∈ 𝓤 X) : - coverEntropyInfEnt T F U ≤ coverEntropyInf T F := - le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEnt T F U) U h + coverEntropyInfEntourage T F U ≤ coverEntropyInf T F := + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEntourage T F U) U h lemma coverEntropy_eq_iSup_basis {ι : Sort*} {p : ι → Prop} {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : - coverEntropy T F = ⨆ (i : ι) (_ : p i), coverEntropyEnt T F (s i) := by + coverEntropy T F = ⨆ (i : ι) (_ : p i), coverEntropyEntourage T F (s i) := by refine (iSup₂_le fun U U_uni ↦ ?_).antisymm (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩) rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ - exact (coverEntropyEnt_antitone T F si_U).trans - (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyEnt T F (s i)) i h_i) + exact (coverEntropyEntourage_antitone T F si_U).trans + (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyEntourage T F (s i)) i h_i) lemma coverEntropyInf_eq_iSup_basis {ι : Sort*} {p : ι → Prop} {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : - coverEntropyInf T F = ⨆ (i : ι) (_ : p i), coverEntropyInfEnt T F (s i) := by + coverEntropyInf T F = ⨆ (i : ι) (_ : p i), coverEntropyInfEntourage T F (s i) := by refine (iSup₂_le fun U U_uni ↦ ?_).antisymm (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩) rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ - exact (coverEntropyInfEnt_antitone T F si_U).trans - (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyInfEnt T F (s i)) i h_i) + exact (coverEntropyInfEntourage_antitone T F si_U).trans + (le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ coverEntropyInfEntourage T F (s i)) i h_i) lemma coverEntropyInf_le_coverEntropy (T : X → X) (F : Set X) : coverEntropyInf T F ≤ coverEntropy T F := - iSup₂_mono fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ coverEntropyInfEnt_le_coverEntropyEnt T F U + iSup₂_mono fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ + coverEntropyInfEntourage_le_coverEntropyEntourage T F U @[simp] lemma coverEntropy_empty {T : X → X} : coverEntropy T ∅ = ⊥ := by - simp only [coverEntropy, coverEntropyEnt_empty, iSup_bot] + simp only [coverEntropy, coverEntropyEntourage_empty, iSup_bot] @[simp] lemma coverEntropyInf_empty {T : X → X} : coverEntropyInf T ∅ = ⊥ := by - simp only [coverEntropyInf, coverEntropyInfEnt_empty, iSup_bot] + simp only [coverEntropyInf, coverEntropyInfEntourage_empty, iSup_bot] lemma coverEntropyInf_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) : 0 ≤ coverEntropyInf T F := - le_of_eq_of_le (coverEntropyInfEnt_univ T h).symm - (coverEntropyInfEnt_le_coverEntropyInf T F univ_mem) + (coverEntropyInfEntourage_le_coverEntropyInf T F univ_mem).trans_eq' + (coverEntropyInfEntourage_univ T h).symm lemma coverEntropy_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) : 0 ≤ coverEntropy T F := @@ -590,7 +593,7 @@ lemma coverEntropyInf_eq_coverEntropy (T : X → X) {F : Set X} (h : MapsTo T F coverEntropyInf T F = coverEntropy T F := by refine le_antisymm (coverEntropyInf_le_coverEntropy T F) (iSup₂_le fun U U_uni ↦ ?_) rcases comp_symm_mem_uniformity_sets U_uni with ⟨V, V_uni, V_symm, V_U⟩ - exact (coverEntropyEnt_antitone T F V_U).trans - (le_iSup₂_of_le V V_uni (coverEntropyEnt_le_coverEntropyInfEnt h V_symm)) + exact (coverEntropyEntourage_antitone T F V_U).trans + (le_iSup₂_of_le V V_uni (coverEntropyEntourage_le_coverEntropyInfEntourage h V_symm)) end Dynamics diff --git a/Mathlib/Dynamics/TopologicalEntropy/DynamicalEntourage.lean b/Mathlib/Dynamics/TopologicalEntropy/DynamicalEntourage.lean index ad6c52b6be339..08b6c75d0d4c0 100644 --- a/Mathlib/Dynamics/TopologicalEntropy/DynamicalEntourage.lean +++ b/Mathlib/Dynamics/TopologicalEntropy/DynamicalEntourage.lean @@ -88,7 +88,7 @@ lemma _root_.isOpen.dynEntourage [TopologicalSpace X] {T : X → X} (T_cont : Co IsOpen (dynEntourage T U n) := by rw [dynEntourage_eq_inter_Ico T U n] refine isOpen_iInter_of_finite fun k ↦ ?_ - exact continuous_def.1 ((T_cont.prod_map T_cont).iterate k) U U_open + exact U_open.preimage ((T_cont.prodMap T_cont).iterate k) lemma dynEntourage_monotone (T : X → X) (n : ℕ) : Monotone (fun U : Set (X × X) ↦ dynEntourage T U n) := diff --git a/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean b/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean new file mode 100644 index 0000000000000..7720c694f1ce9 --- /dev/null +++ b/Mathlib/Dynamics/TopologicalEntropy/NetEntropy.lean @@ -0,0 +1,408 @@ +/- +Copyright (c) 2024 Damien Thomine. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damien Thomine, Pietro Monticone +-/ +import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy + +/-! +# Topological entropy via nets +We implement Bowen-Dinaburg's definitions of the topological entropy, via nets. + +The major design decisions are the same as in `Mathlib.Dynamics.TopologicalEntropy.CoverEntropy`, +and are explained in detail there: use of uniform spaces, definition of the topological entropy of +a subset, and values taken in `EReal`. + +Given a map `T : X → X` and a subset `F ⊆ X`, the topological entropy is loosely defined using +nets as the exponential growth (in `n`) of the number of distinguishable orbits of length `n` +starting from `F`. More precisely, given an entourage `U`, two orbits of length `n` can be +distinguished if there exists some index `k < n` such that `T^[k] x` and `T^[k] y` are far enough +(i.e. `(T^[k] x, T^[k] y)` is not in `U`). The maximal number of distinguishable orbits of +length `n` is `netMaxcard T F U n`, and its exponential growth `netEntropyEntourage T F U`. This +quantity increases when `U` decreases, and a definition of the topological entropy is +`⨆ U ∈ 𝓤 X, netEntropyInfEntourage T F U`. + +The definition of topological entropy using nets coincides with the definition using covers. +Instead of defining a new notion of topological entropy, we prove that +`coverEntropy` coincides with `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. + +## Main definitions +- `IsDynNetIn`: property that dynamical balls centered on a subset `s` of `F` are disjoint. +- `netMaxcard`: maximal cardinality of a dynamical net. Takes values in `ℕ∞`. +- `netEntropyInfEntourage`/`netEntropyEntourage`: exponential growth of `netMaxcard`. The former is +defined with a `liminf`, the latter with a `limsup`. Take values in `EReal`. + +## Implementation notes +As when using covers, there are two competing definitions `netEntropyInfEntourage` and +`netEntropyEntourage` in this file: one uses a `liminf`, the other a `limsup`. When using covers, +we chose the `limsup` definition as the default. + +## Main results +- `coverEntropy_eq_iSup_netEntropyEntourage`: equality between the notions of topological entropy +defined with covers and with nets. Has a variant for `coverEntropyInf`. + +## Tags +net, entropy + +## TODO +Get versions of the topological entropy on (pseudo-e)metric spaces. +-/ + +namespace Dynamics + +open Set Uniformity UniformSpace + +variable {X : Type*} + +/-! ### Dynamical nets -/ + +/-- Given a subset `F`, an entourage `U` and an integer `n`, a subset `s` of `F` is a +`(U, n)`-dynamical net of `F` if no two orbits of length `n` of points in `s` shadow each other.-/ +def IsDynNetIn (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) (s : Set X) : Prop := + s ⊆ F ∧ s.PairwiseDisjoint (fun x : X ↦ ball x (dynEntourage T U n)) + +lemma IsDynNetIn.of_le {T : X → X} {F : Set X} {U : Set (X × X)} {m n : ℕ} (m_n : m ≤ n) {s : Set X} + (h : IsDynNetIn T F U m s) : + IsDynNetIn T F U n s := + ⟨h.1, PairwiseDisjoint.mono h.2 (fun x ↦ ball_mono (dynEntourage_antitone T U m_n) x)⟩ + +lemma IsDynNetIn.of_entourage_subset {T : X → X} {F : Set X} {U V : Set (X × X)} (U_V : U ⊆ V) + {n : ℕ} {s : Set X} (h : IsDynNetIn T F V n s) : + IsDynNetIn T F U n s := + ⟨h.1, PairwiseDisjoint.mono h.2 (fun x ↦ ball_mono (dynEntourage_monotone T n U_V) x)⟩ + +lemma isDynNetIn_empty {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} : + IsDynNetIn T F U n ∅ := + ⟨empty_subset F, pairwise_empty _⟩ + +lemma isDynNetIn_singleton (T : X → X) {F : Set X} (U : Set (X × X)) (n : ℕ) {x : X} (h : x ∈ F) : + IsDynNetIn T F U n {x} := + ⟨singleton_subset_iff.2 h, pairwise_singleton x _⟩ + +/-- Given an entourage `U` and a time `n`, a dynamical net has a smaller cardinality than + a dynamical cover. This lemma is the first of two key results to compare two versions of + topological entropy: with cover and with nets, the second being `coverMincard_le_netMaxcard`.-/ +lemma IsDynNetIn.card_le_card_of_isDynCoverOf {T : X → X} {F : Set X} {U : Set (X × X)} + (U_symm : SymmetricRel U) {n : ℕ} {s t : Finset X} (hs : IsDynNetIn T F U n s) + (ht : IsDynCoverOf T F U n t) : + s.card ≤ t.card := by + have (x : X) (x_s : x ∈ s) : ∃ z ∈ t, x ∈ ball z (dynEntourage T U n) := by + specialize ht (hs.1 x_s) + simp only [Finset.coe_sort_coe, mem_iUnion, Subtype.exists, exists_prop] at ht + exact ht + choose! F s_t using this + simp only [mem_ball_symmetry (U_symm.dynEntourage T n)] at s_t + apply Finset.card_le_card_of_injOn F (fun x x_s ↦ (s_t x x_s).1) + exact fun x x_s y y_s Fx_Fy ↦ + PairwiseDisjoint.elim_set hs.2 x_s y_s (F x) (s_t x x_s).2 (Fx_Fy ▸ (s_t y y_s).2) + +/-! ### Maximal cardinality of dynamical nets -/ + +/-- The largest cardinality of a `(U, n)`-dynamical net of `F`. Takes values in `ℕ∞`, and is +infinite if and only if `F` admits nets of arbitrarily large size.-/ +noncomputable def netMaxcard (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : ℕ∞ := + ⨆ (s : Finset X) (_ : IsDynNetIn T F U n s), (s.card : ℕ∞) + +lemma IsDynNetIn.card_le_netMaxcard {T : X → X} {F : Set X} {U : Set (X × X)} {n : ℕ} {s : Finset X} + (h : IsDynNetIn T F U n s) : + s.card ≤ netMaxcard T F U n := + le_iSup₂ (α := ℕ∞) s h + +lemma netMaxcard_monotone_time (T : X → X) (F : Set X) (U : Set (X × X)) : + Monotone (fun n : ℕ ↦ netMaxcard T F U n) := + fun _ _ m_n ↦ biSup_mono (fun _ h ↦ h.of_le m_n) + +lemma netMaxcard_antitone (T : X → X) (F : Set X) (n : ℕ) : + Antitone (fun U : Set (X × X) ↦ netMaxcard T F U n) := + fun _ _ U_V ↦ biSup_mono (fun _ h ↦ h.of_entourage_subset U_V) + +lemma netMaxcard_finite_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n < ⊤ ↔ + ∃ s : Finset X, IsDynNetIn T F U n s ∧ (s.card : ℕ∞) = netMaxcard T F U n := by + apply Iff.intro <;> intro h + · rcases WithTop.ne_top_iff_exists.1 h.ne with ⟨k, k_max⟩ + rw [← k_max] + simp only [ENat.some_eq_coe, Nat.cast_inj] + -- The criterion we want to use is `Nat.sSup_mem`. We rewrite `netMaxcard` with an `sSup`, + -- then check its `BddAbove` and `Nonempty` hypotheses. + have : netMaxcard T F U n + = sSup (WithTop.some '' (Finset.card '' {s : Finset X | IsDynNetIn T F U n s})) := by + rw [netMaxcard, ← image_comp, sSup_image] + simp only [mem_setOf_eq, ENat.some_eq_coe, Function.comp_apply] + rw [this] at k_max + have h_bdda : BddAbove (Finset.card '' {s : Finset X | IsDynNetIn T F U n s}) := by + refine ⟨k, mem_upperBounds.2 ?_⟩ + simp only [mem_image, mem_setOf_eq, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + intro s h + rw [← WithTop.coe_le_coe, k_max] + apply le_sSup + simp only [ENat.some_eq_coe, mem_image, mem_setOf_eq, Nat.cast_inj, exists_eq_right] + exact Filter.frequently_principal.mp fun a ↦ a h rfl + have h_nemp : (Finset.card '' {s : Finset X | IsDynNetIn T F U n s}).Nonempty := by + refine ⟨0, ?_⟩ + simp only [mem_image, mem_setOf_eq, Finset.card_eq_zero, exists_eq_right, Finset.coe_empty] + exact isDynNetIn_empty + rw [← WithTop.coe_sSup' h_bdda, ENat.some_eq_coe, Nat.cast_inj] at k_max + have key := Nat.sSup_mem h_nemp h_bdda + rw [← k_max, mem_image] at key + simp only [mem_setOf_eq] at key + exact key + · rcases h with ⟨s, _, s_netMaxcard⟩ + rw [← s_netMaxcard] + exact WithTop.coe_lt_top s.card + +@[simp] +lemma netMaxcard_empty {T : X → X} {U : Set (X × X)} {n : ℕ} : netMaxcard T ∅ U n = 0 := by + rw [netMaxcard, ← bot_eq_zero, iSup₂_eq_bot] + intro s s_net + replace s_net := subset_empty_iff.1 s_net.1 + norm_cast at s_net + rw [s_net, Finset.card_empty, CharP.cast_eq_zero, bot_eq_zero'] + +lemma netMaxcard_eq_zero_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n = 0 ↔ F = ∅ := by + refine Iff.intro (fun h ↦ ?_) (fun h ↦ by rw [h, netMaxcard_empty]) + rw [eq_empty_iff_forall_not_mem] + intro x x_F + have key := isDynNetIn_singleton T U n x_F + rw [← Finset.coe_singleton] at key + replace key := key.card_le_netMaxcard + rw [Finset.card_singleton, Nat.cast_one, h] at key + exact key.not_lt zero_lt_one + +lemma one_le_netMaxcard_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + 1 ≤ netMaxcard T F U n ↔ F.Nonempty := by + rw [ENat.one_le_iff_ne_zero, nonempty_iff_ne_empty] + exact not_iff_not.2 (netMaxcard_eq_zero_iff T F U n) + +lemma netMaxcard_zero (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + netMaxcard T F U 0 = 1 := by + apply (iSup₂_le _).antisymm ((one_le_netMaxcard_iff T F U 0).2 h) + intro s ⟨_, s_net⟩ + simp only [ball, dynEntourage_zero, preimage_univ] at s_net + norm_cast + refine Finset.card_le_one.2 (fun x x_s y y_s ↦ ?_) + exact PairwiseDisjoint.elim_set s_net x_s y_s x (mem_univ x) (mem_univ x) + +lemma netMaxcard_univ (T : X → X) {F : Set X} (h : F.Nonempty) (n : ℕ) : + netMaxcard T F univ n = 1 := by + apply (iSup₂_le _).antisymm ((one_le_netMaxcard_iff T F univ n).2 h) + intro s ⟨_, s_net⟩ + simp only [ball, dynEntourage_univ, preimage_univ] at s_net + norm_cast + refine Finset.card_le_one.2 (fun x x_s y y_s ↦ ?_) + exact PairwiseDisjoint.elim_set s_net x_s y_s x (mem_univ x) (mem_univ x) + +lemma netMaxcard_infinite_iff (T : X → X) (F : Set X) (U : Set (X × X)) (n : ℕ) : + netMaxcard T F U n = ⊤ ↔ ∀ k : ℕ, ∃ s : Finset X, IsDynNetIn T F U n s ∧ k ≤ s.card := by + apply Iff.intro <;> intro h + · intro k + rw [netMaxcard, iSup_subtype', iSup_eq_top] at h + specialize h k (ENat.coe_lt_top k) + simp only [Nat.cast_lt, Subtype.exists, exists_prop] at h + rcases h with ⟨s, s_net, s_k⟩ + exact ⟨s, ⟨s_net, s_k.le⟩⟩ + · refine WithTop.forall_gt_iff_eq_top.1 fun k ↦ ?_ + specialize h (k + 1) + rcases h with ⟨s, s_net, s_card⟩ + apply s_net.card_le_netMaxcard.trans_lt' + rw [ENat.some_eq_coe, Nat.cast_lt] + exact (lt_add_one k).trans_le s_card + +lemma netMaxcard_le_coverMincard (T : X → X) (F : Set X) {U : Set (X × X)} (U_symm : SymmetricRel U) + (n : ℕ) : + netMaxcard T F U n ≤ coverMincard T F U n := by + rcases eq_top_or_lt_top (coverMincard T F U n) with h | h + · exact h ▸ le_top + · rcases ((coverMincard_finite_iff T F U n).1 h) with ⟨t, t_cover, t_mincard⟩ + rw [← t_mincard] + exact iSup₂_le (fun s s_net ↦ Nat.cast_le.2 (s_net.card_le_card_of_isDynCoverOf U_symm t_cover)) + +/-- Given an entourage `U` and a time `n`, a minimal dynamical cover by `U ○ U` has a smaller + cardinality than a maximal dynamical net by `U`. This lemma is the second of two key results to + compare two versions topological entropy: with cover and with nets.-/ +lemma coverMincard_le_netMaxcard (T : X → X) (F : Set X) {U : Set (X × X)} (U_rfl : idRel ⊆ U) + (U_symm : SymmetricRel U) (n : ℕ) : + coverMincard T F (U ○ U) n ≤ netMaxcard T F U n := by + classical + -- WLOG, there exists a maximal dynamical net `s`. + rcases (eq_top_or_lt_top (netMaxcard T F U n)) with h | h + · exact h ▸ le_top + rcases ((netMaxcard_finite_iff T F U n).1 h) with ⟨s, s_net, s_netMaxcard⟩ + rw [← s_netMaxcard] + apply IsDynCoverOf.coverMincard_le_card + -- We have to check that `s` is a cover for `dynEntourage T F (U ○ U) n`. + -- If `s` is not a cover, then we can add to `s` a point `x` which is not covered + -- and get a new net. This contradicts the maximality of `s`. + by_contra h + rcases not_subset.1 h with ⟨x, x_F, x_uncov⟩ + simp only [Finset.mem_coe, mem_iUnion, exists_prop, not_exists, not_and] at x_uncov + have larger_net : IsDynNetIn T F U n (insert x s) := + And.intro (insert_subset x_F s_net.1) (pairwiseDisjoint_insert.2 (And.intro s_net.2 + (fun y y_s _ ↦ (disjoint_left.2 (fun z z_x z_y ↦ x_uncov y y_s + (mem_ball_dynEntourage_comp T n U_symm x y (nonempty_of_mem ⟨z_x, z_y⟩))))))) + rw [← Finset.coe_insert x s] at larger_net + apply larger_net.card_le_netMaxcard.not_lt + rw [← s_netMaxcard, Nat.cast_lt] + refine (lt_add_one s.card).trans_eq (Finset.card_insert_of_not_mem fun x_s ↦ ?_).symm + apply x_uncov x x_s (ball_mono (dynEntourage_monotone T n (subset_comp_self U_rfl)) x + (ball_mono (idRel_subset_dynEntourage T U_rfl n) x _)) + simp only [ball, mem_preimage, mem_idRel] + +open ENNReal EReal + +lemma log_netMaxcard_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) (n : ℕ) : + 0 ≤ log (netMaxcard T F U n) := by + apply zero_le_log_iff.2 + rw [← ENat.toENNReal_one, ENat.toENNReal_le] + exact (one_le_netMaxcard_iff T F U n).2 h + +/-! ### Net entropy of entourages -/ + +open Filter + +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size of the +largest `(U, n)`-dynamical net of `F`. Takes values in the space of extended real numbers +`[-∞,+∞]`. This version uses a `limsup`, and is chosen as the default definition.-/ +noncomputable def netEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := + atTop.limsup fun n : ℕ ↦ log (netMaxcard T F U n) / n + +/-- The entropy of an entourage `U`, defined as the exponential rate of growth of the size of the +largest `(U, n)`-dynamical net of `F`. Takes values in the space of extended real numbers +`[-∞,+∞]`. This version uses a `liminf`, and is an alternative definition.-/ +noncomputable def netEntropyInfEntourage (T : X → X) (F : Set X) (U : Set (X × X)) := + atTop.liminf fun n : ℕ ↦ log (netMaxcard T F U n) / n + +lemma netEntropyInfEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ netEntropyInfEntourage T F U) := + fun _ _ U_V ↦ (liminf_le_liminf) (Eventually.of_forall + fun n ↦ monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (netMaxcard_antitone T F n U_V)))) + +lemma netEntropyEntourage_antitone (T : X → X) (F : Set X) : + Antitone (fun U : Set (X × X) ↦ netEntropyEntourage T F U) := + fun _ _ U_V ↦ (limsup_le_limsup) (Eventually.of_forall + fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (netMaxcard_antitone T F n U_V))))) + +lemma netEntropyInfEntourage_le_netEntropyEntourage (T : X → X) (F : Set X) (U : Set (X × X)) : + netEntropyInfEntourage T F U ≤ netEntropyEntourage T F U := liminf_le_limsup + +@[simp] +lemma netEntropyEntourage_empty {T : X → X} {U : Set (X × X)} : netEntropyEntourage T ∅ U = ⊥ := by + suffices h : ∀ᶠ n : ℕ in atTop, log (netMaxcard T ∅ U n) / n = ⊥ by + rw [netEntropyEntourage, limsup_congr h] + exact limsup_const ⊥ + simp only [netMaxcard_empty, ENat.toENNReal_zero, log_zero, eventually_atTop] + exact ⟨1, fun n n_pos ↦ bot_div_of_pos_ne_top (Nat.cast_pos'.2 n_pos) (natCast_ne_top n)⟩ + +@[simp] +lemma netEntropyInfEntourage_empty {T : X → X} {U : Set (X × X)} : + netEntropyInfEntourage T ∅ U = ⊥ := + eq_bot_mono (netEntropyInfEntourage_le_netEntropyEntourage T ∅ U) netEntropyEntourage_empty + +lemma netEntropyInfEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ netEntropyInfEntourage T F U := + (le_iInf fun n ↦ div_nonneg (log_netMaxcard_nonneg T h U n) (Nat.cast_nonneg' n)).trans + iInf_le_liminf + +lemma netEntropyEntourage_nonneg (T : X → X) {F : Set X} (h : F.Nonempty) (U : Set (X × X)) : + 0 ≤ netEntropyEntourage T F U := + (netEntropyInfEntourage_nonneg T h U).trans (netEntropyInfEntourage_le_netEntropyEntourage T F U) + +lemma netEntropyInfEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + netEntropyInfEntourage T F univ = 0 := by simp [netEntropyInfEntourage, netMaxcard_univ T h] + +lemma netEntropyEntourage_univ (T : X → X) {F : Set X} (h : F.Nonempty) : + netEntropyEntourage T F univ = 0 := by simp [netEntropyEntourage, netMaxcard_univ T h] + +lemma netEntropyInfEntourage_le_coverEntropyInfEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_symm : SymmetricRel U) : + netEntropyInfEntourage T F U ≤ coverEntropyInfEntourage T F U := + (liminf_le_liminf) (Eventually.of_forall fun n ↦ (div_le_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_le.2 (netMaxcard_le_coverMincard T F U_symm n))))) + +lemma coverEntropyInfEntourage_le_netEntropyInfEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_rfl : idRel ⊆ U) (U_symm : SymmetricRel U) : + coverEntropyInfEntourage T F (U ○ U) ≤ netEntropyInfEntourage T F U := by + refine (liminf_le_liminf) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (coverMincard_le_netMaxcard T F U_rfl U_symm n) + +lemma netEntropyEntourage_le_coverEntropyEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_symm : SymmetricRel U) : + netEntropyEntourage T F U ≤ coverEntropyEntourage T F U := by + refine (limsup_le_limsup) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (netMaxcard_le_coverMincard T F U_symm n) + +lemma coverEntropyEntourage_le_netEntropyEntourage (T : X → X) (F : Set X) {U : Set (X × X)} + (U_rfl : idRel ⊆ U) (U_symm : SymmetricRel U) : + coverEntropyEntourage T F (U ○ U) ≤ netEntropyEntourage T F U := by + refine (limsup_le_limsup) (Eventually.of_forall fun n ↦ ?_) + apply div_le_div_right_of_nonneg (Nat.cast_nonneg' n) (log_monotone _) + exact ENat.toENNReal_le.2 (coverMincard_le_netMaxcard T F U_rfl U_symm n) + +/-! ### Relationship with entropy via covers -/ + +variable [UniformSpace X] (T : X → X) (F : Set X) + +/-- Bowen-Dinaburg's definition of topological entropy using nets is + `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. This quantity is the same as the topological entropy using + covers, so there is no need to define a new notion of topological entropy. This version of the + theorem relates the `liminf` versions of topological entropy.-/ +theorem coverEntropyInf_eq_iSup_netEntropyInfEntourage : + coverEntropyInf T F = ⨆ U ∈ 𝓤 X, netEntropyInfEntourage T F U := by + apply le_antisymm <;> refine iSup₂_le fun U U_uni ↦ ?_ + · rcases (comp_symm_mem_uniformity_sets U_uni) with ⟨V, V_uni, V_symm, V_comp_U⟩ + apply (coverEntropyInfEntourage_antitone T F V_comp_U).trans (le_iSup₂_of_le V V_uni _) + exact coverEntropyInfEntourage_le_netEntropyInfEntourage T F (refl_le_uniformity V_uni) V_symm + · apply (netEntropyInfEntourage_antitone T F (symmetrizeRel_subset_self U)).trans + apply (le_iSup₂ (symmetrizeRel U) (symmetrize_mem_uniformity U_uni)).trans' + exact netEntropyInfEntourage_le_coverEntropyInfEntourage T F (symmetric_symmetrizeRel U) + +/-- Bowen-Dinaburg's definition of topological entropy using nets is + `⨆ U ∈ 𝓤 X, netEntropyEntourage T F U`. This quantity is the same as the topological entropy using + covers, so there is no need to define a new notion of topological entropy. This version of the + theorem relates the `limsup` versions of topological entropy.-/ +theorem coverEntropy_eq_iSup_netEntropyEntourage : + coverEntropy T F = ⨆ U ∈ 𝓤 X, netEntropyEntourage T F U := by + apply le_antisymm <;> refine iSup₂_le fun U U_uni ↦ ?_ + · rcases (comp_symm_mem_uniformity_sets U_uni) with ⟨V, V_uni, V_symm, V_comp_U⟩ + apply (coverEntropyEntourage_antitone T F V_comp_U).trans (le_iSup₂_of_le V V_uni _) + exact coverEntropyEntourage_le_netEntropyEntourage T F (refl_le_uniformity V_uni) V_symm + · apply (netEntropyEntourage_antitone T F (symmetrizeRel_subset_self U)).trans + apply (le_iSup₂ (symmetrizeRel U) (symmetrize_mem_uniformity U_uni)).trans' + exact netEntropyEntourage_le_coverEntropyEntourage T F (symmetric_symmetrizeRel U) + +lemma coverEntropyInf_eq_iSup_basis_netEntropyInfEntourage {ι : Sort*} {p : ι → Prop} + {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : + coverEntropyInf T F = ⨆ (i : ι) (_ : p i), netEntropyInfEntourage T F (s i) := by + rw [coverEntropyInf_eq_iSup_netEntropyInfEntourage T F] + apply (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩).antisymm' + refine iSup₂_le fun U U_uni ↦ ?_ + rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ + apply (netEntropyInfEntourage_antitone T F si_U).trans + exact le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ netEntropyInfEntourage T F (s i)) i h_i + +lemma coverEntropy_eq_iSup_basis_netEntropyEntourage {ι : Sort*} {p : ι → Prop} + {s : ι → Set (X × X)} (h : (𝓤 X).HasBasis p s) (T : X → X) (F : Set X) : + coverEntropy T F = ⨆ (i : ι) (_ : p i), netEntropyEntourage T F (s i) := by + rw [coverEntropy_eq_iSup_netEntropyEntourage T F] + apply (iSup₂_mono' fun i h_i ↦ ⟨s i, HasBasis.mem_of_mem h h_i, le_refl _⟩).antisymm' + refine iSup₂_le fun U U_uni ↦ ?_ + rcases (HasBasis.mem_iff h).1 U_uni with ⟨i, h_i, si_U⟩ + apply (netEntropyEntourage_antitone T F si_U).trans _ + exact le_iSup₂ (f := fun (i : ι) (_ : p i) ↦ netEntropyEntourage T F (s i)) i h_i + +lemma netEntropyInfEntourage_le_coverEntropyInf {U : Set (X × X)} (h : U ∈ 𝓤 X) : + netEntropyInfEntourage T F U ≤ coverEntropyInf T F := + coverEntropyInf_eq_iSup_netEntropyInfEntourage T F ▸ + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ netEntropyInfEntourage T F U) U h + +lemma netEntropyEntourage_le_coverEntropy {U : Set (X × X)} (h : U ∈ 𝓤 X) : + netEntropyEntourage T F U ≤ coverEntropy T F := + coverEntropy_eq_iSup_netEntropyEntourage T F ▸ + le_iSup₂ (f := fun (U : Set (X × X)) (_ : U ∈ 𝓤 X) ↦ netEntropyEntourage T F U) U h + +end Dynamics diff --git a/Mathlib/Dynamics/TopologicalEntropy/Semiconj.lean b/Mathlib/Dynamics/TopologicalEntropy/Semiconj.lean new file mode 100644 index 0000000000000..66d3c3288216b --- /dev/null +++ b/Mathlib/Dynamics/TopologicalEntropy/Semiconj.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2024 Damien Thomine. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damien Thomine, Pietro Monticone +-/ +import Mathlib.Dynamics.TopologicalEntropy.CoverEntropy + +/-! +# Topological entropy of the image of a set under a semiconjugacy +Consider two dynamical systems `(X, S)` and `(Y, T)` together with a semiconjugacy `φ`: + + +``` +X ---S--> X +| | +φ φ +| | +v v +Y ---T--> Y +``` + +We relate the topological entropy of a subset `F ⊆ X` with the topological entropy +of its image `φ '' F ⊆ Y`. + +The best-known theorem is that, if all maps are uniformly continuous, then +`coverEntropy T (φ '' F) ≤ coverEntropy S F`. This is theorem +`coverEntropy_image_le_of_uniformContinuous` herein. We actually prove the much more general +statement that `coverEntropy T (φ '' F) = coverEntropy S F` if `X` is endowed with the pullback +by `φ` of the uniform structure of `Y`. + +This more general statement has another direct consequence: if `F` is `S`-invariant, then the +topological entropy of the restriction of `S` to `F` is exactly `coverEntropy S F`. This +corollary is essential: in most references, the entropy of an invariant subset (or subsystem) `F` is +defined as the entropy of the restriction to `F` of the system. We chose instead to give a direct +definition of the topological entropy of a subset, so as to avoid working with subtypes. Theorem +`coverEntropy_restrict` shows that this choice is coherent with the literature. + +## Implementation notes +We use only the definition of the topological entropy using covers; the simplest version of +`IsDynCoverOf.image` for nets fails. + +## Main results +- `coverEntropy_image_of_comap`/`coverEntropyInf_image_of_comap`: the entropy of `φ '' F` equals +the entropy of `F` if `X` is endowed with the pullback by `φ` of the uniform structure of `Y`. +- `coverEntropy_image_le_of_uniformContinuous`/`coverEntropyInf_image_le_of_uniformContinuous`: +the entropy of `φ '' F` is lower than the entropy of `F` if `φ` is uniformly continuous. +- `coverEntropy_restrict`: the entropy of the restriction of `S` to an invariant set `F` is +`coverEntropy S F`. + +## Tags +entropy, semiconjugacy +-/ + +namespace Dynamics + +open Function Prod Set Uniformity UniformSpace + +variable {X Y : Type*} {S : X → X} {T : Y → Y} {φ : X → Y} + +lemma IsDynCoverOf.image (h : Semiconj φ S T) {F : Set X} {V : Set (Y × Y)} {n : ℕ} {s : Set X} + (h' : IsDynCoverOf S F ((map φ φ) ⁻¹' V) n s) : + IsDynCoverOf T (φ '' F) V n (φ '' s) := by + simp only [IsDynCoverOf, image_subset_iff, preimage_iUnion₂, biUnion_image] + refine h'.trans (iUnion₂_mono fun i _ ↦ subset_of_eq ?_) + rw [← h.preimage_dynEntourage V n, ball_preimage] + +lemma IsDynCoverOf.preimage (h : Semiconj φ S T) {F : Set X} {V : Set (Y × Y)} + (V_symm : SymmetricRel V) {n : ℕ} {t : Finset Y} (h' : IsDynCoverOf T (φ '' F) V n t) : + ∃ s : Finset X, IsDynCoverOf S F ((map φ φ) ⁻¹' (V ○ V)) n s ∧ s.card ≤ t.card := by + classical + rcases isEmpty_or_nonempty X with _ | _ + · exact ⟨∅, eq_empty_of_isEmpty F ▸ ⟨isDynCoverOf_empty, Finset.card_empty ▸ zero_le t.card⟩⟩ + -- If `t` is a dynamical cover of `φ '' F`, then we want to choose one preimage by `φ` for each + -- element of `t`. This is complicated by the fact that `t` may not be a subset of `φ '' F`, + -- and may not even be in the range of `φ`. Hence, we first modify `t` to make it a subset + -- of `φ '' F`. This requires taking larger entourages. + rcases h'.nonempty_inter with ⟨s, s_cover, s_card, s_inter⟩ + choose! g gs_cover using fun (x : Y) (h : x ∈ s) ↦ nonempty_def.1 (s_inter x h) + choose! f f_section using fun (y : Y) (a : y ∈ φ '' F) ↦ a + refine ⟨s.image (f ∘ g), And.intro ?_ (Finset.card_image_le.trans s_card)⟩ + simp only [IsDynCoverOf, Finset.mem_coe, image_subset_iff, preimage_iUnion₂] at s_cover ⊢ + apply s_cover.trans + rw [← h.preimage_dynEntourage (V ○ V) n, Finset.set_biUnion_finset_image] + refine iUnion₂_mono fun i i_s ↦ ?_ + rw [comp_apply, ball_preimage, (f_section (g i) (gs_cover i i_s).2).2] + refine preimage_mono fun x x_i ↦ mem_ball_dynEntourage_comp T n V_symm x (g i) ⟨i, ?_⟩ + replace gs_cover := (gs_cover i i_s).1 + rw [mem_ball_symmetry (V_symm.dynEntourage T n)] at x_i gs_cover + exact ⟨x_i, gs_cover⟩ + +lemma le_coverMincard_image (h : Semiconj φ S T) (F : Set X) {V : Set (Y × Y)} + (V_symm : SymmetricRel V) (n : ℕ) : + coverMincard S F ((map φ φ) ⁻¹' (V ○ V)) n ≤ coverMincard T (φ '' F) V n := by + rcases eq_top_or_lt_top (coverMincard T (φ '' F) V n) with h' | h' + · exact h' ▸ le_top + rcases (coverMincard_finite_iff T (φ '' F) V n).1 h' with ⟨t, t_cover, t_card⟩ + rcases t_cover.preimage h V_symm with ⟨s, s_cover, s_card⟩ + rw [← t_card] + exact s_cover.coverMincard_le_card.trans (WithTop.coe_le_coe.2 s_card) + +lemma coverMincard_image_le (h : Semiconj φ S T) (F : Set X) (V : Set (Y × Y)) (n : ℕ) : + coverMincard T (φ '' F) V n ≤ coverMincard S F ((map φ φ) ⁻¹' V) n := by + classical + rcases eq_top_or_lt_top (coverMincard S F ((map φ φ) ⁻¹' V) n) with h' | h' + · exact h' ▸ le_top + rcases (coverMincard_finite_iff S F ((map φ φ) ⁻¹' V) n).1 h' with ⟨s, s_cover, s_card⟩ + rw [← s_card] + have := s_cover.image h + rw [← s.coe_image] at this + exact this.coverMincard_le_card.trans (WithTop.coe_le_coe.2 s.card_image_le) + +open ENNReal EReal Filter + +lemma le_coverEntropyEntourage_image (h : Semiconj φ S T) (F : Set X) {V : Set (Y × Y)} + (V_symm : SymmetricRel V) : + coverEntropyEntourage S F ((map φ φ) ⁻¹' (V ○ V)) ≤ coverEntropyEntourage T (φ '' F) V := + limsup_le_limsup (Eventually.of_forall fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (le_coverMincard_image h F V_symm n))))) + +lemma le_coverEntropyInfEntourage_image (h : Semiconj φ S T) (F : Set X) {V : Set (Y × Y)} + (V_symm : SymmetricRel V) : + coverEntropyInfEntourage S F ((map φ φ) ⁻¹' (V ○ V)) ≤ coverEntropyInfEntourage T (φ '' F) V := + liminf_le_liminf (Eventually.of_forall fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (le_coverMincard_image h F V_symm n))))) + +lemma coverEntropyEntourage_image_le (h : Semiconj φ S T) (F : Set X) (V : Set (Y × Y)) : + coverEntropyEntourage T (φ '' F) V ≤ coverEntropyEntourage S F ((map φ φ) ⁻¹' V) := + limsup_le_limsup (Eventually.of_forall fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (coverMincard_image_le h F V n))))) + +lemma coverEntropyInfEntourage_image_le (h : Semiconj φ S T) (F : Set X) (V : Set (Y × Y)) : + coverEntropyInfEntourage T (φ '' F) V ≤ coverEntropyInfEntourage S F ((map φ φ) ⁻¹' V) := + liminf_le_liminf (Eventually.of_forall fun n ↦ (monotone_div_right_of_nonneg (Nat.cast_nonneg' n) + (log_monotone (ENat.toENNReal_mono (coverMincard_image_le h F V n))))) + +/-- The entropy of `φ '' F` equals the entropy of `F` if `X` is endowed with the pullback by `φ` + of the uniform structure of `Y`.-/ +theorem coverEntropy_image_of_comap (u : UniformSpace Y) {S : X → X} {T : Y → Y} {φ : X → Y} + (h : Semiconj φ S T) (F : Set X) : + coverEntropy T (φ '' F) = @coverEntropy X (comap φ u) S F := by + apply le_antisymm + · refine iSup₂_le fun V V_uni ↦ (coverEntropyEntourage_image_le h F V).trans ?_ + apply @coverEntropyEntourage_le_coverEntropy X (comap φ u) S F + rw [uniformity_comap φ, mem_comap] + exact ⟨V, V_uni, Subset.rfl⟩ + · refine iSup₂_le fun U U_uni ↦ ?_ + simp only [uniformity_comap φ, mem_comap] at U_uni + rcases U_uni with ⟨V, V_uni, V_sub⟩ + rcases comp_symm_mem_uniformity_sets V_uni with ⟨W, W_uni, W_symm, W_V⟩ + apply (coverEntropyEntourage_antitone S F ((preimage_mono W_V).trans V_sub)).trans + apply (le_coverEntropyEntourage_image h F W_symm).trans + exact coverEntropyEntourage_le_coverEntropy T (φ '' F) W_uni + +/-- The entropy of `φ '' F` equals the entropy of `F` if `X` is endowed with the pullback by `φ` + of the uniform structure of `Y`. This version uses a `liminf`.-/ +theorem coverEntropyInf_image_of_comap (u : UniformSpace Y) {S : X → X} {T : Y → Y} {φ : X → Y} + (h : Semiconj φ S T) (F : Set X) : + coverEntropyInf T (φ '' F) = @coverEntropyInf X (comap φ u) S F := by + apply le_antisymm + · refine iSup₂_le fun V V_uni ↦ (coverEntropyInfEntourage_image_le h F V).trans ?_ + apply @coverEntropyInfEntourage_le_coverEntropyInf X (comap φ u) S F + rw [uniformity_comap φ, mem_comap] + exact ⟨V, V_uni, Subset.rfl⟩ + · refine iSup₂_le fun U U_uni ↦ ?_ + simp only [uniformity_comap φ, mem_comap] at U_uni + rcases U_uni with ⟨V, V_uni, V_sub⟩ + rcases comp_symm_mem_uniformity_sets V_uni with ⟨W, W_uni, W_symm, W_V⟩ + apply (coverEntropyInfEntourage_antitone S F ((preimage_mono W_V).trans V_sub)).trans + apply (le_coverEntropyInfEntourage_image h F W_symm).trans + exact coverEntropyInfEntourage_le_coverEntropyInf T (φ '' F) W_uni + +open Subtype + +lemma coverEntropy_restrict_subset [UniformSpace X] {T : X → X} {F G : Set X} (hF : F ⊆ G) + (hG : MapsTo T G G) : + coverEntropy (hG.restrict T G G) (val ⁻¹' F) = coverEntropy T F := by + rw [← coverEntropy_image_of_comap _ hG.val_restrict_apply (val ⁻¹' F), image_preimage_coe G F, + inter_eq_right.2 hF] + +lemma coverEntropyInf_restrict_subset [UniformSpace X] {T : X → X} {F G : Set X} (hF : F ⊆ G) + (hG : MapsTo T G G) : + coverEntropyInf (hG.restrict T G G) (val ⁻¹' F) = coverEntropyInf T F := by + rw [← coverEntropyInf_image_of_comap _ hG.val_restrict_apply (val ⁻¹' F), image_preimage_coe G F, + inter_eq_right.2 hF] + +/-- The entropy of the restriction of `T` to an invariant set `F` is `coverEntropy S F`. This +theorem justifies our definition of `coverEntropy T F`.-/ +theorem coverEntropy_restrict [UniformSpace X] {T : X → X} {F : Set X} (h : MapsTo T F F) : + coverEntropy (h.restrict T F F) univ = coverEntropy T F := by + rw [← coverEntropy_restrict_subset Subset.rfl h, coe_preimage_self F] + +/-- The entropy of `φ '' F` is lower than entropy of `F` if `φ` is uniformly continuous.-/ +theorem coverEntropy_image_le_of_uniformContinuous [UniformSpace X] [UniformSpace Y] {S : X → X} + {T : Y → Y} {φ : X → Y} (h : Semiconj φ S T) (h' : UniformContinuous φ) (F : Set X) : + coverEntropy T (φ '' F) ≤ coverEntropy S F := by + rw [coverEntropy_image_of_comap _ h F] + exact coverEntropy_antitone S F (uniformContinuous_iff.1 h') + +/-- The entropy of `φ '' F` is lower than entropy of `F` if `φ` is uniformly continuous. This + version uses a `liminf`.-/ +theorem coverEntropyInf_image_le_of_uniformContinuous [UniformSpace X] [UniformSpace Y] {S : X → X} + {T : Y → Y} {φ : X → Y} (h : Semiconj φ S T) (h' : UniformContinuous φ) (F : Set X) : + coverEntropyInf T (φ '' F) ≤ coverEntropyInf S F := by + rw [coverEntropyInf_image_of_comap _ h F] + exact coverEntropyInf_antitone S F (uniformContinuous_iff.1 h') + +lemma coverEntropy_image_le_of_uniformContinuousOn_invariant [UniformSpace X] [UniformSpace Y] + {S : X → X} {T : Y → Y} {φ : X → Y} (h : Semiconj φ S T) {F G : Set X} + (h' : UniformContinuousOn φ G) (hF : F ⊆ G) (hG : MapsTo S G G) : + coverEntropy T (φ '' F) ≤ coverEntropy S F := by + rw [← coverEntropy_restrict_subset hF hG] + have hφ : Semiconj (G.restrict φ) (hG.restrict S G G) T := by + intro x + rw [G.restrict_apply, G.restrict_apply, hG.val_restrict_apply, h.eq x] + apply (coverEntropy_image_le_of_uniformContinuous hφ + (uniformContinuousOn_iff_restrict.1 h') (val ⁻¹' F)).trans_eq' + rw [← image_image_val_eq_restrict_image, image_preimage_coe G F, inter_eq_right.2 hF] + +lemma coverEntropyInf_image_le_of_uniformContinuousOn_invariant [UniformSpace X] [UniformSpace Y] + {S : X → X} {T : Y → Y} {φ : X → Y} (h : Semiconj φ S T) {F G : Set X} + (h' : UniformContinuousOn φ G) (hF : F ⊆ G) (hG : MapsTo S G G) : + coverEntropyInf T (φ '' F) ≤ coverEntropyInf S F := by + rw [← coverEntropyInf_restrict_subset hF hG] + have hφ : Semiconj (G.restrict φ) (hG.restrict S G G) T := by + intro a + rw [G.restrict_apply, G.restrict_apply, hG.val_restrict_apply, h.eq a] + apply (coverEntropyInf_image_le_of_uniformContinuous hφ + (uniformContinuousOn_iff_restrict.1 h') (val ⁻¹' F)).trans_eq' + rw [← image_image_val_eq_restrict_image, image_preimage_coe G F, inter_eq_right.2 hF] + +end Dynamics diff --git a/Mathlib/FieldTheory/Adjoin.lean b/Mathlib/FieldTheory/Adjoin.lean index 07881787d2645..c83073349810a 100644 --- a/Mathlib/FieldTheory/Adjoin.lean +++ b/Mathlib/FieldTheory/Adjoin.lean @@ -28,7 +28,7 @@ For example, `Algebra.adjoin K {x}` might not include `x⁻¹`. - `F⟮α⟯`: adjoin a single element `α` to `F` (in scope `IntermediateField`). -/ -open FiniteDimensional Polynomial +open Module Polynomial namespace IntermediateField @@ -872,7 +872,7 @@ theorem adjoin_natCast (n : ℕ) : F⟮(n : E)⟯ = ⊥ := section AdjoinRank -open FiniteDimensional Module +open Module Module variable {K L : IntermediateField F E} @@ -1043,7 +1043,7 @@ theorem isAlgebraic_adjoin_simple {x : L} (hx : IsIntegral K x) : Algebra.IsAlge have := adjoin.finiteDimensional hx; Algebra.IsAlgebraic.of_finite K K⟮x⟯ theorem adjoin.finrank {x : L} (hx : IsIntegral K x) : - FiniteDimensional.finrank K K⟮x⟯ = (minpoly K x).natDegree := by + Module.finrank K K⟮x⟯ = (minpoly K x).natDegree := by rw [PowerBasis.finrank (adjoin.powerBasis hx : _)] rfl @@ -1114,6 +1114,14 @@ theorem _root_.minpoly.degree_le (x : L) [FiniteDimensional K L] : (minpoly K x).degree ≤ finrank K L := degree_le_of_natDegree_le (minpoly.natDegree_le x) +/-- If `x : L` is an integral element in a field extension `L` over `K`, then the degree of the + minimal polynomial of `x` over `K` divides `[L : K]`.-/ +theorem _root_.minpoly.degree_dvd {x : L} (hx : IsIntegral K x) : + (minpoly K x).natDegree ∣ finrank K L := by + rw [dvd_iff_exists_eq_mul_left, ← IntermediateField.adjoin.finrank hx] + use finrank K⟮x⟯ L + rw [mul_comm, finrank_mul_finrank] + -- TODO: generalize to `Sort` /-- A compositum of algebraic extensions is algebraic -/ theorem isAlgebraic_iSup {ι : Type*} {t : ι → IntermediateField K L} @@ -1169,7 +1177,7 @@ theorem card_algHom_adjoin_integral (h : IsIntegral F α) (h_sep : IsSeparable F exact h_sep -- Apparently `K⟮root f⟯ →+* K⟮root f⟯` is expensive to unify during instance synthesis. -open FiniteDimensional AdjoinRoot in +open Module 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) @@ -1217,7 +1225,7 @@ theorem _root_.Polynomial.irreducible_comp {f g : K[X]} (hfm : f.Monic) (hgm : g rw [← finrank_top', ← this, adjoin.finrank] exact IsIntegral.of_finite _ _ · simp [← key₂] - have := FiniteDimensional.finrank_mul_finrank K K⟮aeval (root p) g⟯ Kx + have := Module.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 diff --git a/Mathlib/FieldTheory/Cardinality.lean b/Mathlib/FieldTheory/Cardinality.lean index 8a0482682912f..045db9322dcbf 100644 --- a/Mathlib/FieldTheory/Cardinality.lean +++ b/Mathlib/FieldTheory/Cardinality.lean @@ -43,8 +43,8 @@ theorem Fintype.isPrimePow_card_of_field {α} [Fintype α] [Field α] : IsPrimeP let b := IsNoetherian.finsetBasis (ZMod p) α rw [Module.card_fintype b, ZMod.card, isPrimePow_pow_iff] · exact hp.1.isPrimePow - rw [← FiniteDimensional.finrank_eq_card_basis b] - exact FiniteDimensional.finrank_pos.ne' + rw [← Module.finrank_eq_card_basis b] + exact Module.finrank_pos.ne' /-- A `Fintype` can be given a field structure iff its cardinality is a prime power. -/ theorem Fintype.nonempty_field_iff {α} [Fintype α] : Nonempty (Field α) ↔ IsPrimePow ‖α‖ := by diff --git a/Mathlib/FieldTheory/Finite/Basic.lean b/Mathlib/FieldTheory/Finite/Basic.lean index 6b5c4835a87c6..715387ba0669b 100644 --- a/Mathlib/FieldTheory/Finite/Basic.lean +++ b/Mathlib/FieldTheory/Finite/Basic.lean @@ -455,9 +455,9 @@ variable {V : Type*} [Fintype K] [DivisionRing K] [AddCommGroup V] [Module K V] -- should this go in a namespace? -- finite_dimensional would be natural, -- but we don't assume it... -theorem card_eq_pow_finrank [Fintype V] : Fintype.card V = q ^ FiniteDimensional.finrank K V := by +theorem card_eq_pow_finrank [Fintype V] : Fintype.card V = q ^ Module.finrank K V := by let b := IsNoetherian.finsetBasis K V - rw [Module.card_fintype b, ← FiniteDimensional.finrank_eq_card_basis b] + rw [Module.card_fintype b, ← Module.finrank_eq_card_basis b] end diff --git a/Mathlib/FieldTheory/Finite/GaloisField.lean b/Mathlib/FieldTheory/Finite/GaloisField.lean index baca752d4d5c6..89b627d0328c8 100644 --- a/Mathlib/FieldTheory/Finite/GaloisField.lean +++ b/Mathlib/FieldTheory/Finite/GaloisField.lean @@ -3,10 +3,10 @@ Copyright (c) 2021 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Aaron Anderson, Alex J. Best, Johan Commelin, Eric Rodriguez, Ruben Van de Velde -/ +import Mathlib.Algebra.Algebra.ZMod import Mathlib.Algebra.CharP.Algebra -import Mathlib.Data.ZMod.Algebra import Mathlib.FieldTheory.Finite.Basic -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic import Mathlib.FieldTheory.SplittingField.IsSplittingField /-! @@ -88,7 +88,7 @@ instance : Fintype (GaloisField p n) := by dsimp only [GaloisField] exact FiniteDimensional.fintypeOfFintype (ZMod p) (GaloisField p n) -theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisField p n) = n := by +theorem finrank {n} (h : n ≠ 0) : Module.finrank (ZMod p) (GaloisField p n) = n := by set g_poly := (X ^ p ^ n - X : (ZMod p)[X]) have hp : 1 < p := h_prime.out.one_lt have aux : g_poly ≠ 0 := FiniteField.X_pow_card_pow_sub_X_ne_zero _ h hp @@ -139,7 +139,7 @@ theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisFi theorem card (h : n ≠ 0) : Fintype.card (GaloisField p n) = p ^ n := by let b := IsNoetherian.finsetBasis (ZMod p) (GaloisField p n) - rw [Module.card_fintype b, ← FiniteDimensional.finrank_eq_card_basis b, ZMod.card, finrank p h] + rw [Module.card_fintype b, ← Module.finrank_eq_card_basis b, ZMod.card, finrank p h] theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by have hp : 1 < p := h_prime.out.one_lt diff --git a/Mathlib/FieldTheory/Finite/Polynomial.lean b/Mathlib/FieldTheory/Finite/Polynomial.lean index 8207de7d06c14..00e92545eba5b 100644 --- a/Mathlib/FieldTheory/Finite/Polynomial.lean +++ b/Mathlib/FieldTheory/Finite/Polynomial.lean @@ -215,8 +215,8 @@ instance [Finite σ] : FiniteDimensional K (R σ K) := by simpa only [rank_R] using Cardinal.nat_lt_aleph0 (Fintype.card (σ → K))) open Classical in -theorem finrank_R [Fintype σ] : FiniteDimensional.finrank K (R σ K) = Fintype.card (σ → K) := - FiniteDimensional.finrank_eq_of_rank_eq (rank_R σ K) +theorem finrank_R [Fintype σ] : Module.finrank K (R σ K) = Fintype.card (σ → K) := + Module.finrank_eq_of_rank_eq (rank_R σ K) -- Porting note: was `(evalᵢ σ K).range`. theorem range_evalᵢ [Finite σ] : range (evalᵢ σ K) = ⊤ := by @@ -228,7 +228,7 @@ theorem ker_evalₗ [Finite σ] : ker (evalᵢ σ K) = ⊥ := by cases nonempty_fintype σ refine (ker_eq_bot_iff_range_eq_top_of_finrank_eq_finrank ?_).mpr (range_evalᵢ σ K) classical - rw [FiniteDimensional.finrank_fintype_fun_eq_card, finrank_R] + rw [Module.finrank_fintype_fun_eq_card, finrank_R] theorem eq_zero_of_eval_eq_zero [Finite σ] (p : MvPolynomial σ K) (h : ∀ v : σ → K, eval v p = 0) (hp : p ∈ restrictDegree σ K (Fintype.card K - 1)) : p = 0 := diff --git a/Mathlib/FieldTheory/Finiteness.lean b/Mathlib/FieldTheory/Finiteness.lean index 6c2e5621a9272..d6cc69e04c7ae 100644 --- a/Mathlib/FieldTheory/Finiteness.lean +++ b/Mathlib/FieldTheory/Finiteness.lean @@ -72,7 +72,7 @@ theorem coeSort_finsetBasisIndex [IsNoetherian K V] : /-- In a noetherian module over a division ring, there exists a finite basis. This is indexed by the `Finset` `IsNoetherian.finsetBasisIndex`. This is in contrast to the result `finite_basis_index (Basis.ofVectorSpace K V)`, -which provides a set and a `Set.finite`. +which provides a set and a `Set.Finite`. -/ noncomputable def finsetBasis [IsNoetherian K V] : Basis (finsetBasisIndex K V) K V := (Basis.ofVectorSpace K V).reindex (by rw [coeSort_finsetBasisIndex]) diff --git a/Mathlib/FieldTheory/Fixed.lean b/Mathlib/FieldTheory/Fixed.lean index bf86498f3027a..4b86ac581b736 100644 --- a/Mathlib/FieldTheory/Fixed.lean +++ b/Mathlib/FieldTheory/Fixed.lean @@ -30,7 +30,7 @@ element of `G`, where `G` is a group that acts on `F`. noncomputable section -open MulAction Finset FiniteDimensional +open MulAction Finset Module universe u v w @@ -193,7 +193,7 @@ theorem of_eval₂ (f : Polynomial (FixedPoints.subfield G F)) have h : Polynomial.map (MulSemiringActionHom.toRingHom (IsInvariantSubring.subtypeHom G (subfield G F).toSubring)) f = Polynomial.map ((IsInvariantSubring.subtypeHom G (subfield G F).toSubring)) f := rfl - erw [← Polynomial.map_dvd_map' (Subfield.subtype <| FixedPoints.subfield G F), minpoly, this, + rw [← Polynomial.map_dvd_map' (Subfield.subtype <| FixedPoints.subfield G F), minpoly, this, Polynomial.map_toSubring _ _, prodXSubSMul] refine Fintype.prod_dvd_of_coprime diff --git a/Mathlib/FieldTheory/Galois.lean b/Mathlib/FieldTheory/Galois/Basic.lean similarity index 99% rename from Mathlib/FieldTheory/Galois.lean rename to Mathlib/FieldTheory/Galois/Basic.lean index 868454440fa9b..3f571ef51fa06 100644 --- a/Mathlib/FieldTheory/Galois.lean +++ b/Mathlib/FieldTheory/Galois/Basic.lean @@ -24,7 +24,7 @@ In this file we define Galois extensions as extensions which are both separable - `IntermediateField.fixingSubgroup_fixedField` : If `E/F` is finite dimensional (but not necessarily Galois) then `fixingSubgroup (fixedField H) = H` -- `IntermediateField.fixedField_fixingSubgroup`: If `E/F` is finite dimensional and Galois +- `IsGalois.fixedField_fixingSubgroup`: If `E/F` is finite dimensional and Galois then `fixedField (fixingSubgroup K) = K` Together, these two results prove the Galois correspondence. @@ -35,7 +35,7 @@ Together, these two results prove the Galois correspondence. open scoped Polynomial IntermediateField -open FiniteDimensional AlgEquiv +open Module AlgEquiv section diff --git a/Mathlib/FieldTheory/IntermediateField/Algebraic.lean b/Mathlib/FieldTheory/IntermediateField/Algebraic.lean index 99eab922d6a3d..55ecc96148306 100644 --- a/Mathlib/FieldTheory/IntermediateField/Algebraic.lean +++ b/Mathlib/FieldTheory/IntermediateField/Algebraic.lean @@ -13,7 +13,7 @@ import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition # Results on finite dimensionality and algebraicity of intermediate fields. -/ -open FiniteDimensional +open Module variable {K : Type*} {L : Type*} [Field K] [Field L] [Algebra K L] {S : IntermediateField K L} @@ -24,11 +24,8 @@ section FiniteDimensional variable (F E : IntermediateField K L) -instance finiteDimensional_left [FiniteDimensional K L] : FiniteDimensional K F := - left K F L - -instance finiteDimensional_right [FiniteDimensional K L] : FiniteDimensional F L := - right K F L +instance finiteDimensional_left [FiniteDimensional K L] : FiniteDimensional K F := .left K F L +instance finiteDimensional_right [FiniteDimensional K L] : FiniteDimensional F L := .right K F L @[simp] theorem rank_eq_rank_subalgebra : Module.rank K F.toSubalgebra = Module.rank K F := diff --git a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean index 21d9418e249a5..787429c5e3827 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/AlgebraicClosure.lean @@ -79,7 +79,7 @@ theorem spanEval_ne_top : spanEval k ≠ ⊤ := by rw [map_one, Finsupp.linearCombination_apply, Finsupp.sum, map_sum, Finset.sum_eq_zero] at hv · exact zero_ne_one hv intro j hj - rw [smul_eq_mul, map_mul, toSplittingField_evalXSelf (s := v.support) hj, + rw [smul_eq_mul, map_mul, toSplittingField_evalXSelf _ (s := v.support) hj, mul_zero] /-- A random maximal ideal that contains `spanEval k` -/ diff --git a/Mathlib/FieldTheory/IsAlgClosed/Classification.lean b/Mathlib/FieldTheory/IsAlgClosed/Classification.lean index eadc63373a37b..e0fb0cd9df594 100644 --- a/Mathlib/FieldTheory/IsAlgClosed/Classification.lean +++ b/Mathlib/FieldTheory/IsAlgClosed/Classification.lean @@ -3,9 +3,9 @@ Copyright (c) 2022 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes -/ -import Mathlib.Algebra.Polynomial.Cardinal +import Mathlib.Algebra.Algebra.ZMod import Mathlib.Algebra.MvPolynomial.Cardinal -import Mathlib.Data.ZMod.Algebra +import Mathlib.Algebra.Polynomial.Cardinal import Mathlib.FieldTheory.IsAlgClosed.Basic import Mathlib.RingTheory.AlgebraicIndependent @@ -48,7 +48,7 @@ theorem cardinal_mk_le_sigma_polynomial : Polynomial.degree_map_eq_of_injective (NoZeroSMulDivisors.algebraMap_injective R L), Polynomial.degree_eq_bot] exact p.2.1 - erw [Polynomial.mem_roots h, Polynomial.IsRoot, Polynomial.eval_map, ← Polynomial.aeval_def, + rw [Polynomial.mem_roots h, Polynomial.IsRoot, Polynomial.eval_map, ← Polynomial.aeval_def, p.2.2]⟩) fun x y => by intro h diff --git a/Mathlib/FieldTheory/IsPerfectClosure.lean b/Mathlib/FieldTheory/IsPerfectClosure.lean index 70d3708472eb5..743199124c340 100644 --- a/Mathlib/FieldTheory/IsPerfectClosure.lean +++ b/Mathlib/FieldTheory/IsPerfectClosure.lean @@ -60,7 +60,7 @@ perfect ring, perfect closure, purely inseparable -/ -open FiniteDimensional Polynomial IntermediateField Field +open Module Polynomial IntermediateField Field noncomputable section diff --git a/Mathlib/FieldTheory/IsSepClosed.lean b/Mathlib/FieldTheory/IsSepClosed.lean index a986c4144c374..1a11e8d38dff7 100644 --- a/Mathlib/FieldTheory/IsSepClosed.lean +++ b/Mathlib/FieldTheory/IsSepClosed.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jz Pan -/ import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic /-! # Separably Closed Field diff --git a/Mathlib/FieldTheory/KrullTopology.lean b/Mathlib/FieldTheory/KrullTopology.lean index 18d9b02736673..7f7f53c3109a7 100644 --- a/Mathlib/FieldTheory/KrullTopology.lean +++ b/Mathlib/FieldTheory/KrullTopology.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Sebastian Monnet. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sebastian Monnet -/ -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic import Mathlib.Topology.Algebra.FilterBasis import Mathlib.Topology.Algebra.OpenSubgroup import Mathlib.Tactic.ByContra diff --git a/Mathlib/FieldTheory/KummerExtension.lean b/Mathlib/FieldTheory/KummerExtension.lean index 18680d5a83dd6..671a4b1bb374a 100644 --- a/Mathlib/FieldTheory/KummerExtension.lean +++ b/Mathlib/FieldTheory/KummerExtension.lean @@ -5,7 +5,7 @@ Authors: Andrew Yang -/ import Mathlib.RingTheory.RootsOfUnity.Basic import Mathlib.RingTheory.AdjoinRoot -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic import Mathlib.LinearAlgebra.Eigenspace.Minpoly import Mathlib.RingTheory.Norm.Basic /-! @@ -272,6 +272,11 @@ theorem Polynomial.separable_X_pow_sub_C_of_irreducible : (X ^ n - C a).Separabl AdjoinRoot.algebraMap_eq, X_pow_sub_C_eq_prod (hζ.map_of_injective (algebraMap K _).injective) hn (root_X_pow_sub_C_pow n a), separable_prod_X_sub_C_iff'] + #adaptation_note + /-- + After https://github.com/leanprover/lean4/pull/5376 we need to provide this helper instance. + -/ + have : MonoidHomClass (K →+* K[n√a]) K K[n√a] := inferInstance exact (hζ.map_of_injective (algebraMap K K[n√a]).injective).injOn_pow_mul (root_X_pow_sub_C_ne_zero (lt_of_le_of_ne (show 1 ≤ n from hn) (Ne.symm hn')) _) @@ -530,7 +535,7 @@ lemma isGalois_of_isSplittingField_X_pow_sub_C : IsGalois K L := IsGalois.of_separable_splitting_field (separable_X_pow_sub_C_of_irreducible hζ a H) include hζ H in -lemma finrank_of_isSplittingField_X_pow_sub_C : FiniteDimensional.finrank K L = n := by +lemma finrank_of_isSplittingField_X_pow_sub_C : Module.finrank K L = n := by have := Polynomial.IsSplittingField.finiteDimensional L (X ^ n - C a) have := isGalois_of_isSplittingField_X_pow_sub_C hζ H L have hn := Nat.pos_iff_ne_zero.mpr (ne_zero_of_irreducible_X_pow_sub_C H) @@ -545,9 +550,9 @@ end IsSplittingField section IsCyclic variable {L} [Field L] [Algebra K L] [FiniteDimensional K L] -variable (hK : (primitiveRoots (FiniteDimensional.finrank K L) K).Nonempty) +variable (hK : (primitiveRoots (Module.finrank K L) K).Nonempty) -open FiniteDimensional +open Module variable (K L) include hK in @@ -623,7 +628,7 @@ lemma isSplittingField_X_pow_sub_C_of_root_adjoin_eq_top end IsCyclic -open FiniteDimensional in +open Module 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 @@ -631,7 +636,7 @@ Then `L/K` is cyclic 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) : + (hK : (primitiveRoots (Module.finrank K L) K).Nonempty) : List.TFAE [ IsGalois K L ∧ IsCyclic (L ≃ₐ[K] L), ∃ a : K, Irreducible (X ^ (finrank K L) - C a) ∧ diff --git a/Mathlib/FieldTheory/Minpoly/Field.lean b/Mathlib/FieldTheory/Minpoly/Field.lean index 32d3a549998d0..b129b8a0ecbc5 100644 --- a/Mathlib/FieldTheory/Minpoly/Field.lean +++ b/Mathlib/FieldTheory/Minpoly/Field.lean @@ -127,22 +127,47 @@ theorem eq_of_irreducible [Nontrivial B] {p : A[X]} (hp1 : Irreducible p) · rw [aeval_mul, hp2, zero_mul] · rwa [Polynomial.Monic, leadingCoeff_mul, leadingCoeff_C, mul_inv_cancel₀] -theorem add_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (hx : IsIntegral A x) +theorem add_algebraMap {B : Type*} [CommRing B] [Algebra A B] (x : B) (a : A) : minpoly A (x + algebraMap A B a) = (minpoly A x).comp (X - C a) := by - refine (minpoly.unique _ _ ((minpoly.monic hx).comp_X_sub_C _) ?_ fun q qmo hq => ?_).symm - · simp [aeval_comp] - · have : (Polynomial.aeval x) (q.comp (X + C a)) = 0 := by simpa [aeval_comp] using hq - have H := minpoly.min A x (qmo.comp_X_add_C _) this - rw [degree_eq_natDegree qmo.ne_zero, - degree_eq_natDegree ((minpoly.monic hx).comp_X_sub_C _).ne_zero, natDegree_comp, - natDegree_X_sub_C, mul_one] - rwa [degree_eq_natDegree (minpoly.ne_zero hx), - degree_eq_natDegree (qmo.comp_X_add_C _).ne_zero, natDegree_comp, - natDegree_X_add_C, mul_one] at H - -theorem sub_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (hx : IsIntegral A x) + by_cases hx : IsIntegral A x + · refine (minpoly.unique _ _ ((minpoly.monic hx).comp_X_sub_C _) ?_ fun q qmo hq => ?_).symm + · simp [aeval_comp] + · have : (Polynomial.aeval x) (q.comp (X + C a)) = 0 := by simpa [aeval_comp] using hq + have H := minpoly.min A x (qmo.comp_X_add_C _) this + rw [degree_eq_natDegree qmo.ne_zero, + degree_eq_natDegree ((minpoly.monic hx).comp_X_sub_C _).ne_zero, natDegree_comp, + natDegree_X_sub_C, mul_one] + rwa [degree_eq_natDegree (minpoly.ne_zero hx), + degree_eq_natDegree (qmo.comp_X_add_C _).ne_zero, natDegree_comp, + natDegree_X_add_C, mul_one] at H + · rw [minpoly.eq_zero hx, minpoly.eq_zero, zero_comp] + refine fun h ↦ hx ?_ + simpa only [add_sub_cancel_right] using IsIntegral.sub h (isIntegral_algebraMap (x := a)) + +theorem sub_algebraMap {B : Type*} [CommRing B] [Algebra A B] {x : B} (a : A) : minpoly A (x - algebraMap A B a) = (minpoly A x).comp (X + C a) := by - simpa [sub_eq_add_neg] using add_algebraMap hx (-a) + simpa [sub_eq_add_neg] using add_algebraMap x (-a) + +theorem neg {B : Type*} [CommRing B] [Algebra A B] (x : B) : + minpoly A (- x) = (-1) ^ (natDegree (minpoly A x)) * (minpoly A x).comp (- X) := by + by_cases hx : IsIntegral A x + · refine (minpoly.unique _ _ ((minpoly.monic hx).neg_one_pow_natDegree_mul_comp_neg_X) + ?_ fun q qmo hq => ?_).symm + · simp [aeval_comp] + · have : (Polynomial.aeval x) ((-1) ^ q.natDegree * q.comp (- X)) = 0 := by + simpa [aeval_comp] using hq + have H := minpoly.min A x qmo.neg_one_pow_natDegree_mul_comp_neg_X this + have n1 := ((minpoly.monic hx).neg_one_pow_natDegree_mul_comp_neg_X).ne_zero + have n2 := qmo.neg_one_pow_natDegree_mul_comp_neg_X.ne_zero + rw [degree_eq_natDegree qmo.ne_zero, + degree_eq_natDegree n1, natDegree_mul (by simp) (right_ne_zero_of_mul n1), natDegree_comp] + rw [degree_eq_natDegree (minpoly.ne_zero hx), + degree_eq_natDegree qmo.neg_one_pow_natDegree_mul_comp_neg_X.ne_zero, + natDegree_mul (by simp) (right_ne_zero_of_mul n2), natDegree_comp] at H + simpa using H + · rw [minpoly.eq_zero hx, minpoly.eq_zero, zero_comp] + · simp only [natDegree_zero, pow_zero, mul_zero] + · exact IsIntegral.neg_iff.not.mpr hx section AlgHomFintype @@ -158,7 +183,7 @@ variable (F E K : Type*) [Field F] [Ring E] [CommRing K] [IsDomain K] [Algebra F -- though it isn't very computable in practice (since neither `finrank` nor `finBasis` are). /-- Function from Hom_K(E,L) to pi type Π (x : basis), roots of min poly of x -/ def rootsOfMinPolyPiType (φ : E →ₐ[F] K) - (x : range (FiniteDimensional.finBasis F E : _ → E)) : + (x : range (Module.finBasis F E : _ → E)) : { l : K // l ∈ (minpoly F x.1).aroots K } := ⟨φ x, by rw [mem_roots_map (minpoly.ne_zero_of_finite F x.val), @@ -169,14 +194,14 @@ theorem aux_inj_roots_of_min_poly : Injective (rootsOfMinPolyPiType F E K) := by -- needs explicit coercion on the RHS suffices (f : E →ₗ[F] K) = (g : E →ₗ[F] K) 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 => + exact LinearMap.ext_on (Module.finBasis F E).span_eq fun e he => Subtype.ext_iff.mp (h ⟨e, he⟩) /-- Given field extensions `E/F` and `K/F`, with `E/F` finite, there are finitely many `F`-algebra homomorphisms `E →ₐ[K] K`. -/ noncomputable instance AlgHom.fintype : Fintype (E →ₐ[F] K) := @Fintype.ofInjective _ _ - (Fintype.subtypeProd (finite_range (FiniteDimensional.finBasis F E)) fun e => + (Fintype.subtypeProd (finite_range (Module.finBasis F E)) fun e => (minpoly F e).aroots K) _ (aux_inj_roots_of_min_poly F E K) diff --git a/Mathlib/FieldTheory/Minpoly/IsIntegrallyClosed.lean b/Mathlib/FieldTheory/Minpoly/IsIntegrallyClosed.lean index 5abd2d46ef12c..3db3147d29b05 100644 --- a/Mathlib/FieldTheory/Minpoly/IsIntegrallyClosed.lean +++ b/Mathlib/FieldTheory/Minpoly/IsIntegrallyClosed.lean @@ -186,4 +186,24 @@ theorem _root_.PowerBasis.ofGenMemAdjoin'_gen (B : PowerBasis R S) (hint : IsInt end AdjoinRoot +section Subring + +variable {K L : Type*} [Field K] [Field L] [Algebra K L] + +variable (A : Subring K) [IsIntegrallyClosed A] [IsFractionRing A K] + +-- Implementation note: `inferInstance` does not work for these. +instance : Algebra A (integralClosure A L) := Subalgebra.algebra (integralClosure A L) +instance : SMul A (integralClosure A L) := Algebra.toSMul +instance : IsScalarTower A ((integralClosure A L)) L := + IsScalarTower.subalgebra' A L L (integralClosure A L) + +/-- The minimal polynomial of `x : L` over `K` agrees with its minimal polynomial over the +integrally closed subring `A`. -/ +theorem ofSubring (x : integralClosure A L) : + Polynomial.map (algebraMap A K) (minpoly A x) = minpoly K (x : L) := + eq_comm.mpr (isIntegrallyClosed_eq_field_fractions K L (IsIntegralClosure.isIntegral A L x)) + +end Subring + end minpoly diff --git a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean index c327e135c3ddd..fae1bec1703c0 100644 --- a/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean +++ b/Mathlib/FieldTheory/Minpoly/MinpolyDiv.lean @@ -20,7 +20,7 @@ See `traceForm_dualBasis_powerBasis_eq`. - `span_coeff_minpolyDiv`: The coefficients of `minpolyDiv` spans `R`. -/ -open Polynomial FiniteDimensional +open Polynomial Module variable (R K) {L S} [CommRing R] [Field K] [Field L] [CommRing S] [Algebra R S] [Algebra K L] variable (x : S) diff --git a/Mathlib/FieldTheory/PerfectClosure.lean b/Mathlib/FieldTheory/PerfectClosure.lean index df62d0fc00813..50b237cb61ab0 100644 --- a/Mathlib/FieldTheory/PerfectClosure.lean +++ b/Mathlib/FieldTheory/PerfectClosure.lean @@ -92,7 +92,6 @@ theorem quot_mk_eq_mk (x : ℕ × K) : (Quot.mk (R K p) x : PerfectClosure K p) variable {K p} /-- Lift a function `ℕ × K → L` to a function on `PerfectClosure K p`. -/ --- Porting note: removed `@[elab_as_elim]` for "unexpected eliminator resulting type L" def liftOn {L : Type*} (x : PerfectClosure K p) (f : ℕ × K → L) (hf : ∀ x y, R K p x y → f x = f y) : L := Quot.liftOn x f hf diff --git a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean index 159fca2636398..ef2d383b8d52b 100644 --- a/Mathlib/FieldTheory/PolynomialGaloisGroup.lean +++ b/Mathlib/FieldTheory/PolynomialGaloisGroup.lean @@ -3,7 +3,7 @@ Copyright (c) 2020 Thomas Browning, Patrick Lutz. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Thomas Browning, Patrick Lutz -/ -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic /-! # Galois Groups of Polynomials @@ -41,7 +41,7 @@ noncomputable section open scoped Polynomial -open FiniteDimensional +open Module namespace Polynomial @@ -384,10 +384,10 @@ theorem prime_degree_dvd_card [CharZero F] (p_irr : Irreducible p) (p_deg : p.na let α : p.SplittingField := rootOfSplits (algebraMap F p.SplittingField) (SplittingField.splits p) hp have hα : IsIntegral F α := .of_finite F α - use FiniteDimensional.finrank F⟮α⟯ p.SplittingField + use Module.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, + rw [← Module.finrank_mul_finrank F F⟮α⟯ p.SplittingField, IntermediateField.adjoin.finrank hα, this] suffices minpoly F α ∣ p by have key := (minpoly.irreducible hα).dvd_symm p_irr this diff --git a/Mathlib/FieldTheory/PrimitiveElement.lean b/Mathlib/FieldTheory/PrimitiveElement.lean index 65b6d1707f19d..da215b5d8dbf4 100644 --- a/Mathlib/FieldTheory/PrimitiveElement.lean +++ b/Mathlib/FieldTheory/PrimitiveElement.lean @@ -36,7 +36,7 @@ exists_adjoin_simple_eq_top noncomputable section -open FiniteDimensional Polynomial IntermediateField +open Module Polynomial IntermediateField namespace Field @@ -63,7 +63,7 @@ theorem exists_primitive_element_of_finite_top [Finite E] : ∃ α : E, F⟮α /-- Primitive element theorem for finite dimensional extension of a finite field. -/ theorem exists_primitive_element_of_finite_bot [Finite F] [FiniteDimensional F E] : ∃ α : E, F⟮α⟯ = ⊤ := - haveI : Finite E := finite_of_finite F E + haveI : Finite E := FiniteDimensional.finite_of_finite F E exists_primitive_element_of_finite_top F E end PrimitiveElementFinite @@ -367,7 +367,7 @@ section iff namespace Field -open FiniteDimensional IntermediateField Polynomial Algebra Set +open Module IntermediateField Polynomial Algebra Set variable (F : Type*) {E : Type*} [Field F] [Field E] [Algebra F E] [FiniteDimensional F E] diff --git a/Mathlib/FieldTheory/PurelyInseparable.lean b/Mathlib/FieldTheory/PurelyInseparable.lean index f8b347c9bf68a..93c3226de53d7 100644 --- a/Mathlib/FieldTheory/PurelyInseparable.lean +++ b/Mathlib/FieldTheory/PurelyInseparable.lean @@ -127,7 +127,7 @@ separable degree, degree, separable closure, purely inseparable -/ -open FiniteDimensional Polynomial IntermediateField Field Finsupp +open Module Polynomial IntermediateField Field Finsupp noncomputable section @@ -166,7 +166,7 @@ variable {F K} theorem isPurelyInseparable_iff : IsPurelyInseparable F E ↔ ∀ x : E, IsIntegral F x ∧ (IsSeparable F x → x ∈ (algebraMap F E).range) := - ⟨fun h x ↦ ⟨h.isIntegral' x, h.inseparable' x⟩, fun h ↦ ⟨⟨fun x ↦ (h x).1⟩, fun x ↦ (h x).2⟩⟩ + ⟨fun h x ↦ ⟨h.isIntegral' _ x, h.inseparable' x⟩, fun h ↦ ⟨⟨fun x ↦ (h x).1⟩, fun x ↦ (h x).2⟩⟩ /-- Transfer `IsPurelyInseparable` across an `AlgEquiv`. -/ theorem AlgEquiv.isPurelyInseparable (e : K ≃ₐ[F] E) [IsPurelyInseparable F K] : @@ -756,7 +756,7 @@ private theorem LinearIndependent.map_pow_expChar_pow_of_fd_isSeparable have h' := h.coe_range let ι' := h'.extend (Set.range v).subset_univ let b : Basis ι' F E := Basis.extend h' - letI : Fintype ι' := fintypeBasisIndex b + letI : Fintype ι' := FiniteDimensional.fintypeBasisIndex b have H := linearIndependent_of_top_le_span_of_card_eq_finrank (span_map_pow_expChar_pow_eq_top_of_isSeparable q n b.span_eq).ge (finrank_eq_card_basis b).symm diff --git a/Mathlib/FieldTheory/RatFunc/Basic.lean b/Mathlib/FieldTheory/RatFunc/Basic.lean index 477f652402ff1..66d5c87abee7c 100644 --- a/Mathlib/FieldTheory/RatFunc/Basic.lean +++ b/Mathlib/FieldTheory/RatFunc/Basic.lean @@ -269,7 +269,7 @@ macro "smul_tac" : tactic => `(tactic| simp_rw [← ofFractionRing_smul] <;> simp only [add_comm, mul_comm, zero_smul, succ_nsmul, zsmul_eq_mul, mul_add, mul_one, mul_zero, neg_add, mul_neg, - Int.ofNat_eq_coe, Int.cast_zero, Int.cast_add, Int.cast_one, + Int.cast_zero, Int.cast_add, Int.cast_one, Int.cast_negSucc, Int.cast_natCast, Nat.cast_succ, Localization.mk_zero, Localization.add_mk_self, Localization.neg_mk, ofFractionRing_zero, ← ofFractionRing_add, ← ofFractionRing_neg]) diff --git a/Mathlib/FieldTheory/Separable.lean b/Mathlib/FieldTheory/Separable.lean index c6a87d0dbf1fb..11f14b5edd03f 100644 --- a/Mathlib/FieldTheory/Separable.lean +++ b/Mathlib/FieldTheory/Separable.lean @@ -337,8 +337,7 @@ theorem separable_or {f : F[X]} (hf : Irreducible f) : exact Or.inr ⟨by rw [separable_iff_derivative_ne_zero hf, Classical.not_not, H], contract p f, - of_irreducible_map (expand F p : F[X] →+* F[X]) - (by rwa [← expand_contract p H hp.ne'] at hf), + Irreducible.of_map (by rwa [← expand_contract p H hp.ne'] at hf), expand_contract p H hp.ne'⟩ else Or.inl <| (separable_iff_derivative_ne_zero hf).2 H @@ -652,7 +651,7 @@ theorem IsSeparable.tower_bot {x : K} (h : IsSeparable F (algebraMap K E x)) : I variable (K E) in theorem Algebra.isSeparable_tower_bot_of_isSeparable [h : Algebra.IsSeparable F E] : Algebra.IsSeparable F K := - ⟨fun _ ↦ IsSeparable.tower_bot (h.isSeparable _)⟩ + ⟨fun _ ↦ IsSeparable.tower_bot (h.isSeparable _ _)⟩ end IsScalarTower diff --git a/Mathlib/FieldTheory/SeparableClosure.lean b/Mathlib/FieldTheory/SeparableClosure.lean index 596db72fdf6cd..68110800b109d 100644 --- a/Mathlib/FieldTheory/SeparableClosure.lean +++ b/Mathlib/FieldTheory/SeparableClosure.lean @@ -59,7 +59,7 @@ separable degree, degree, separable closure -/ -open FiniteDimensional Polynomial IntermediateField Field +open Module Polynomial IntermediateField Field noncomputable section diff --git a/Mathlib/FieldTheory/SeparableDegree.lean b/Mathlib/FieldTheory/SeparableDegree.lean index 3bac952cdb9f8..fb1ec8ab2843c 100644 --- a/Mathlib/FieldTheory/SeparableDegree.lean +++ b/Mathlib/FieldTheory/SeparableDegree.lean @@ -67,7 +67,7 @@ This file contains basics about the separable degree of a field extension. if `K / E / F` is a field extension tower, such that `K / E` is algebraic, then there is a non-canonical bijection `Field.Emb F E × Field.Emb E K ≃ Field.Emb F K`. In particular, the separable degrees satisfy the tower law: $[E:F]_s [K:E]_s = [K:F]_s$ - (see also `FiniteDimensional.finrank_mul_finrank`). + (see also `Module.finrank_mul_finrank`). - `Polynomial.natSepDegree_le_natDegree`: the separable degree of a polynomial is smaller than its degree. @@ -118,7 +118,7 @@ separable degree, degree, polynomial -/ -open FiniteDimensional Polynomial IntermediateField Field +open Module Polynomial IntermediateField Field noncomputable section @@ -208,7 +208,7 @@ def embEquivOfAdjoinSplits {S : Set E} (hS : adjoin F S = ⊤) (hS ▸ isAlgebraic_adjoin (S := S) fun x hx ↦ (hK x hx).1) have halg := (topEquiv (F := F) (E := E)).isAlgebraic Classical.choice <| Function.Embedding.antisymm - (halg.algHomEmbeddingOfSplits (fun _ ↦ splits_of_mem_adjoin F (S := S) hK (hS ▸ mem_top)) _) + (halg.algHomEmbeddingOfSplits (fun _ ↦ splits_of_mem_adjoin F E (S := S) hK (hS ▸ mem_top)) _) (halg.algHomEmbeddingOfSplits (fun _ ↦ IsAlgClosed.splits_codomain _) _) /-- The `Field.finSepDegree F E` is equal to the cardinality of `E →ₐ[F] K` @@ -246,7 +246,7 @@ def embProdEmbOfIsAlgebraic [Algebra E K] [IsScalarTower F E K] [Algebra.IsAlgeb /-- If `K / E / F` is a field extension tower, such that `K / E` is algebraic, then their separable degrees satisfy the tower law -$[E:F]_s [K:E]_s = [K:F]_s$. See also `FiniteDimensional.finrank_mul_finrank`. -/ +$[E:F]_s [K:E]_s = [K:F]_s$. See also `Module.finrank_mul_finrank`. -/ theorem finSepDegree_mul_finSepDegree_of_isAlgebraic [Algebra E K] [IsScalarTower F E K] [Algebra.IsAlgebraic E K] : finSepDegree F E * finSepDegree E K = finSepDegree F K := by @@ -701,7 +701,7 @@ theorem finSepDegree_dvd_finrank : finSepDegree F E ∣ finrank F E := by set M := L⟮x⟯ have := Algebra.IsAlgebraic.of_finite L M rwa [finSepDegree_mul_finSepDegree_of_isAlgebraic F L M, - FiniteDimensional.finrank_mul_finrank F L M] at hdvd + Module.finrank_mul_finrank F L M] at hdvd rw [finrank_of_infinite_dimensional hfd] exact dvd_zero _ @@ -735,7 +735,7 @@ theorem finSepDegree_eq_finrank_of_isSeparable [Algebra.IsSeparable F E] : set M := L⟮x⟯ have := Algebra.IsAlgebraic.of_finite L M rwa [finSepDegree_mul_finSepDegree_of_isAlgebraic F L M, - FiniteDimensional.finrank_mul_finrank F L M] at heq + Module.finrank_mul_finrank F L M] at heq alias Algebra.IsSeparable.finSepDegree_eq := finSepDegree_eq_finrank_of_isSeparable @@ -749,7 +749,7 @@ theorem finSepDegree_eq_finrank_iff [FiniteDimensional F E] : (finSepDegree_adjoin_simple_le_finrank F E x halg) <| le_of_not_lt fun h ↦ ?_ 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, - FiniteDimensional.finrank_mul_finrank F F⟮x⟯ E] at this + Module.finrank_mul_finrank F F⟮x⟯ E] at this linarith only [heq, this]⟩, fun _ ↦ finSepDegree_eq_finrank_of_isSeparable F E⟩ end Field @@ -796,7 +796,7 @@ theorem IsSeparable.of_algebra_isSeparable_of_isSeparable [Algebra E K] [IsScala have := finSepDegree_mul_finSepDegree_of_isAlgebraic F E' E'⟮x⟯ rw [finSepDegree_eq_finrank_of_isSeparable F E', finSepDegree_eq_finrank_of_isSeparable E' E'⟮x⟯, - FiniteDimensional.finrank_mul_finrank F E' E'⟮x⟯, + Module.finrank_mul_finrank F E' E'⟮x⟯, eq_comm, finSepDegree_eq_finrank_iff F E'⟮x⟯] at this change Algebra.IsSeparable F (restrictScalars F E'⟮x⟯) at this exact isSeparable_of_mem_isSeparable F K hx diff --git a/Mathlib/FieldTheory/Tower.lean b/Mathlib/FieldTheory/Tower.lean index 4a4720b3cb6aa..297650824b8be 100644 --- a/Mathlib/FieldTheory/Tower.lean +++ b/Mathlib/FieldTheory/Tower.lean @@ -15,7 +15,7 @@ We prove that given `IsScalarTower F K A`, if `A` is finite as a module over `F` In particular these conditions hold when `A`, `F`, and `K` are fields. -The formulas for the dimensions are given elsewhere by `FiniteDimensional.finrank_mul_finrank`. +The formulas for the dimensions are given elsewhere by `Module.finrank_mul_finrank`. ## Tags diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/Affine.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/Affine.lean index 40018bcc026e4..6e6e991b9b0b4 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/Affine.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/Affine.lean @@ -22,7 +22,7 @@ This file defines oriented angles in Euclidean affine spaces. noncomputable section -open FiniteDimensional Complex +open Module Complex open scoped Affine EuclideanGeometry Real RealInnerProductSpace ComplexConjugate diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean index fb641332e085a..3f2938cdce408 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/Basic.lean @@ -31,7 +31,7 @@ modulo `2 * π` as equalities of `(2 : ℤ) • θ`. noncomputable section -open FiniteDimensional Complex +open Module Complex open scoped Real RealInnerProductSpace ComplexConjugate diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/RightAngle.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/RightAngle.lean index d634919578060..8ca1f21c9b812 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/RightAngle.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/RightAngle.lean @@ -25,7 +25,7 @@ open scoped RealInnerProductSpace namespace Orientation -open FiniteDimensional +open Module variable {V : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] variable [hd2 : Fact (finrank ℝ V = 2)] (o : Orientation ℝ V (Fin 2)) @@ -519,7 +519,7 @@ end Orientation namespace EuclideanGeometry -open FiniteDimensional +open Module variable {V : Type*} {P : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] [NormedAddTorsor V P] [hd2 : Fact (finrank ℝ V = 2)] [Module.Oriented ℝ V (Fin 2)] diff --git a/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean b/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean index b933762e6b4a6..734899c867f50 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Oriented/Rotation.lean @@ -20,7 +20,7 @@ This file defines rotations by oriented angles in real inner product spaces. noncomputable section -open FiniteDimensional Complex +open Module Complex open scoped Real RealInnerProductSpace ComplexConjugate @@ -65,9 +65,8 @@ def rotation (θ : Real.Angle) : V ≃ₗᵢ[ℝ] V := · simp only [o.rightAngleRotation_rightAngleRotation, o.rotationAux_apply, Function.comp_apply, id, LinearEquiv.coe_coe, LinearIsometry.coe_toLinearMap, LinearIsometryEquiv.coe_toLinearEquiv, map_smul, map_sub, LinearMap.coe_comp, - LinearMap.id_coe, LinearMap.smul_apply, LinearMap.sub_apply, ← mul_smul, add_smul, - smul_add, smul_neg, smul_sub, mul_comm, sq] - abel + LinearMap.id_coe, LinearMap.smul_apply, LinearMap.sub_apply] + module · simp) (by ext x @@ -75,10 +74,8 @@ def rotation (θ : Real.Angle) : V ≃ₗᵢ[ℝ] V := · simp only [o.rightAngleRotation_rightAngleRotation, o.rotationAux_apply, Function.comp_apply, id, LinearEquiv.coe_coe, LinearIsometry.coe_toLinearMap, LinearIsometryEquiv.coe_toLinearEquiv, map_add, map_smul, LinearMap.coe_comp, - LinearMap.id_coe, LinearMap.smul_apply, LinearMap.sub_apply, - add_smul, smul_neg, smul_sub, smul_smul] - ring_nf - abel + LinearMap.id_coe, LinearMap.smul_apply, LinearMap.sub_apply] + module · simp) theorem rotation_apply (θ : Real.Angle) (x : V) : @@ -104,8 +101,7 @@ theorem rotation_eq_matrix_toLin (θ : Real.Angle) {x : V} (hx : x ≠ 0) : /-- The determinant of `rotation` (as a linear map) is equal to `1`. -/ @[simp] theorem det_rotation (θ : Real.Angle) : LinearMap.det (o.rotation θ).toLinearMap = 1 := by - haveI : Nontrivial V := - FiniteDimensional.nontrivial_of_finrank_eq_succ (@Fact.out (finrank ℝ V = 2) _) + haveI : Nontrivial V := nontrivial_of_finrank_eq_succ (@Fact.out (finrank ℝ V = 2) _) obtain ⟨x, hx⟩ : ∃ x, x ≠ (0 : V) := exists_ne (0 : V) rw [o.rotation_eq_matrix_toLin θ hx] simpa [sq] using θ.cos_sq_add_sin_sq @@ -146,11 +142,9 @@ theorem rotation_pi_div_two : o.rotation (π / 2 : ℝ) = J := by @[simp] theorem rotation_rotation (θ₁ θ₂ : Real.Angle) (x : V) : o.rotation θ₁ (o.rotation θ₂ x) = o.rotation (θ₁ + θ₂) x := by - simp only [o.rotation_apply, ← mul_smul, Real.Angle.cos_add, Real.Angle.sin_add, add_smul, - sub_smul, LinearIsometryEquiv.trans_apply, smul_add, LinearIsometryEquiv.map_add, - LinearIsometryEquiv.map_smul, rightAngleRotation_rightAngleRotation, smul_neg] - ring_nf - abel + simp only [o.rotation_apply, Real.Angle.cos_add, Real.Angle.sin_add, LinearIsometryEquiv.map_add, + LinearIsometryEquiv.trans_apply, map_smul, rightAngleRotation_rightAngleRotation] + module /-- Rotating twice is equivalent to rotating by the sum of the angles. -/ @[simp] @@ -338,8 +332,7 @@ theorem oangle_eq_iff_eq_pos_smul_rotation_or_eq_zero {x y : V} (θ : Real.Angle theorem exists_linearIsometryEquiv_eq_of_det_pos {f : V ≃ₗᵢ[ℝ] V} (hd : 0 < LinearMap.det (f.toLinearEquiv : V →ₗ[ℝ] V)) : ∃ θ : Real.Angle, f = o.rotation θ := by - haveI : Nontrivial V := - FiniteDimensional.nontrivial_of_finrank_eq_succ (@Fact.out (finrank ℝ V = 2) _) + haveI : Nontrivial V := nontrivial_of_finrank_eq_succ (@Fact.out (finrank ℝ V = 2) _) obtain ⟨x, hx⟩ : ∃ x, x ≠ (0 : V) := exists_ne (0 : V) use o.oangle x (f x) apply LinearIsometryEquiv.toLinearEquiv_injective diff --git a/Mathlib/Geometry/Euclidean/Angle/Sphere.lean b/Mathlib/Geometry/Euclidean/Angle/Sphere.lean index dd2a20922dbdb..17315a1b24430 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Sphere.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Sphere.lean @@ -16,7 +16,7 @@ This file proves results about angles in circles and spheres. noncomputable section -open FiniteDimensional Complex +open Module Complex open scoped EuclideanGeometry Real RealInnerProductSpace ComplexConjugate diff --git a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean index 9dcdde2ba5730..b58876fe73b9d 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Unoriented/Affine.lean @@ -350,7 +350,7 @@ theorem angle_eq_zero_iff_ne_and_wbtw {p₁ p₂ p₃ : P} : · rw [angle, angle_eq_zero_iff] rintro ⟨hp₁p₂, r, hr0, hp₃p₂⟩ rcases le_or_lt 1 r with (hr1 | hr1) - · refine Or.inl ⟨vsub_ne_zero.1 hp₁p₂, r⁻¹, ⟨(inv_pos.2 hr0).le, inv_le_one hr1⟩, ?_⟩ + · refine Or.inl ⟨vsub_ne_zero.1 hp₁p₂, r⁻¹, ⟨(inv_pos.2 hr0).le, inv_le_one_of_one_le₀ hr1⟩, ?_⟩ rw [AffineMap.lineMap_apply, hp₃p₂, smul_smul, inv_mul_cancel₀ hr0.ne.symm, one_smul, vsub_vadd] · refine Or.inr ⟨?_, r, ⟨hr0.le, hr1.le⟩, ?_⟩ diff --git a/Mathlib/Geometry/Euclidean/Angle/Unoriented/RightAngle.lean b/Mathlib/Geometry/Euclidean/Angle/Unoriented/RightAngle.lean index a85b10c3cdb58..03de613c6af8b 100644 --- a/Mathlib/Geometry/Euclidean/Angle/Unoriented/RightAngle.lean +++ b/Mathlib/Geometry/Euclidean/Angle/Unoriented/RightAngle.lean @@ -121,7 +121,7 @@ theorem cos_angle_add_of_inner_eq_zero {x y : V} (h : ⟪x, y⟫ = 0) : Real.cos (angle x (x + y)) = ‖x‖ / ‖x + y‖ := by rw [angle_add_eq_arccos_of_inner_eq_zero h, Real.cos_arccos (le_trans (by norm_num) (div_nonneg (norm_nonneg _) (norm_nonneg _))) - (div_le_one_of_le _ (norm_nonneg _))] + (div_le_one_of_le₀ _ (norm_nonneg _))] rw [mul_self_le_mul_self_iff (norm_nonneg _) (norm_nonneg _), norm_add_sq_eq_norm_sq_add_norm_sq_real h] exact le_add_of_nonneg_right (mul_self_nonneg _) @@ -131,7 +131,7 @@ theorem sin_angle_add_of_inner_eq_zero {x y : V} (h : ⟪x, y⟫ = 0) (h0 : x Real.sin (angle x (x + y)) = ‖y‖ / ‖x + y‖ := by rw [angle_add_eq_arcsin_of_inner_eq_zero h h0, Real.sin_arcsin (le_trans (by norm_num) (div_nonneg (norm_nonneg _) (norm_nonneg _))) - (div_le_one_of_le _ (norm_nonneg _))] + (div_le_one_of_le₀ _ (norm_nonneg _))] rw [mul_self_le_mul_self_iff (norm_nonneg _) (norm_nonneg _), norm_add_sq_eq_norm_sq_add_norm_sq_real h] exact le_add_of_nonneg_left (mul_self_nonneg _) diff --git a/Mathlib/Geometry/Euclidean/Basic.lean b/Mathlib/Geometry/Euclidean/Basic.lean index 3ac078670754f..b9807b923e2cb 100644 --- a/Mathlib/Geometry/Euclidean/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Basic.lean @@ -113,8 +113,9 @@ another point. -/ theorem dist_smul_vadd_eq_dist {v : V} (p₁ p₂ : P) (hv : v ≠ 0) (r : ℝ) : dist (r • v +ᵥ p₁) p₂ = dist p₁ p₂ ↔ r = 0 ∨ r = -2 * ⟪v, p₁ -ᵥ p₂⟫ / ⟪v, v⟫ := by conv_lhs => - rw [← mul_self_inj_of_nonneg dist_nonneg dist_nonneg, dist_smul_vadd_sq, ← sub_eq_zero, - add_sub_assoc, dist_eq_norm_vsub V p₁ p₂, ← real_inner_self_eq_norm_mul_norm, sub_self] + rw [← mul_self_inj_of_nonneg dist_nonneg dist_nonneg, dist_smul_vadd_sq, mul_assoc, + ← sub_eq_zero, add_sub_assoc, dist_eq_norm_vsub V p₁ p₂, ← real_inner_self_eq_norm_mul_norm, + sub_self] have hvi : ⟪v, v⟫ ≠ 0 := by simpa using hv have hd : discrim ⟪v, v⟫ (2 * ⟪v, p₁ -ᵥ p₂⟫) 0 = 2 * ⟪v, p₁ -ᵥ p₂⟫ * (2 * ⟪v, p₁ -ᵥ p₂⟫) := by rw [discrim] @@ -124,7 +125,7 @@ theorem dist_smul_vadd_eq_dist {v : V} (p₁ p₂ : P) (hv : v ≠ 0) (r : ℝ) mul_div_assoc] norm_num -open AffineSubspace FiniteDimensional +open AffineSubspace Module /-- Distances `r₁` `r₂` of `p` from two different points `c₁` `c₂` determine at most two points `p₁` `p₂` in a two-dimensional subspace containing those points @@ -150,7 +151,7 @@ theorem eq_of_dist_eq_of_dist_eq_of_mem_of_finrank_eq_two {s : AffineSubspace · rw [real_inner_comm] exact ho have hbs : Submodule.span ℝ (Set.range b) = s.direction := by - refine eq_of_le_of_finrank_eq ?_ ?_ + refine Submodule.eq_of_le_of_finrank_eq ?_ ?_ · rw [Submodule.span_le, Set.range_subset_iff] intro i fin_cases i diff --git a/Mathlib/Geometry/Euclidean/Circumcenter.lean b/Mathlib/Geometry/Euclidean/Circumcenter.lean index ed19fa6831d20..ab715d6d83899 100644 --- a/Mathlib/Geometry/Euclidean/Circumcenter.lean +++ b/Mathlib/Geometry/Euclidean/Circumcenter.lean @@ -667,7 +667,7 @@ end Affine namespace EuclideanGeometry -open Affine AffineSubspace FiniteDimensional +open Affine AffineSubspace Module variable {V : Type*} {P : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] [NormedAddTorsor V P] diff --git a/Mathlib/Geometry/Euclidean/MongePoint.lean b/Mathlib/Geometry/Euclidean/MongePoint.lean index 6343ce224c3da..fbf488bef44b3 100644 --- a/Mathlib/Geometry/Euclidean/MongePoint.lean +++ b/Mathlib/Geometry/Euclidean/MongePoint.lean @@ -344,7 +344,7 @@ theorem vectorSpan_isOrtho_altitude_direction {n : ℕ} (s : Simplex ℝ P (n + rw [direction_altitude] exact (Submodule.isOrtho_orthogonal_right _).mono_right inf_le_left -open FiniteDimensional +open Module /-- An altitude is finite-dimensional. -/ instance finiteDimensional_direction_altitude {n : ℕ} (s : Simplex ℝ P (n + 1)) (i : Fin (n + 2)) : @@ -392,7 +392,7 @@ theorem affineSpan_pair_eq_altitude_iff {n : ℕ} (s : Simplex ℝ P (n + 1)) (i rw [vectorSpan_eq_span_vsub_set_left_ne ℝ (Set.mem_insert _ _), Set.insert_diff_of_mem _ (Set.mem_singleton _), Set.diff_singleton_eq_self fun h => hne (Set.mem_singleton_iff.1 h), Set.image_singleton] - refine eq_of_le_of_finrank_eq ?_ ?_ + refine Submodule.eq_of_le_of_finrank_eq ?_ ?_ · rw [Submodule.span_le] simpa using h · rw [finrank_direction_altitude, finrank_span_set_eq_card] @@ -404,7 +404,7 @@ end Simplex namespace Triangle -open EuclideanGeometry Finset Simplex AffineSubspace FiniteDimensional +open EuclideanGeometry Finset Simplex AffineSubspace Module variable {V : Type*} {P : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] [NormedAddTorsor V P] @@ -548,7 +548,8 @@ theorem altitude_replace_orthocenter_eq_affineSpan {t₁ t₂ : Triangle ℝ P} have he : affineSpan ℝ (Set.range t₂.points) = affineSpan ℝ (Set.range t₁.points) := by refine ext_of_direction_eq ?_ ⟨t₁.points i₃, mem_affineSpan ℝ ⟨j₃, h₃⟩, mem_affineSpan ℝ (Set.mem_range_self _)⟩ - refine eq_of_le_of_finrank_eq (direction_le (spanPoints_subset_coe_of_subset_coe ?_)) ?_ + refine Submodule.eq_of_le_of_finrank_eq (direction_le (spanPoints_subset_coe_of_subset_coe ?_)) + ?_ · have hu : (Finset.univ : Finset (Fin 3)) = {j₁, j₂, j₃} := by clear h₁ h₂ h₃ -- Porting note (#11043): was `decide!` @@ -602,7 +603,7 @@ end Affine namespace EuclideanGeometry -open Affine AffineSubspace FiniteDimensional +open Affine AffineSubspace Module variable {V : Type*} {P : Type*} [NormedAddCommGroup V] [InnerProductSpace ℝ V] [MetricSpace P] [NormedAddTorsor V P] @@ -706,7 +707,7 @@ theorem affineSpan_of_orthocentricSystem {s : Set P} (ho : OrthocentricSystem s) ⟨p 0, mem_affineSpan ℝ (Set.mem_range_self _), mem_affineSpan ℝ (hps (Set.mem_range_self _))⟩ have hfd : FiniteDimensional ℝ (affineSpan ℝ s).direction := by rw [hs]; infer_instance haveI := hfd - refine eq_of_le_of_finrank_eq (direction_le (affineSpan_mono ℝ hps)) ?_ + refine Submodule.eq_of_le_of_finrank_eq (direction_le (affineSpan_mono ℝ hps)) ?_ rw [hs, direction_affineSpan, direction_affineSpan, ha.finrank_vectorSpan (Fintype.card_fin _), t.independent.finrank_vectorSpan (Fintype.card_fin _)] diff --git a/Mathlib/Geometry/Euclidean/Sphere/Basic.lean b/Mathlib/Geometry/Euclidean/Sphere/Basic.lean index 20d5711b81e4d..6c5067aad4c23 100644 --- a/Mathlib/Geometry/Euclidean/Sphere/Basic.lean +++ b/Mathlib/Geometry/Euclidean/Sphere/Basic.lean @@ -33,7 +33,7 @@ namespace EuclideanGeometry variable {V : Type*} (P : Type*) -open FiniteDimensional +open Module /-- A `Sphere P` bundles a `center` and `radius`. This definition does not require the radius to be positive; that should be given as a hypothesis to lemmas that require it. -/ diff --git a/Mathlib/Geometry/Euclidean/Triangle.lean b/Mathlib/Geometry/Euclidean/Triangle.lean index 5a28ab76286ee..9e2ab6a89582d 100644 --- a/Mathlib/Geometry/Euclidean/Triangle.lean +++ b/Mathlib/Geometry/Euclidean/Triangle.lean @@ -295,7 +295,7 @@ theorem angle_add_angle_add_angle_eq_pi {p1 p2 p3 : P} (h2 : p2 ≠ p1) (h3 : p3 /-- The **sum of the angles of a triangle** (possibly degenerate, where the triangle is a line), oriented angles at point. -/ theorem oangle_add_oangle_add_oangle_eq_pi [Module.Oriented ℝ V (Fin 2)] - [Fact (FiniteDimensional.finrank ℝ V = 2)] {p1 p2 p3 : P} (h21 : p2 ≠ p1) (h32 : p3 ≠ p2) + [Fact (Module.finrank ℝ V = 2)] {p1 p2 p3 : P} (h21 : p2 ≠ p1) (h32 : p3 ≠ p2) (h13 : p1 ≠ p3) : ∡ p1 p2 p3 + ∡ p2 p3 p1 + ∡ p3 p1 p2 = π := by simpa only [neg_vsub_eq_vsub_rev] using positiveOrientation.oangle_add_cyc3_neg_left (vsub_ne_zero.mpr h21) (vsub_ne_zero.mpr h32) diff --git a/Mathlib/Geometry/Manifold/AnalyticManifold.lean b/Mathlib/Geometry/Manifold/AnalyticManifold.lean index 442b24423f19a..8ef606a4540a1 100644 --- a/Mathlib/Geometry/Manifold/AnalyticManifold.lean +++ b/Mathlib/Geometry/Manifold/AnalyticManifold.lean @@ -17,7 +17,7 @@ interior and smooth everywhere (including at the boundary). The definition mirr analytic manifolds are smooth manifolds. Completeness is required throughout, but this is nonessential: it is due to many of the lemmas about -AnalyticWithinOn` requiring completeness for ease of proof. +AnalyticOn` requiring completeness for ease of proof. -/ noncomputable section @@ -42,10 +42,10 @@ analytic on the interior, and map the interior to itself. This allows us to def section analyticGroupoid /-- Given a model with corners `(E, H)`, we define the pregroupoid of analytic transformations of -`H` as the maps that are `AnalyticWithinOn` when read in `E` through `I`. Using `AnalyticWithinOn` -rather than `AnalyticOn` gives us meaningful definitions at boundary points. -/ +`H` as the maps that are `AnalyticOn` when read in `E` through `I`. Using `AnalyticOn` +rather than `AnalyticOnNhd` gives us meaningful definitions at boundary points. -/ def analyticPregroupoid : Pregroupoid H where - property f s := AnalyticWithinOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' s ∩ range I) + property f s := AnalyticOn 𝕜 (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] @@ -54,12 +54,12 @@ def analyticPregroupoid : Pregroupoid H where · rintro x ⟨hx1, _⟩ simpa only [mfld_simps] using hx1.2 id_mem := by - apply analyticWithinOn_id.congr + apply analyticOn_id.congr rintro x ⟨_, hx2⟩ obtain ⟨y, hy⟩ := mem_range.1 hx2 simp only [mfld_simps, ← hy] locality {f u} _ H := by - apply analyticWithinOn_of_locally_analyticWithinOn + apply analyticOn_of_locally_analyticOn rintro y ⟨hy1, hy2⟩ obtain ⟨x, hx⟩ := mem_range.1 hy2 simp only [mfld_simps, ← hx] at hy1 ⊢ @@ -75,8 +75,8 @@ def analyticPregroupoid : Pregroupoid H where rw [fg _ hy1] /-- Given a model with corners `(E, H)`, we define the groupoid of analytic transformations of -`H` as the maps that are `AnalyticWithinOn` when read in `E` through `I`. Using `AnalyticWithinOn` -rather than `AnalyticOn` gives us meaningful definitions at boundary points. -/ +`H` as the maps that are `AnalyticOn` when read in `E` through `I`. Using `AnalyticOn` +rather than `AnalyticOnNhd` gives us meaningful definitions at boundary points. -/ def analyticGroupoid : StructureGroupoid H := (analyticPregroupoid I).groupoid @@ -84,9 +84,9 @@ def analyticGroupoid : StructureGroupoid H := theorem ofSet_mem_analyticGroupoid {s : Set H} (hs : IsOpen s) : PartialHomeomorph.ofSet s hs ∈ analyticGroupoid I := by rw [analyticGroupoid, mem_groupoid_of_pregroupoid] - suffices h : AnalyticWithinOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) by + suffices h : AnalyticOn 𝕜 (I ∘ I.symm) (I.symm ⁻¹' s ∩ range I) by simp [h, analyticPregroupoid] - have hi : AnalyticWithinOn 𝕜 id (univ : Set E) := analyticWithinOn_id + have hi : AnalyticOn 𝕜 id (univ : Set E) := analyticOn_id exact (hi.mono (subset_univ _)).congr (fun x hx ↦ I.right_inv hx.2) /-- The composition of a partial homeomorphism from `H` to `M` and its inverse belongs to @@ -108,17 +108,17 @@ instance : ClosedUnderRestriction (analyticGroupoid I) := /-- `f ∈ analyticGroupoid` iff it and its inverse are analytic within `range I`. -/ lemma mem_analyticGroupoid {I : ModelWithCorners 𝕜 E H} {f : PartialHomeomorph H H} : f ∈ analyticGroupoid I ↔ - AnalyticWithinOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' f.source ∩ range I) ∧ - AnalyticWithinOn 𝕜 (I ∘ f.symm ∘ I.symm) (I.symm ⁻¹' f.target ∩ range I) := by + AnalyticOn 𝕜 (I ∘ f ∘ I.symm) (I.symm ⁻¹' f.source ∩ range I) ∧ + AnalyticOn 𝕜 (I ∘ f.symm ∘ I.symm) (I.symm ⁻¹' f.target ∩ range I) := by rfl /-- The analytic groupoid on a boundaryless charted space modeled on a complete vector space consists of the partial homeomorphisms which are analytic and have analytic inverse. -/ theorem mem_analyticGroupoid_of_boundaryless [I.Boundaryless] (e : PartialHomeomorph H H) : - e ∈ analyticGroupoid I ↔ AnalyticOn 𝕜 (I ∘ e ∘ I.symm) (I '' e.source) ∧ - AnalyticOn 𝕜 (I ∘ e.symm ∘ I.symm) (I '' e.target) := by + e ∈ analyticGroupoid I ↔ AnalyticOnNhd 𝕜 (I ∘ e ∘ I.symm) (I '' e.source) ∧ + AnalyticOnNhd 𝕜 (I ∘ e.symm ∘ I.symm) (I '' e.target) := by simp only [mem_analyticGroupoid, I.range_eq_univ, inter_univ, I.image_eq] - rw [IsOpen.analyticWithinOn_iff_analyticOn, IsOpen.analyticWithinOn_iff_analyticOn] + rw [IsOpen.analyticOn_iff_analyticOnNhd, IsOpen.analyticOn_iff_analyticOnNhd] · exact I.continuous_symm.isOpen_preimage _ e.open_target · exact I.continuous_symm.isOpen_preimage _ e.open_source @@ -131,12 +131,12 @@ theorem analyticGroupoid_prod {E A : Type} [NormedAddCommGroup E] [NormedSpace f.prod g ∈ analyticGroupoid (I.prod J) := by have pe : range (I.prod J) = (range I).prod (range J) := I.range_prod simp only [mem_analyticGroupoid, Function.comp, image_subset_iff] at fa ga ⊢ - exact ⟨AnalyticWithinOn.prod - (fa.1.comp analyticWithinOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) - (ga.1.comp analyticWithinOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩), - AnalyticWithinOn.prod - (fa.2.comp analyticWithinOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) - (ga.2.comp analyticWithinOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩)⟩ + exact ⟨AnalyticOn.prod + (fa.1.comp analyticOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.1.comp analyticOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩), + AnalyticOn.prod + (fa.2.comp analyticOn_fst fun _ m ↦ ⟨m.1.1, (pe ▸ m.2).1⟩) + (ga.2.comp analyticOn_snd fun _ m ↦ ⟨m.1.2, (pe ▸ m.2).2⟩)⟩ end analyticGroupoid diff --git a/Mathlib/Geometry/Manifold/BumpFunction.lean b/Mathlib/Geometry/Manifold/BumpFunction.lean index d32ef29050ef2..16f7d52a36180 100644 --- a/Mathlib/Geometry/Manifold/BumpFunction.lean +++ b/Mathlib/Geometry/Manifold/BumpFunction.lean @@ -34,7 +34,7 @@ variable {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type uH} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] -open Function Filter FiniteDimensional Set Metric +open Function Filter Module Set Metric open scoped Topology Manifold diff --git a/Mathlib/Geometry/Manifold/Complex.lean b/Mathlib/Geometry/Manifold/Complex.lean index a0110600277bb..a9ea94cdde69c 100644 --- a/Mathlib/Geometry/Manifold/Complex.lean +++ b/Mathlib/Geometry/Manifold/Complex.lean @@ -90,7 +90,7 @@ theorem norm_eqOn_of_isPreconnected_of_isMaxOn {f : M → F} {U : Set M} {c : M} replace hm : IsLocalMax (‖f ·‖) x := mem_of_superset (ho.mem_nhds hx.1) fun z hz ↦ (hm hz).out.trans_eq hx.2.symm replace hd : ∀ᶠ y in 𝓝 x, MDifferentiableAt I 𝓘(ℂ, F) f y := - (eventually_mem_nhds.2 (ho.mem_nhds hx.1)).mono fun z ↦ hd.mdifferentiableAt + (eventually_mem_nhds_iff.2 (ho.mem_nhds hx.1)).mono fun z ↦ hd.mdifferentiableAt exact (Complex.norm_eventually_eq_of_mdifferentiableAt_of_isLocalMax hd hm).mono fun _ ↦ (Eq.trans · hx.2) have hVne : (U ∩ V).Nonempty := ⟨c, hcU, hcU, rfl⟩ diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean index c8a972fc9462a..cd4f4365ba286 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Basic.lean @@ -324,7 +324,7 @@ theorem ContMDiff.extend_one [T2Space M] [One M'] {n : ℕ∞} {U : Opens M} {f (supp.mulTSupport_extend_one_subset continuous_subtype_val h) rw [← contMdiffAt_subtype_iff] simp_rw [← comp_def] - erw [extend_comp Subtype.val_injective] + rw [extend_comp Subtype.val_injective] exact diff.contMDiffAt theorem contMDiff_inclusion {n : ℕ∞} {U V : Opens M} (h : U ≤ V) : diff --git a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean index 3028f6318c3cd..cde9ee6782c47 100644 --- a/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean +++ b/Mathlib/Geometry/Manifold/ContMDiff/Defs.lean @@ -769,7 +769,7 @@ theorem contMDiffAt_iff_contMDiffAt_nhds refine ⟨?_, fun h => h.self_of_nhds⟩ rw [contMDiffAt_iff_contMDiffOn_nhds] rintro ⟨u, hu, h⟩ - refine (eventually_mem_nhds.mpr hu).mono fun x' hx' => ?_ + refine (eventually_mem_nhds_iff.mpr hu).mono fun x' hx' => ?_ exact (h x' <| mem_of_mem_nhds hx').contMDiffAt hx' /-! ### Congruence lemmas -/ diff --git a/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean b/Mathlib/Geometry/Manifold/ContMDiffMFDeriv.lean index 3dba3c04792f4..98fc2cc47a1e1 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.UniqueDifferential +import Mathlib.Geometry.Manifold.MFDeriv.Tangent import Mathlib.Geometry.Manifold.ContMDiffMap /-! @@ -96,7 +96,7 @@ protected theorem ContMDiffAt.mfderiv {x₀ : N} (f : N → M → M') (g : N → rw [contMDiffAt_iff] at hf hg simp_rw [Function.comp_def, uncurry, extChartAt_prod, PartialEquiv.prod_coe_symm, ModelWithCorners.range_prod] at hf ⊢ - refine ContDiffWithinAt.fderivWithin ?_ hg.2 I.unique_diff hmn (mem_range_self _) ?_ + refine ContDiffWithinAt.fderivWithin ?_ hg.2 I.uniqueDiffOn hmn (mem_range_self _) ?_ · simp_rw [extChartAt_to_inv]; exact hf.2 · rw [← image_subset_iff] rintro _ ⟨x, -, rfl⟩ @@ -165,7 +165,7 @@ protected theorem ContMDiffAt.mfderiv {x₀ : N} (f : N → M → M') (g : N → PartialEquiv.mem_symm_trans_source _ (mem_extChartAt_source I' (f x₂ (g x₂))) h3x₂).differentiableWithinAt le_top have h3f := (h2x₂.mdifferentiableAt le_rfl).differentiableWithinAt_writtenInExtChartAt - refine fderivWithin.comp₃ _ hI' h3f hI ?_ ?_ ?_ ?_ (I.unique_diff _ <| mem_range_self _) + refine fderivWithin.comp₃ _ hI' h3f hI ?_ ?_ ?_ ?_ (I.uniqueDiffOn _ <| mem_range_self _) · exact fun x _ => mem_range_self _ · exact fun x _ => mem_range_self _ · simp_rw [writtenInExtChartAt, Function.comp_apply, @@ -577,7 +577,7 @@ theorem tangentMap_tangentBundle_pure [Is : SmoothManifoldWithCorners I M] (p : · simp · exact differentiableAt_id' · exact differentiableAt_const _ - · exact ModelWithCorners.unique_diff_at_image I + · exact ModelWithCorners.uniqueDiffWithinAt_image I · exact differentiableAt_id'.prod (differentiableAt_const _) simp (config := { unfoldPartialApp := true }) only [Bundle.zeroSection, tangentMap, mfderiv, A, if_pos, chartAt, FiberBundle.chartedSpace_chartAt, TangentBundle.trivializationAt_apply, diff --git a/Mathlib/Geometry/Manifold/Diffeomorph.lean b/Mathlib/Geometry/Manifold/Diffeomorph.lean index 2c6f481393275..425037472ff7a 100644 --- a/Mathlib/Geometry/Manifold/Diffeomorph.lean +++ b/Mathlib/Geometry/Manifold/Diffeomorph.lean @@ -383,8 +383,6 @@ end end Constructions -variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners J N] - theorem uniqueMDiffOn_image_aux (h : M ≃ₘ^n⟮I, J⟯ N) (hn : 1 ≤ n) {s : Set M} (hs : UniqueMDiffOn I s) : UniqueMDiffOn J (h '' s) := by convert hs.uniqueMDiffOn_preimage (h.toPartialHomeomorph_mdifferentiable hn) @@ -447,7 +445,7 @@ variable (I) (e : E ≃ₘ[𝕜] E') def transDiffeomorph (I : ModelWithCorners 𝕜 E H) (e : E ≃ₘ[𝕜] E') : ModelWithCorners 𝕜 E' H where toPartialEquiv := I.toPartialEquiv.trans e.toEquiv.toPartialEquiv source_eq := by simp - unique_diff' := by simp [range_comp e, I.unique_diff] + uniqueDiffOn' := by simp [range_comp e, I.uniqueDiffOn] continuous_toFun := e.continuous.comp I.continuous continuous_invFun := I.continuous_symm.comp e.symm.continuous diff --git a/Mathlib/Geometry/Manifold/Instances/Real.lean b/Mathlib/Geometry/Manifold/Instances/Real.lean index 5a704749a28a5..43cbf79926a58 100644 --- a/Mathlib/Geometry/Manifold/Instances/Real.lean +++ b/Mathlib/Geometry/Manifold/Instances/Real.lean @@ -136,7 +136,7 @@ def modelWithCornersEuclideanHalfSpace (n : ℕ) [NeZero n] : exact ⟨max_eq_left xprop, fun i _ => rfl⟩ right_inv' x hx := update_eq_iff.2 ⟨max_eq_left hx, fun i _ => rfl⟩ source_eq := rfl - unique_diff' := by + uniqueDiffOn' := by have : UniqueDiffOn ℝ _ := UniqueDiffOn.pi (Fin n) (fun _ => ℝ) _ _ fun i (_ : i ∈ ({0} : Set (Fin n))) => uniqueDiffOn_Ici 0 @@ -159,7 +159,7 @@ def modelWithCornersEuclideanQuadrant (n : ℕ) : left_inv' x _ := by ext i; simp only [Subtype.coe_mk, x.2 i, max_eq_left] right_inv' x hx := by ext1 i; simp only [hx i, max_eq_left] source_eq := rfl - unique_diff' := by + uniqueDiffOn' := by have this : UniqueDiffOn ℝ _ := UniqueDiffOn.univ_pi (Fin n) (fun _ => ℝ) _ fun _ => uniqueDiffOn_Ici 0 simpa only [pi_univ_Ici] using this diff --git a/Mathlib/Geometry/Manifold/Instances/Sphere.lean b/Mathlib/Geometry/Manifold/Instances/Sphere.lean index 6b2de5ca878f6..f5d59a6f08222 100644 --- a/Mathlib/Geometry/Manifold/Instances/Sphere.lean +++ b/Mathlib/Geometry/Manifold/Instances/Sphere.lean @@ -11,6 +11,7 @@ import Mathlib.Analysis.InnerProductSpace.PiL2 import Mathlib.Geometry.Manifold.Algebra.LieGroup import Mathlib.Geometry.Manifold.Instances.Real import Mathlib.Geometry.Manifold.MFDeriv.Basic +import Mathlib.Tactic.Module /-! # Manifold structure on the sphere @@ -66,7 +67,7 @@ variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] noncomputable section -open Metric FiniteDimensional Function +open Metric Module Function open scoped Manifold @@ -161,7 +162,7 @@ theorem contDiff_stereoInvFunAux : ContDiff ℝ ⊤ (stereoInvFunAux v) := by have h₁ : ContDiff ℝ ⊤ fun w : E => (‖w‖ ^ 2 + 4)⁻¹ := by refine (h₀.add contDiff_const).inv ?_ intro x - nlinarith + positivity have h₂ : ContDiff ℝ ⊤ fun w => (4 : ℝ) • w + (‖w‖ ^ 2 - 4) • v := by refine (contDiff_const.smul contDiff_id).add ?_ exact (h₀.sub contDiff_const).smul contDiff_const @@ -184,9 +185,9 @@ theorem stereoInvFun_ne_north_pole (hv : ‖v‖ = 1) (w : (ℝ ∙ v)ᗮ) : rw [← inner_lt_one_iff_real_of_norm_one _ hv] · have hw : ⟪v, w⟫_ℝ = 0 := Submodule.mem_orthogonal_singleton_iff_inner_right.mp w.2 have hw' : (‖(w : E)‖ ^ 2 + 4)⁻¹ * (‖(w : E)‖ ^ 2 - 4) < 1 := by - refine (inv_mul_lt_iff' ?_).mpr ?_ - · nlinarith - linarith + rw [inv_mul_lt_iff₀'] + · linarith + positivity simpa [real_inner_comm, inner_add_right, inner_smul_right, real_inner_self_eq_norm_mul_norm, hw, hv] using hw' · simpa using stereoInvFunAux_mem hv w.2 @@ -195,6 +196,7 @@ theorem continuous_stereoInvFun (hv : ‖v‖ = 1) : Continuous (stereoInvFun hv continuous_induced_rng.2 (contDiff_stereoInvFunAux.continuous.comp continuous_subtype_val) open scoped InnerProductSpace in +attribute [-simp] AddSubgroupClass.coe_norm Submodule.coe_norm in theorem stereo_left_inv (hv : ‖v‖ = 1) {x : sphere (0 : E) 1} (hx : (x : E) ≠ v) : stereoInvFun hv (stereoToFun v x) = x := by ext @@ -212,57 +214,35 @@ theorem stereo_left_inv (hv : ‖v‖ = 1) {x : sphere (0 : E) 1} (hx : (x : E) · simp [← split] · simp [norm_smul, hv, ← sq, sq_abs] · exact sq _ - -- two facts which will be helpful for clearing denominators in the main calculation - have ha : 1 - a ≠ 0 := by + -- a fact which will be helpful for clearing denominators in the main calculation + have ha : 0 < 1 - a := by have : a < 1 := (inner_lt_one_iff_real_of_norm_one hv (by simp)).mpr hx.symm linarith - -- the core of the problem is these two algebraic identities: - have h₁ : (2 ^ 2 / (1 - a) ^ 2 * ‖y‖ ^ 2 + 4)⁻¹ * 4 * (2 / (1 - a)) = 1 := by - -- TODO(#15486): used to be `field_simp`, but was really slow - -- replaced by `simp only ...` to speed up. Reinstate `field_simp` once it is faster. - simp (disch := field_simp_discharge) only [AddSubgroupClass.coe_norm, div_mul_eq_mul_div, - div_add', inv_div, mul_div_assoc', div_div, div_eq_iff, one_mul] - simp only [Submodule.coe_norm] at *; nlinarith only [pythag] - have h₂ : (2 ^ 2 / (1 - a) ^ 2 * ‖y‖ ^ 2 + 4)⁻¹ * (2 ^ 2 / (1 - a) ^ 2 * ‖y‖ ^ 2 - 4) = a := by - -- TODO(#15486): used to be `field_simp`, but was really slow - -- replaced by `simp only ...` to speed up. Reinstate `field_simp` once it is faster. - simp (disch := field_simp_discharge) only [AddSubgroupClass.coe_norm, div_mul_eq_mul_div, - div_add', inv_div, div_sub', mul_div_assoc', div_div, div_eq_iff] - transitivity (1 - a) ^ 2 * (a * (2 ^ 2 * ‖y‖ ^ 2 + 4 * (1 - a) ^ 2)) - · congr - simp only [Submodule.coe_norm] at * - nlinarith only [pythag] - ring! - convert - congr_arg₂ Add.add (congr_arg (fun t => t • (y : E)) h₁) (congr_arg (fun t => t • v) h₂) using 1 - · simp only [innerSL_apply, norm_smul, norm_div, RCLike.norm_ofNat, Real.norm_eq_abs, - AddSubgroupClass.coe_norm, mul_pow, div_pow, sq_abs, SetLike.val_smul, mul_smul, a] - -- Porting note: used to be simp only [split, add_comm] but get maxRec errors - rw [split, add_comm] - ac_rfl - -- Porting note: this branch did not exit in ml3 - · rw [split, add_comm] - congr - dsimp - rw [one_smul] + rw [split, Submodule.coe_smul_of_tower] + simp only [norm_smul, norm_div, RCLike.norm_ofNat, Real.norm_eq_abs, abs_of_nonneg ha.le] + match_scalars + · field_simp + linear_combination 4 * (1 - a) * pythag + · field_simp + linear_combination 4 * (a - 1) ^ 3 * pythag theorem stereo_right_inv (hv : ‖v‖ = 1) (w : (ℝ ∙ v)ᗮ) : stereoToFun v (stereoInvFun hv w) = w := by - have : 2 / (1 - (‖(w : E)‖ ^ 2 + 4)⁻¹ * (‖(w : E)‖ ^ 2 - 4)) * (‖(w : E)‖ ^ 2 + 4)⁻¹ * 4 = 1 := by - -- TODO(#15486): used to be `field_simp`, but was really slow - -- replaced by `simp only ...` to speed up. Reinstate `field_simp` once it is faster. - simp (disch := field_simp_discharge) only [inv_eq_one_div, div_mul_eq_mul_div, one_mul, - sub_div', add_sub_sub_cancel, div_div_eq_mul_div, mul_div_assoc', mul_one, div_div, - div_eq_iff] - ring - convert congr_arg (· • w) this - · have h₁ : orthogonalProjection (ℝ ∙ v)ᗮ v = 0 := - orthogonalProjection_orthogonalComplement_singleton_eq_zero v - -- Porting note: was innerSL _ and now just inner - have h₃ : inner v w = (0 : ℝ) := Submodule.mem_orthogonal_singleton_iff_inner_right.mp w.2 - -- Porting note: was innerSL _ and now just inner - have h₄ : inner v v = (1 : ℝ) := by simp [real_inner_self_eq_norm_mul_norm, hv] - simp [h₁, h₃, h₄, ContinuousLinearMap.map_add, ContinuousLinearMap.map_smul, mul_smul] - · simp + simp only [stereoToFun, stereoInvFun, stereoInvFunAux, smul_add, map_add, map_smul, innerSL_apply, + orthogonalProjection_mem_subspace_eq_self] + have h₁ : orthogonalProjection (ℝ ∙ v)ᗮ v = 0 := + orthogonalProjection_orthogonalComplement_singleton_eq_zero v + -- Porting note: was innerSL _ and now just inner + have h₂ : inner v w = (0 : ℝ) := Submodule.mem_orthogonal_singleton_iff_inner_right.mp w.2 + -- Porting note: was innerSL _ and now just inner + have h₃ : inner v v = (1 : ℝ) := by simp [real_inner_self_eq_norm_mul_norm, hv] + rw [h₁, h₂, h₃] + match_scalars + -- TODO(#15486): used to be `field_simp`, but was really slow + -- replaced by `simp only ...` to speed up. Reinstate `field_simp` once it is faster. + simp (disch := field_simp_discharge) only [add_div', add_sub_sub_cancel, div_div, + div_div_eq_mul_div, div_eq_iff, div_mul_eq_mul_div, inv_eq_one_div, + mul_div_assoc', mul_one, mul_zero, one_mul, smul_eq_mul, sub_div', zero_add, zero_div, zero_mul] + ring /-- Stereographic projection from the unit sphere in `E`, centred at a unit vector `v` in `E`; this is the version as a partial homeomorphism. -/ diff --git a/Mathlib/Geometry/Manifold/IntegralCurve.lean b/Mathlib/Geometry/Manifold/IntegralCurve.lean index 01130e726c4b7..b16bd2c24cde9 100644 --- a/Mathlib/Geometry/Manifold/IntegralCurve.lean +++ b/Mathlib/Geometry/Manifold/IntegralCurve.lean @@ -6,7 +6,7 @@ Authors: Winston Yin import Mathlib.Analysis.ODE.Gronwall import Mathlib.Analysis.ODE.PicardLindelof import Mathlib.Geometry.Manifold.InteriorBoundary -import Mathlib.Geometry.Manifold.MFDeriv.Atlas +import Mathlib.Geometry.Manifold.MFDeriv.Tangent /-! # Integral curves of vector fields on a manifold @@ -65,7 +65,7 @@ open Function Set variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] + {M : Type*} [TopologicalSpace M] [ChartedSpace H 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 `γ` @@ -150,6 +150,7 @@ lemma IsIntegralCurveAt.continuousAt (hγ : IsIntegralCurveAt γ v t₀) : lemma IsIntegralCurve.continuous (hγ : IsIntegralCurve γ v) : Continuous γ := continuous_iff_continuousAt.mpr fun _ ↦ (hγ.isIntegralCurveOn univ).continuousAt (mem_univ _) +variable [SmoothManifoldWithCorners I M] in /-- 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) @@ -168,10 +169,11 @@ lemma IsIntegralCurveOn.hasDerivAt (hγ : IsIntegralCurveOn γ v s) {t : ℝ} (h mfderiv_chartAt_eq_tangentCoordChange I hsrc] rfl +variable [SmoothManifoldWithCorners I M] in 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 + apply eventually_mem_nhds_iff.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 @@ -266,7 +268,7 @@ lemma IsIntegralCurveAt.comp_mul_ne_zero (hγ : IsIntegralCurveAt γ v t₀) {a 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] + 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 @@ -304,7 +306,7 @@ end Scaling section ExistUnique -variable (t₀) {x₀ : M} +variable [SmoothManifoldWithCorners I M] (t₀) {x₀ : M} /-- Existence of local integral curves for a $C^1$ vector field at interior points of a smooth manifold. -/ @@ -325,7 +327,7 @@ theorem exists_isIntegralCurveAt_of_contMDiffAt [CompleteSpace E] 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 + rw [← eventually_mem_nhds_iff] 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 @@ -391,7 +393,7 @@ theorem isIntegralCurveAt_eventuallyEq_of_contMDiffAt (hγt₀ : I.IsInteriorPoi 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 <| + ∀ᶠ t in 𝓝 t₀, g ⁻¹' (extChartAt I (g t₀)).source ∈ 𝓝 t := eventually_mem_nhds_iff.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 diff --git a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean index 9feae63ffc666..5ea4b4a42e6b8 100644 --- a/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean +++ b/Mathlib/Geometry/Manifold/LocalInvariantProperties.lean @@ -68,7 +68,7 @@ structure LocalInvariantProp (P : (H → H') → Set H → H → Prop) : Prop wh left_invariance' : ∀ {s x f} {e' : PartialHomeomorph H' H'}, e' ∈ G' → s ⊆ f ⁻¹' e'.source → f x ∈ e'.source → P f s x → P (e' ∘ f) s x -variable {G G'} {P : (H → H') → Set H → H → Prop} {s t u : Set H} {x : H} +variable {G G'} {P : (H → H') → Set H → H → Prop} variable (hG : G.LocalInvariantProp G' P) include hG diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean index 908659feaf54a..cbdbcb8afc391 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Atlas.lean @@ -127,37 +127,6 @@ theorem mdifferentiable_of_mem_atlas (h : e ∈ atlas H M) : e.MDifferentiable I theorem mdifferentiable_chart (x : M) : (chartAt H x).MDifferentiable I I := mdifferentiable_of_mem_atlas _ (chart_mem_atlas _ _) -/-- 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 - -/-- 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 - -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 _) hsrc - simp [mfderiv, if_pos this, Function.comp_assoc] - end Charts @@ -176,9 +145,6 @@ protected theorem mdifferentiableAt {x : M} (hx : x ∈ e.source) : MDifferentia 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) -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 diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean index f9b96b110f3fc..077f630896244 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Basic.lean @@ -4,6 +4,7 @@ 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 +import Mathlib.Geometry.Manifold.ContMDiff.Defs /-! # Basic properties of the manifold Fréchet derivative @@ -21,6 +22,8 @@ mimicking the API for Fréchet derivatives. noncomputable section +assert_not_exists tangentBundleCore + open scoped Topology Manifold open Set Bundle @@ -44,7 +47,7 @@ variable theorem uniqueMDiffWithinAt_univ : UniqueMDiffWithinAt I univ x := by unfold UniqueMDiffWithinAt simp only [preimage_univ, univ_inter] - exact I.unique_diff _ (mem_range_self _) + exact I.uniqueDiffOn _ (mem_range_self _) variable {I} @@ -120,12 +123,12 @@ theorem 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, - (differentiable_within_at_localInvariantProp I I').liftPropWithinAt_inter ht] + (differentiableWithinAt_localInvariantProp I I').liftPropWithinAt_inter ht] theorem mdifferentiableWithinAt_inter' (ht : t ∈ 𝓝[s] x) : MDifferentiableWithinAt I I' f (s ∩ t) x ↔ MDifferentiableWithinAt I I' f s x := by rw [MDifferentiableWithinAt, MDifferentiableWithinAt, - (differentiable_within_at_localInvariantProp I I').liftPropWithinAt_inter' ht] + (differentiableWithinAt_localInvariantProp I I').liftPropWithinAt_inter' ht] theorem MDifferentiableAt.mdifferentiableWithinAt (h : MDifferentiableAt I I' f x) : MDifferentiableWithinAt I I' f s x := @@ -256,22 +259,17 @@ theorem writtenInExtChartAt_comp (h : ContinuousWithinAt f s x) : (h.preimage_mem_nhdsWithin (extChartAt_source_mem_nhds _ _))) mfld_set_tac -/- 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)} +variable {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) +protected 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 -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₁' := +protected 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₁ /-! @@ -280,6 +278,7 @@ theorem UniqueMDiffOn.eq (U : UniqueMDiffOn I s) (hx : x ∈ s) (h : HasMFDerivW We mimic the API for functions between vector spaces -/ +variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] in /-- 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'} @@ -288,7 +287,7 @@ theorem mdifferentiableWithinAt_iff_of_mem_source {x' : M} {y : M'} 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 + (differentiableWithinAt_localInvariantProp I I').liftPropWithinAt_indep_chart (StructureGroupoid.chart_mem_maximalAtlas _ x) hx (StructureGroupoid.chart_mem_maximalAtlas _ y) hy @@ -418,6 +417,7 @@ theorem mfderivWithin_eq_mfderiv (hs : UniqueMDiffWithinAt I s x) (h : MDifferen rw [← mfderivWithin_univ] exact mfderivWithin_subset (subset_univ _) hs h.mdifferentiableWithinAt +variable [SmoothManifoldWithCorners I M] [SmoothManifoldWithCorners I' M'] in 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' ↔ diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean index 6a68a762193e5..88e42b72004c0 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/Defs.lean @@ -3,7 +3,8 @@ 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 +import Mathlib.Geometry.Manifold.SmoothManifoldWithCorners +import Mathlib.Geometry.Manifold.LocalInvariantProperties /-! # The derivative of functions between smooth manifolds @@ -128,7 +129,7 @@ def DifferentiableWithinAtProp (f : H → H') (s : Set H) (x : H) : Prop := /-- 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 : +theorem differentiableWithinAt_localInvariantProp : (contDiffGroupoid ⊤ I).LocalInvariantProp (contDiffGroupoid ⊤ I') (DifferentiableWithinAtProp I I') := { is_local := by @@ -173,6 +174,9 @@ theorem differentiable_within_at_localInvariantProp : · ext y; simp only [mfld_simps] · intro y hy; simp only [mfld_simps] at hy; simpa only [hy, mfld_simps] using hs hy.1 } +@[deprecated (since := "2024-10-10")] +alias differentiable_within_at_localInvariantProp := differentiableWithinAt_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) := diff --git a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean index 75f5779ee5a46..e80b20105886e 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean @@ -28,12 +28,12 @@ section SpecificFunctions 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*} + [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'] - [SmoothManifoldWithCorners I' M'] {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] + {E'' : Type*} [NormedAddCommGroup E''] [NormedSpace 𝕜 E''] {H'' : Type*} [TopologicalSpace H''] (I'' : ModelWithCorners 𝕜 E'' H'') {M'' : Type*} - [TopologicalSpace M''] [ChartedSpace H'' M''] [SmoothManifoldWithCorners I'' M''] + [TopologicalSpace M''] [ChartedSpace H'' M''] namespace ContinuousLinearMap @@ -324,7 +324,7 @@ theorem MDifferentiableAt.mfderiv_prod {f : M → M'} {g : M → M''} {x : M} classical simp_rw [mfderiv, if_pos (hf.prod_mk hg), if_pos hf, if_pos hg] exact hf.differentiableWithinAt_writtenInExtChartAt.fderivWithin_prod - hg.differentiableWithinAt_writtenInExtChartAt (I.unique_diff _ (mem_range_self _)) + hg.differentiableWithinAt_writtenInExtChartAt (I.uniqueDiffOn _ (mem_range_self _)) variable (I I' I'') diff --git a/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean b/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean new file mode 100644 index 0000000000000..b1da80bc215d6 --- /dev/null +++ b/Mathlib/Geometry/Manifold/MFDeriv/Tangent.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2024 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 +import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential +import Mathlib.Geometry.Manifold.VectorBundle.Tangent + +/-! +# Derivatives of maps in the tangent bundle + +This file contains properties of derivatives which need the manifold structure of the tangent +bundle. Notably, it includes formulas for the tangent maps to charts, and unique differentiability +statements for subsets of the tangent bundle. +-/ + +open Bundle + +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''] + [SmoothManifoldWithCorners I M] + +/-- 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 + +/-- 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 + +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 _) hsrc + simp [mfderiv, if_pos this, Function.comp_assoc] + +/-- 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 {s : Set M} (hs : UniqueMDiffOn I s) : + UniqueMDiffOn I.tangent (π E (TangentSpace I) ⁻¹' s) := + hs.smooth_bundle_preimage _ diff --git a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean index d73131e3999fb..076089056c123 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/UniqueDifferential.lean @@ -4,6 +4,7 @@ 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 +import Mathlib.Geometry.Manifold.VectorBundle.Basic /-! # Unique derivative sets in manifolds @@ -32,11 +33,10 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCom [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'] - [SmoothManifoldWithCorners I' M'] {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H' M''] + {M'' : Type*} [TopologicalSpace M''] [ChartedSpace H' M''] {s : Set M} {x : M} section -variable [SmoothManifoldWithCorners I 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`. -/ @@ -82,6 +82,7 @@ theorem UniqueMDiffOn.uniqueMDiffOn_preimage (hs : UniqueMDiffOn I s) {e : Parti (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) +variable [SmoothManifoldWithCorners I M] in /-- 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) : @@ -94,6 +95,7 @@ theorem UniqueMDiffOn.uniqueDiffOn_target_inter (hs : UniqueMDiffOn I s) (x : M) (fun y hy ↦ hasMFDerivWithinAt_extChartAt I hy.2) fun y hy ↦ ((mdifferentiable_chart _ _).mfderiv_surjective hy.2).denseRange +variable [SmoothManifoldWithCorners I M] in /-- 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. -/ @@ -120,8 +122,6 @@ theorem Trivialization.mdifferentiable (e : Trivialization F (π F Z)) [MemTrivi e.toPartialHomeomorph.MDifferentiable (I.prod 𝓘(𝕜, F)) (I.prod 𝓘(𝕜, F)) := ⟨(e.smoothOn I).mdifferentiableOn, (e.smoothOn_symm I).mdifferentiableOn⟩ -variable [SmoothManifoldWithCorners I M] - theorem UniqueMDiffWithinAt.smooth_bundle_preimage {p : TotalSpace F Z} (hs : UniqueMDiffWithinAt I s p.proj) : UniqueMDiffWithinAt (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) p := by @@ -147,10 +147,4 @@ theorem UniqueMDiffOn.smooth_bundle_preimage (hs : UniqueMDiffOn I s) : UniqueMDiffOn (I.prod 𝓘(𝕜, F)) (π F Z ⁻¹' s) := fun _p hp ↦ (hs _ hp).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 _ - end UniqueMDiff diff --git a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean index 23d818e090332..d0c29cb8d57a6 100644 --- a/Mathlib/Geometry/Manifold/PartitionOfUnity.lean +++ b/Mathlib/Geometry/Manifold/PartitionOfUnity.lean @@ -57,7 +57,7 @@ smooth bump function, partition of unity universe uι uE uH uM uF -open Function Filter FiniteDimensional Set +open Function Filter Module Set open scoped Topology Manifold noncomputable section @@ -752,7 +752,7 @@ theorem exists_msmooth_support_eq_eq_one_iff · exact f_diff.div₀ (f_diff.add g_diff) (fun x ↦ ne_of_gt (A x)) -- show that the range is included in `[0, 1]` · refine range_subset_iff.2 (fun x ↦ ⟨div_nonneg (f_pos x) (A x).le, ?_⟩) - apply div_le_one_of_le _ (A x).le + apply div_le_one_of_le₀ _ (A x).le simpa only [le_add_iff_nonneg_right] using g_pos x -- show that the support is `s` · have B : support (fun x ↦ f x + g x) = univ := eq_univ_of_forall (fun x ↦ (A x).ne') diff --git a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean index fcd7714d974ef..468a549418177 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/LocallyRingedSpace.lean @@ -54,7 +54,7 @@ theorem smoothSheafCommRing.isUnit_stalk_iff {x : M} obtain ⟨U : Opens M, hxU, f : C^∞⟮IM, U; 𝓘(𝕜), 𝕜⟯, rfl⟩ := S.germ_exist x f have hf' : f ⟨x, hxU⟩ ≠ 0 := by convert hf - exact (smoothSheafCommRing.eval_germ U ⟨x, hxU⟩ f).symm + exact (smoothSheafCommRing.eval_germ U x hxU f).symm -- In fact, by continuity, `f` is nonzero on a neighbourhood `V` of `x` have H : ∀ᶠ (z : U) in 𝓝 ⟨x, hxU⟩, f z ≠ 0 := f.2.continuous.continuousAt.eventually_ne hf' rw [eventually_nhds_iff] at H @@ -77,8 +77,8 @@ theorem smoothSheafCommRing.isUnit_stalk_iff {x : M} -- Let `g` be the pointwise inverse of `f` on `V`, which is smooth since `f` is nonzero there let g : C^∞⟮IM, V; 𝓘(𝕜), 𝕜⟯ := ⟨(f ∘ Set.inclusion hUV)⁻¹, ?_⟩ -- The germ of `g` is inverse to the germ of `f`, so `f` is a unit - · refine ⟨⟨S.germ ⟨x, hxV⟩ (SmoothMap.restrictRingHom IM 𝓘(𝕜) 𝕜 hUV f), S.germ ⟨x, hxV⟩ g, - ?_, ?_⟩, S.germ_res_apply hUV.hom ⟨x, hxV⟩ f⟩ + · refine ⟨⟨S.germ _ x (hxV) (SmoothMap.restrictRingHom IM 𝓘(𝕜) 𝕜 hUV f), S.germ _ x hxV g, + ?_, ?_⟩, S.germ_res_apply hUV.hom x hxV f⟩ · rw [← map_mul] -- Qualified the name to avoid Lean not finding a `OneHomClass` #8386 convert RingHom.map_one _ diff --git a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean index 3fb40aacdf854..d8ac4a298bca8 100644 --- a/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean +++ b/Mathlib/Geometry/Manifold/Sheaf/Smooth.lean @@ -132,10 +132,10 @@ instance [Nontrivial N] (x : M) : Nontrivial ((smoothSheaf IM I M N).presheaf.st variable {IM I N} -@[simp] lemma smoothSheaf.eval_germ (U : Opens M) (x : U) +@[simp] lemma smoothSheaf.eval_germ (U : Opens M) (x : M) (hx : x ∈ U) (f : (smoothSheaf IM I M N).presheaf.obj (op U)) : - smoothSheaf.eval IM I N (x : M) ((smoothSheaf IM I M N).presheaf.germ x f) = f x := - TopCat.stalkToFiber_germ ((contDiffWithinAt_localInvariantProp IM I ⊤).localPredicate M N) _ _ _ + smoothSheaf.eval IM I N (x : M) ((smoothSheaf IM I M N).presheaf.germ U x hx f) = f ⟨x, hx⟩ := + TopCat.stalkToFiber_germ ((contDiffWithinAt_localInvariantProp IM I ⊤).localPredicate M N) _ _ _ _ lemma smoothSheaf.smooth_section {U : (Opens (TopCat.of M))ᵒᵖ} (f : (smoothSheaf IM I M N).presheaf.obj U) : @@ -333,12 +333,12 @@ def smoothSheafCommRing.eval (x : M) : (smoothSheafCommRing IM I M R).presheaf.s smoothSheafCommRing.evalAt _ _ _ _ _ _ := colimit.ι_desc _ _ -@[simp] lemma smoothSheafCommRing.evalHom_germ (U : Opens (TopCat.of M)) (x : U) +@[simp] lemma smoothSheafCommRing.evalHom_germ (U : Opens (TopCat.of M)) (x : M) (hx : x ∈ U) (f : (smoothSheafCommRing IM I M R).presheaf.obj (op U)) : smoothSheafCommRing.evalHom IM I M R (x : TopCat.of M) - ((smoothSheafCommRing IM I M R).presheaf.germ x f) - = f x := - congr_arg (fun a ↦ a f) <| smoothSheafCommRing.ι_evalHom IM I M R x ⟨U, x.2⟩ + ((smoothSheafCommRing IM I M R).presheaf.germ U x hx f) + = f ⟨x, hx⟩ := + congr_arg (fun a ↦ a f) <| smoothSheafCommRing.ι_evalHom IM I M R x ⟨U, hx⟩ @[simp, reassoc, elementwise] lemma smoothSheafCommRing.forgetStalk_inv_comp_eval (x : TopCat.of M) : @@ -372,10 +372,10 @@ instance [Nontrivial R] (x : M) : Nontrivial ((smoothSheafCommRing IM I M R).pre variable {IM I M R} -@[simp] lemma smoothSheafCommRing.eval_germ (U : Opens M) (x : U) +@[simp] lemma smoothSheafCommRing.eval_germ (U : Opens M) (x : M) (hx : x ∈ U) (f : (smoothSheafCommRing IM I M R).presheaf.obj (op U)) : - smoothSheafCommRing.eval IM I M R x ((smoothSheafCommRing IM I M R).presheaf.germ x f) - = f x := - smoothSheafCommRing.evalHom_germ IM I M R U x f + smoothSheafCommRing.eval IM I M R x ((smoothSheafCommRing IM I M R).presheaf.germ U x hx f) + = f ⟨x, hx⟩ := + smoothSheafCommRing.evalHom_germ IM I M R U x hx f end SmoothCommRing diff --git a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean index 5ed443618c56c..55142a16d8ebd 100644 --- a/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean +++ b/Mathlib/Geometry/Manifold/SmoothManifoldWithCorners.lean @@ -3,9 +3,11 @@ Copyright (c) 2019 Sébastien Gouëzel. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel -/ -import Mathlib.Geometry.Manifold.ChartedSpace +import Mathlib.Analysis.Convex.Normed import Mathlib.Analysis.Normed.Module.FiniteDimension import Mathlib.Analysis.Calculus.ContDiff.Basic +import Mathlib.Data.Bundle +import Mathlib.Geometry.Manifold.ChartedSpace /-! # Smooth manifolds (possibly with boundary or corners) @@ -80,6 +82,14 @@ but again in product manifolds the natural model with corners will not be this o one (and they are not defeq as `(fun p : E × F ↦ (p.1, p.2))` is not defeq to the identity). So, it is important to use the above incantation to maximize the applicability of theorems. +We also define `TangentSpace I (x : M)` as a type synonym of `E`, and `TangentBundle I M` as a +type synonym for `Π (x : M), TangentSpace I x` (in the form of an +abbrev of `Bundle.TotalSpace E (TangentSpace I : M → Type _)`). Apart from basic typeclasses on +`TangentSpace I x`, nothing is proved about them in this file, but it is useful to have them +available as definitions early on to get a clean import structure below. The smooth bundle structure +is defined in `VectorBundle.Tangent`, while the definition is used to talk about manifold +derivatives in `MFDeriv.Basic`, and neither file needs import the other. + ## Implementation notes We want to talk about manifolds modelled on a vector space, but also on manifolds with @@ -138,7 +148,7 @@ structure ModelWithCorners (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Ty [NormedAddCommGroup E] [NormedSpace 𝕜 E] (H : Type*) [TopologicalSpace H] extends PartialEquiv H E where source_eq : source = univ - unique_diff' : UniqueDiffOn 𝕜 toPartialEquiv.target + uniqueDiffOn' : UniqueDiffOn 𝕜 toPartialEquiv.target continuous_toFun : Continuous toFun := by continuity continuous_invFun : Continuous invFun := by continuity @@ -149,7 +159,7 @@ def modelWithCornersSelf (𝕜 : Type*) [NontriviallyNormedField 𝕜] (E : Type [NormedAddCommGroup E] [NormedSpace 𝕜 E] : ModelWithCorners 𝕜 E E where toPartialEquiv := PartialEquiv.refl E source_eq := rfl - unique_diff' := uniqueDiffOn_univ + uniqueDiffOn' := uniqueDiffOn_univ continuous_toFun := continuous_id continuous_invFun := continuous_id @@ -236,8 +246,11 @@ theorem target_eq : I.target = range (I : H → E) := by rw [← image_univ, ← I.source_eq] exact I.image_source_eq_target.symm -protected theorem unique_diff : UniqueDiffOn 𝕜 (range I) := - I.target_eq ▸ I.unique_diff' +protected theorem uniqueDiffOn : UniqueDiffOn 𝕜 (range I) := + I.target_eq ▸ I.uniqueDiffOn' + +@[deprecated (since := "2024-09-30")] +protected alias unique_diff := ModelWithCorners.uniqueDiffOn @[simp, mfld_simps] protected theorem left_inv (x : H) : I.symm (I x) = x := by refine I.left_inv' ?_; simp @@ -290,17 +303,26 @@ theorem symm_map_nhdsWithin_image {x : H} {s : Set H} : map I.symm (𝓝[I '' s] theorem symm_map_nhdsWithin_range (x : H) : map I.symm (𝓝[range I] I x) = 𝓝 x := by rw [← I.map_nhds_eq, map_map, I.symm_comp_self, map_id] -theorem unique_diff_preimage {s : Set H} (hs : IsOpen s) : +theorem uniqueDiffOn_preimage {s : Set H} (hs : IsOpen s) : UniqueDiffOn 𝕜 (I.symm ⁻¹' s ∩ range I) := by rw [inter_comm] - exact I.unique_diff.inter (hs.preimage I.continuous_invFun) + exact I.uniqueDiffOn.inter (hs.preimage I.continuous_invFun) + +@[deprecated (since := "2024-09-30")] +alias unique_diff_preimage := uniqueDiffOn_preimage -theorem unique_diff_preimage_source {β : Type*} [TopologicalSpace β] {e : PartialHomeomorph H β} : +theorem uniqueDiffOn_preimage_source {β : Type*} [TopologicalSpace β] {e : PartialHomeomorph H β} : UniqueDiffOn 𝕜 (I.symm ⁻¹' e.source ∩ range I) := - I.unique_diff_preimage e.open_source + I.uniqueDiffOn_preimage e.open_source + +@[deprecated (since := "2024-09-30")] +alias unique_diff_preimage_source := uniqueDiffOn_preimage_source -theorem unique_diff_at_image {x : H} : UniqueDiffWithinAt 𝕜 (range I) (I x) := - I.unique_diff _ (mem_range_self _) +theorem uniqueDiffWithinAt_image {x : H} : UniqueDiffWithinAt 𝕜 (range I) (I x) := + I.uniqueDiffOn _ (mem_range_self _) + +@[deprecated (since := "2024-09-30")] +alias unique_diff_at_image := uniqueDiffWithinAt_image theorem symm_continuousWithinAt_comp_right_iff {X} [TopologicalSpace X] {f : H → X} {s : Set H} {x : H} : @@ -369,9 +391,9 @@ def ModelWithCorners.prod {𝕜 : Type u} [NontriviallyNormedField 𝕜] {E : Ty invFun := fun x => (I.symm x.1, I'.symm x.2) source := { x | x.1 ∈ I.source ∧ x.2 ∈ I'.source } source_eq := by simp only [setOf_true, mfld_simps] - unique_diff' := I.unique_diff'.prod I'.unique_diff' - continuous_toFun := I.continuous_toFun.prod_map I'.continuous_toFun - continuous_invFun := I.continuous_invFun.prod_map I'.continuous_invFun } + uniqueDiffOn' := I.uniqueDiffOn'.prod I'.uniqueDiffOn' + continuous_toFun := I.continuous_toFun.prodMap I'.continuous_toFun + continuous_invFun := I.continuous_invFun.prodMap I'.continuous_invFun } /-- Given a finite family of `ModelWithCorners` `I i` on `(E i, H i)`, we define the model with corners `pi I` on `(Π i, E i, ModelPi H)`. See note [Manifold type tags] for explanation about @@ -382,7 +404,7 @@ def ModelWithCorners.pi {𝕜 : Type u} [NontriviallyNormedField 𝕜] {ι : Typ ModelWithCorners 𝕜 (∀ i, E i) (ModelPi H) where toPartialEquiv := PartialEquiv.pi fun i => (I i).toPartialEquiv source_eq := by simp only [pi_univ, mfld_simps] - unique_diff' := UniqueDiffOn.pi ι E _ _ fun i _ => (I i).unique_diff' + uniqueDiffOn' := UniqueDiffOn.pi ι E _ _ fun i _ => (I i).uniqueDiffOn' continuous_toFun := continuous_pi fun i => (I i).continuous.comp (continuous_apply i) continuous_invFun := continuous_pi fun i => (I i).continuous_symm.comp (continuous_apply i) @@ -1057,7 +1079,7 @@ theorem extChartAt_target (x : M) : theorem uniqueDiffOn_extChartAt_target (x : M) : UniqueDiffOn 𝕜 (extChartAt I x).target := by rw [extChartAt_target] - exact I.unique_diff_preimage (chartAt H x).open_target + exact I.uniqueDiffOn_preimage (chartAt H x).open_target theorem uniqueDiffWithinAt_extChartAt_target (x : M) : UniqueDiffWithinAt 𝕜 (extChartAt I x).target (extChartAt I x x) := @@ -1351,3 +1373,56 @@ lemma Manifold.locallyCompact_of_finiteDimensional exact ChartedSpace.locallyCompactSpace H M end Topology + +section TangentSpace + +/- We define the tangent space to `M` modelled on `I : ModelWithCorners 𝕜 E H` as a type synonym +for `E`. This is enough to define linear maps between tangent spaces, for instance derivatives, +but the interesting part is to define a manifold structure on the whole tangent bundle, which +requires that `M` is a smooth manifold with corners. The definition is put here to avoid importing +all the smooth bundle structure when defining manifold derivatives. -/ + +set_option linter.unusedVariables false in +/-- The tangent space at a point of the manifold `M`. It is just `E`. We could use instead +`(tangentBundleCore I M).to_topological_vector_bundle_core.fiber x`, but we use `E` to help the +kernel. +-/ +@[nolint unusedArguments] +def TangentSpace {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type u} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] (_x : M) : Type u := E +-- Porting note: was deriving TopologicalSpace, AddCommGroup, TopologicalAddGroup + +/- In general, the definition of `TangentSpace` is not reducible, so that type class inference +does not pick wrong instances. We record the right instances for them. -/ + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} + +instance : TopologicalSpace (TangentSpace I x) := inferInstanceAs (TopologicalSpace E) +instance : AddCommGroup (TangentSpace I x) := inferInstanceAs (AddCommGroup E) +instance : TopologicalAddGroup (TangentSpace I x) := inferInstanceAs (TopologicalAddGroup E) +instance : Module 𝕜 (TangentSpace I x) := inferInstanceAs (Module 𝕜 E) +instance : Inhabited (TangentSpace I x) := ⟨0⟩ + +variable (M) in +-- is empty if the base manifold is empty +/-- The tangent bundle to a smooth manifold, as a Sigma type. Defined in terms of +`Bundle.TotalSpace` to be able to put a suitable topology on it. -/ +-- Porting note(#5171): was nolint has_nonempty_instance +abbrev TangentBundle := + Bundle.TotalSpace E (TangentSpace I : M → Type _) + +end TangentSpace + +section Real + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] + {I : ModelWithCorners ℝ E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} + +instance : PathConnectedSpace (TangentSpace I x) := inferInstanceAs (PathConnectedSpace E) + +end Real diff --git a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean index ff5840676376f..10e4fe0a92fe3 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/SmoothSection.lean @@ -3,9 +3,10 @@ Copyright (c) 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.Basic -import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Geometry.Manifold.Algebra.LieGroup +import Mathlib.Geometry.Manifold.MFDeriv.Basic +import Mathlib.Topology.ContinuousMap.Basic +import Mathlib.Geometry.Manifold.VectorBundle.Basic /-! # Smooth sections diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean index fed71bc4299df..7c85fe03db9fd 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Tangent.lean @@ -4,16 +4,19 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Heather Macbeth -/ import Mathlib.Geometry.Manifold.VectorBundle.Basic -import Mathlib.Analysis.Convex.Normed /-! # Tangent bundles This file defines the tangent bundle as a smooth vector bundle. -Let `M` be a smooth manifold with corners with model `I` on `(E, H)`. We define the tangent bundle -of `M` using the `VectorBundleCore` construction indexed by the charts of `M` with fibers `E`. -Given two charts `i, j : PartialHomeomorph M H`, the coordinate change between `i` and `j` -at a point `x : M` is the derivative of the composite +Let `M` be a manifold with model `I` on `(E, H)`. The tangent space `TangentSpace I (x : M)` has +already been defined as a type synonym for `E`, and the tangent bundle `TangentBundle I M` as an +abbrev of `Bundle.TotalSpace E (TangentSpace I : M → Type _)`. + +In this file, when `M` is smooth, we construct a smooth vector bundle structure +on `TangentBundle I M` using the `VectorBundleCore` construction indexed by the charts of `M` +with fibers `E`. Given two charts `i, j : PartialHomeomorph M H`, the coordinate change +between `i` and `j` at a point `x : M` is the derivative of the composite ``` I.symm i.symm j I E -----> H -----> M --> H --> E @@ -21,12 +24,13 @@ E -----> H -----> M --> H --> E within the set `range I ⊆ E` at `I (i x) : E`. This defines a smooth vector bundle `TangentBundle` with fibers `TangentSpace`. -## Main definitions +## Main definitions and results -* `TangentSpace I M x` is the fiber of the tangent bundle at `x : M`, which is defined to be `E`. +* `tangentBundleCore I M` is the vector bundle core for the tangent bundle over `M`. -* `TangentBundle I M` is the total space of `TangentSpace I M`, proven to be a smooth vector - bundle. +* When `M` is a smooth manifold with corners, `TangentBundle I M` has a smooth vector bundle +structure over `M`. In particular, it is a topological space, a vector bundle, a fiber bundle, +and a smooth manifold. -/ @@ -55,7 +59,7 @@ theorem contDiffOn_fderiv_coord_change (i j : atlas H M) : have h : ((i.1.extend I).symm ≫ j.1.extend I).source ⊆ range I := by rw [i.1.extend_coord_change_source]; apply image_subset_range intro x hx - refine (ContDiffWithinAt.fderivWithin_right ?_ I.unique_diff le_top <| h hx).mono h + refine (ContDiffWithinAt.fderivWithin_right ?_ I.uniqueDiffOn le_top <| h hx).mono h refine (PartialHomeomorph.contDiffOn_extend_coord_change I (subset_maximalAtlas I j.2) (subset_maximalAtlas I i.2) x hx).mono_of_mem ?_ exact i.1.extend_coord_change_source_mem_nhdsWithin j.1 I hx @@ -65,7 +69,7 @@ variable (M) open SmoothManifoldWithCorners /-- Let `M` be a smooth manifold with corners with model `I` on `(E, H)`. -Then `VectorBundleCore I M` is the vector bundle core for the tangent bundle over `M`. +Then `tangentBundleCore I M` is the vector bundle core for the tangent bundle over `M`. It is indexed by the atlas of `M`, with fiber `E` and its change of coordinates from the chart `i` to the chart `j` at point `x : M` is the derivative of the composite ``` @@ -84,7 +88,7 @@ def tangentBundleCore : VectorBundleCore 𝕜 M E (atlas H M) where coordChange_self i x hx v := by simp only rw [Filter.EventuallyEq.fderivWithin_eq, fderivWithin_id', ContinuousLinearMap.id_apply] - · exact I.unique_diff_at_image + · exact I.uniqueDiffWithinAt_image · filter_upwards [i.1.extend_target_mem_nhdsWithin I hx] with y hy exact (i.1.extend I).right_inv hy · simp_rw [Function.comp_apply, i.1.extend_left_inv I hx] @@ -105,7 +109,7 @@ def tangentBundleCore : VectorBundleCore 𝕜 M E (atlas H M) where · exact (contDiffWithinAt_extend_coord_change' I (subset_maximalAtlas I j.2) (subset_maximalAtlas I i.2) hxj hxi).differentiableWithinAt le_top · intro x _; exact mem_range_self _ - · exact I.unique_diff_at_image + · exact I.uniqueDiffWithinAt_image · rw [Function.comp_apply, i.1.extend_left_inv I hxi] -- Porting note: moved to a separate `simp high` lemma b/c `simp` can simplify the LHS @@ -164,49 +168,12 @@ lemma continuousOn_tangentCoordChange (x y : M) : ContinuousOn (tangentCoordChan end tangentCoordChange -/-- The tangent space at a point of the manifold `M`. It is just `E`. We could use instead -`(tangentBundleCore I M).to_topological_vector_bundle_core.fiber x`, but we use `E` to help the -kernel. --/ -@[nolint unusedArguments] -def TangentSpace {𝕜} [NontriviallyNormedField 𝕜] {E} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M} [TopologicalSpace M] - [ChartedSpace H M] [SmoothManifoldWithCorners I M] (_x : M) : Type* := E --- Porting note: was deriving TopologicalSpace, AddCommGroup, TopologicalAddGroup - -instance {x : M} : TopologicalSpace (TangentSpace I x) := inferInstanceAs (TopologicalSpace E) -instance {x : M} : AddCommGroup (TangentSpace I x) := inferInstanceAs (AddCommGroup E) -instance {x : M} : TopologicalAddGroup (TangentSpace I x) := inferInstanceAs (TopologicalAddGroup E) - variable (M) --- is empty if the base manifold is empty -/-- The tangent bundle to a smooth manifold, as a Sigma type. Defined in terms of -`Bundle.TotalSpace` to be able to put a suitable topology on it. -/ --- Porting note(#5171): was nolint has_nonempty_instance -abbrev TangentBundle := - Bundle.TotalSpace E (TangentSpace I : M → Type _) - local notation "TM" => TangentBundle I M section TangentBundleInstances -/- In general, the definition of `TangentSpace` is not reducible, so that type class inference -does not pick wrong instances. In this section, we record the right instances for -them, noting in particular that the tangent bundle is a smooth manifold. -/ -section - -variable {M} -variable (x : M) - -instance : Module 𝕜 (TangentSpace I x) := inferInstanceAs (Module 𝕜 E) - -instance : Inhabited (TangentSpace I x) := ⟨0⟩ - --- Porting note: removed unneeded ContinuousAdd (TangentSpace I x) - -end - instance : TopologicalSpace TM := (tangentBundleCore I M).toTopologicalSpace @@ -448,13 +415,3 @@ theorem inTangentCoordinates_eq (f : N → M) (g : N → M') (ϕ : N → E →L[ end inTangentCoordinates end General - -section Real - -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] - {I : ModelWithCorners ℝ E H} {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - [SmoothManifoldWithCorners I M] - -instance {x : M} : PathConnectedSpace (TangentSpace I x) := by unfold TangentSpace; infer_instance - -end Real diff --git a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean index e99bb7ea3797f..3e3f2e4bb92fd 100644 --- a/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean +++ b/Mathlib/Geometry/Manifold/WhitneyEmbedding.lean @@ -31,7 +31,7 @@ variable {ι : Type uι} {E : Type uE} [NormedAddCommGroup E] [NormedSpace ℝ E [FiniteDimensional ℝ E] {H : Type uH} [TopologicalSpace H] {I : ModelWithCorners ℝ E H} {M : Type uM} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M] -open Function Filter FiniteDimensional Set +open Function Filter Module Set open scoped Manifold noncomputable section diff --git a/Mathlib/Geometry/RingedSpace/Basic.lean b/Mathlib/Geometry/RingedSpace/Basic.lean index 5b110af7a48ad..a1960cb7b7970 100644 --- a/Mathlib/Geometry/RingedSpace/Basic.lean +++ b/Mathlib/Geometry/RingedSpace/Basic.lean @@ -51,24 +51,24 @@ instance : CoeSort RingedSpace Type* where If the germ of a section `f` is a unit in the stalk at `x`, then `f` must be a unit on some small neighborhood around `x`. -/ -theorem isUnit_res_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) (x : U) - (h : IsUnit (X.presheaf.germ x f)) : - ∃ (V : Opens X) (i : V ⟶ U) (_ : x.1 ∈ V), IsUnit (X.presheaf.map i.op f) := by +theorem isUnit_res_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) (x : X) (hx : x ∈ U) + (h : IsUnit (X.presheaf.germ U x hx f)) : + ∃ (V : Opens X) (i : V ⟶ U) (_ : x ∈ V), IsUnit (X.presheaf.map i.op f) := by obtain ⟨g', heq⟩ := h.exists_right_inv - obtain ⟨V, hxV, g, rfl⟩ := X.presheaf.germ_exist x.1 g' + obtain ⟨V, hxV, g, rfl⟩ := X.presheaf.germ_exist x g' let W := U ⊓ V - have hxW : x.1 ∈ W := ⟨x.2, hxV⟩ + have hxW : x ∈ W := ⟨hx, hxV⟩ -- Porting note: `erw` can't write into `HEq`, so this is replaced with another `HEq` in the -- desired form - replace heq : (X.presheaf.germ ⟨x.val, hxW⟩) ((X.presheaf.map (U.infLELeft V).op) f * - (X.presheaf.map (U.infLERight V).op) g) = (X.presheaf.germ ⟨x.val, hxW⟩) 1 := by + replace heq : (X.presheaf.germ _ x hxW) ((X.presheaf.map (U.infLELeft V).op) f * + (X.presheaf.map (U.infLERight V).op) g) = (X.presheaf.germ _ x hxW) 1 := by dsimp [germ] - erw [map_mul, map_one, show X.presheaf.germ ⟨x, hxW⟩ ((X.presheaf.map (U.infLELeft V).op) f) = - X.presheaf.germ x f from X.presheaf.germ_res_apply (Opens.infLELeft U V) ⟨x.1, hxW⟩ f, - show X.presheaf.germ ⟨x, hxW⟩ (X.presheaf.map (U.infLERight V).op g) = - X.presheaf.germ ⟨x, hxV⟩ g from X.presheaf.germ_res_apply (Opens.infLERight U V) ⟨x.1, hxW⟩ g] + erw [map_mul, map_one, show X.presheaf.germ _ x hxW ((X.presheaf.map (U.infLELeft V).op) f) = + X.presheaf.germ U x hx f from X.presheaf.germ_res_apply (Opens.infLELeft U V) x hxW f, + show X.presheaf.germ _ x hxW (X.presheaf.map (U.infLERight V).op g) = + X.presheaf.germ _ x hxV g from X.presheaf.germ_res_apply (Opens.infLERight U V) x hxW g] exact heq - obtain ⟨W', hxW', i₁, i₂, heq'⟩ := X.presheaf.germ_eq x.1 hxW hxW _ _ heq + obtain ⟨W', hxW', i₁, i₂, heq'⟩ := X.presheaf.germ_eq x hxW hxW _ _ heq use W', i₁ ≫ Opens.infLELeft U V, hxW' rw [(X.presheaf.map i₂.op).map_one, (X.presheaf.map i₁.op).map_mul] at heq' rw [← comp_apply, ← X.presheaf.map_comp, ← comp_apply, ← X.presheaf.map_comp, ← op_comp] at heq' @@ -76,9 +76,9 @@ theorem isUnit_res_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) (x : /-- If a section `f` is a unit in each stalk, `f` must be a unit. -/ theorem isUnit_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) - (h : ∀ x : U, IsUnit (X.presheaf.germ x f)) : IsUnit f := by + (h : ∀ (x) (hx : x ∈ U), IsUnit (X.presheaf.germ U x hx f)) : IsUnit f := by -- We pick a cover of `U` by open sets `V x`, such that `f` is a unit on each `V x`. - choose V iVU m h_unit using fun x : U => X.isUnit_res_of_isUnit_germ U f x (h x) + choose V iVU m h_unit using fun x : U => X.isUnit_res_of_isUnit_germ U f x x.2 (h x.1 x.2) have hcover : U ≤ iSup V := by intro x hxU -- Porting note: in Lean3 `rw` is sufficient @@ -89,27 +89,20 @@ theorem isUnit_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) have ic : IsCompatible (sheaf X).val V g := by intro x y apply section_ext X.sheaf (V x ⊓ V y) - rintro ⟨z, hzVx, hzVy⟩ - erw [germ_res_apply, germ_res_apply] - apply (IsUnit.mul_right_inj (h ⟨z, (iVU x).le hzVx⟩)).mp + rintro z ⟨hzVx, hzVy⟩ + rw [germ_res_apply, germ_res_apply] + apply (h z ((iVU x).le hzVx)).mul_right_inj.mp -- Porting note: now need explicitly typing the rewrites - rw [← show X.presheaf.germ ⟨z, hzVx⟩ (X.presheaf.map (iVU x).op f) = - X.presheaf.germ ⟨z, ((iVU x) ⟨z, hzVx⟩).2⟩ f from - X.presheaf.germ_res_apply (iVU x) ⟨z, hzVx⟩ f] + rw [← X.presheaf.germ_res_apply (iVU x) z hzVx f] -- Porting note: change was not necessary in Lean3 - change X.presheaf.germ ⟨z, hzVx⟩ _ * (X.presheaf.germ ⟨z, hzVx⟩ _) = - X.presheaf.germ ⟨z, hzVx⟩ _ * X.presheaf.germ ⟨z, hzVy⟩ (g y) + change X.presheaf.germ _ z hzVx _ * (X.presheaf.germ _ z hzVx _) = + X.presheaf.germ _ z hzVx _ * X.presheaf.germ _ z hzVy (g y) rw [← RingHom.map_mul, - congr_arg (X.presheaf.germ (⟨z, hzVx⟩ : V x)) (hg x), - -- Porting note: now need explicitly typing the rewrites - show X.presheaf.germ ⟨z, hzVx⟩ (X.presheaf.map (iVU x).op f) = - X.presheaf.germ ⟨z, ((iVU x) ⟨z, hzVx⟩).2⟩ f from X.presheaf.germ_res_apply _ _ f, - -- Porting note: now need explicitly typing the rewrites - ← show X.presheaf.germ ⟨z, hzVy⟩ (X.presheaf.map (iVU y).op f) = - X.presheaf.germ ⟨z, ((iVU x) ⟨z, hzVx⟩).2⟩ f from - X.presheaf.germ_res_apply (iVU y) ⟨z, hzVy⟩ f, + congr_arg (X.presheaf.germ (V x) z hzVx) (hg x), + X.presheaf.germ_res_apply _ _ _ f, + ← X.presheaf.germ_res_apply (iVU y) z hzVy f, ← RingHom.map_mul, - congr_arg (X.presheaf.germ (⟨z, hzVy⟩ : V y)) (hg y), RingHom.map_one, RingHom.map_one] + congr_arg (X.presheaf.germ (V y) z hzVy) (hg y), RingHom.map_one, RingHom.map_one] -- We claim that these local inverses glue together to a global inverse of `f`. obtain ⟨gl, gl_spec, -⟩ := X.sheaf.existsUnique_gluing' V U iVU hcover g ic apply isUnit_of_mul_eq_one f gl @@ -122,58 +115,54 @@ theorem isUnit_of_isUnit_germ (U : Opens X) (f : X.presheaf.obj (op U)) `x` is a unit. -/ def basicOpen {U : Opens X} (f : X.presheaf.obj (op U)) : Opens X where - -- Porting note: `coe` does not work - carrier := Subtype.val '' { x : U | IsUnit (X.presheaf.germ x f) } + carrier := { x : X | ∃ (hx : x ∈ U), IsUnit (X.presheaf.germ U x hx f) } is_open' := by rw [isOpen_iff_forall_mem_open] - rintro _ ⟨x, hx, rfl⟩ - obtain ⟨V, i, hxV, hf⟩ := X.isUnit_res_of_isUnit_germ U f x hx + rintro x ⟨hxU, hx⟩ + obtain ⟨V, i, hxV, hf⟩ := X.isUnit_res_of_isUnit_germ U f x hxU hx use V.1 refine ⟨?_, V.2, hxV⟩ intro y hy - use (⟨y, i.le hy⟩ : U) - rw [Set.mem_setOf_eq] - constructor - · convert RingHom.isUnit_map (X.presheaf.germ ⟨y, hy⟩) hf - exact (X.presheaf.germ_res_apply i ⟨y, hy⟩ f).symm - · rfl + use i.le hy + convert RingHom.isUnit_map (X.presheaf.germ _ y hy) hf + exact (X.presheaf.germ_res_apply i y hy f).symm +theorem mem_basicOpen {U : Opens X} (f : X.presheaf.obj (op U)) (x : X) (hx : x ∈ U) : + x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ U x hx f) := + ⟨Exists.choose_spec, (⟨hx, ·⟩)⟩ + +/-- A variant of `mem_basicOpen` with bundled `x : U`. -/ @[simp] -theorem mem_basicOpen {U : Opens X} (f : X.presheaf.obj (op U)) (x : U) : - ↑x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ x f) := by - constructor - · rintro ⟨x, hx, a⟩; cases Subtype.eq a; exact hx - · intro h; exact ⟨x, h, rfl⟩ +theorem mem_basicOpen' {U : Opens X} (f : X.presheaf.obj (op U)) (x : U) : + ↑x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ U x.1 x.2 f) := + mem_basicOpen X f x.1 x.2 @[simp] theorem mem_top_basicOpen (f : X.presheaf.obj (op ⊤)) (x : X) : - x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.germ ⟨x, show x ∈ (⊤ : Opens X) by trivial⟩ f) := - mem_basicOpen X f ⟨x, _⟩ + x ∈ X.basicOpen f ↔ IsUnit (X.presheaf.Γgerm x f) := + mem_basicOpen X f x .intro theorem basicOpen_le {U : Opens X} (f : X.presheaf.obj (op U)) : X.basicOpen f ≤ U := by - rintro _ ⟨x, _, rfl⟩; exact x.2 + rintro x ⟨h, _⟩; exact h /-- The restriction of a section `f` to the basic open of `f` is a unit. -/ theorem isUnit_res_basicOpen {U : Opens X} (f : X.presheaf.obj (op U)) : IsUnit (X.presheaf.map (@homOfLE (Opens X) _ _ _ (X.basicOpen_le f)).op f) := by apply isUnit_of_isUnit_germ - rintro ⟨_, ⟨x, (hx : IsUnit _), rfl⟩⟩ + rintro x ⟨hxU, hx⟩ convert hx - convert X.presheaf.germ_res_apply _ _ _ + convert X.presheaf.germ_res_apply _ _ _ _ @[simp] theorem basicOpen_res {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) (f : X.presheaf.obj U) : @basicOpen X (unop V) (X.presheaf.map i f) = unop V ⊓ @basicOpen X (unop U) f := by - induction U using Opposite.rec' - induction V using Opposite.rec' - let g := i.unop; have : i = g.op := rfl; clear_value g; subst this - ext; constructor - · rintro ⟨x, hx : IsUnit _, rfl⟩ - erw [X.presheaf.germ_res_apply _ _ _] at hx - exact ⟨x.2, g x, hx, rfl⟩ - · rintro ⟨hxV, x, hx, rfl⟩ - refine ⟨⟨x, hxV⟩, (?_ : IsUnit _), rfl⟩ - erw [X.presheaf.germ_res_apply _ _ _] + ext x; constructor + · rintro ⟨hxV, hx⟩ + rw [X.presheaf.germ_res_apply'] at hx + exact ⟨hxV, i.unop.le hxV, hx⟩ + · rintro ⟨hxV, _, hx⟩ + refine ⟨hxV, ?_⟩ + rw [X.presheaf.germ_res_apply'] exact hx -- This should fire before `basicOpen_res`. @@ -193,11 +182,10 @@ theorem basicOpen_res_eq {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) [IsIso i] (f : X. @[simp] theorem basicOpen_mul {U : Opens X} (f g : X.presheaf.obj (op U)) : X.basicOpen (f * g) = X.basicOpen f ⊓ X.basicOpen g := by - ext1 - dsimp [RingedSpace.basicOpen] - rw [← Set.image_inter Subtype.coe_injective] ext x - simp [map_mul, Set.mem_image] + by_cases hx : x ∈ U + · simp [mem_basicOpen (hx := hx)] + · simp [mt (basicOpen_le X _ ·) hx] @[simp] lemma basicOpen_pow {U : Opens X} (f : X.presheaf.obj (op U)) (n : ℕ) (h : 0 < n) : @@ -212,7 +200,7 @@ theorem basicOpen_of_isUnit {U : Opens X} {f : X.presheaf.obj (op U)} (hf : IsUn apply le_antisymm · exact X.basicOpen_le f intro x hx - erw [X.mem_basicOpen f (⟨x, hx⟩ : U)] + rw [SetLike.mem_coe, X.mem_basicOpen f x hx] exact RingHom.isUnit_map _ hf /-- diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean index 75e798757aa2f..30d7e6eaa301e 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace.lean @@ -89,10 +89,11 @@ noncomputable def Hom.stalkMap {X Y : LocallyRingedSpace.{u}} (f : Hom X Y) (x : Y.presheaf.stalk (f.1.1 x) ⟶ X.presheaf.stalk x := f.val.stalkMap x -instance {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) (x : X) : IsLocalRingHom (f.stalkMap x) := +instance isLocalRingHomStalkMap {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) (x : X) : + IsLocalRingHom (f.stalkMap x) := f.2 x -instance {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) (x : X) : +instance isLocalRingHomValStalkMap {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) (x : X) : IsLocalRingHom (f.val.stalkMap x) := f.2 x @@ -108,7 +109,7 @@ instance (X : LocallyRingedSpace.{u}) : Inhabited (Hom X X) := def comp {X Y Z : LocallyRingedSpace.{u}} (f : Hom X Y) (g : Hom Y Z) : Hom X Z := ⟨f.val ≫ g.val, fun x => by erw [PresheafedSpace.stalkMap.comp] - exact @isLocalRingHom_comp _ _ _ _ _ _ _ _ (f.2 _) (g.2 _)⟩ + exact @RingHom.isLocalRingHom_comp _ _ _ _ _ _ _ _ (f.2 _) (g.2 _)⟩ /-- The category of locally ringed spaces. -/ instance : Category LocallyRingedSpace.{u} where @@ -258,21 +259,6 @@ instance {X : LocallyRingedSpace} : Unique (∅ ⟶ X) where noncomputable def emptyIsInitial : Limits.IsInitial (∅ : LocallyRingedSpace.{u}) := Limits.IsInitial.ofUnique _ -theorem preimage_basicOpen {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) {U : Opens Y} - (s : Y.presheaf.obj (op U)) : - (Opens.map f.1.base).obj (Y.toRingedSpace.basicOpen s) = - @RingedSpace.basicOpen X.toRingedSpace ((Opens.map f.1.base).obj U) (f.1.c.app _ s) := by - ext x - constructor - · rintro ⟨⟨y, hyU⟩, hy : IsUnit _, rfl : y = _⟩ - erw [RingedSpace.mem_basicOpen _ _ ⟨x, show x ∈ (Opens.map f.1.base).obj U from hyU⟩, - ← PresheafedSpace.stalkMap_germ_apply] - exact (f.val.stalkMap _).isUnit_map hy - · rintro ⟨y, hy : IsUnit _, rfl⟩ - erw [RingedSpace.mem_basicOpen _ _ ⟨f.1.base y.1, y.2⟩] - erw [← PresheafedSpace.stalkMap_germ_apply] at hy - exact (isUnit_map_iff (f.val.stalkMap _) _).mp hy - -- This actually holds for all ringed spaces with nontrivial stalks. theorem basicOpen_zero (X : LocallyRingedSpace.{u}) (U : Opens X.carrier) : X.toRingedSpace.basicOpen (0 : X.presheaf.obj <| op U) = ⊥ := by @@ -300,7 +286,7 @@ lemma basicOpen_eq_bot_of_isNilpotent (X : LocallyRingedSpace.{u}) (U : Opens X. instance component_nontrivial (X : LocallyRingedSpace.{u}) (U : Opens X.carrier) [hU : Nonempty U] : Nontrivial (X.presheaf.obj <| op U) := - (X.presheaf.germ hU.some).domain_nontrivial + (X.presheaf.germ _ _ hU.some.2).domain_nontrivial @[simp] lemma iso_hom_val_base_inv_val_base {X Y : LocallyRingedSpace.{u}} (e : X ≅ Y) : @@ -398,30 +384,33 @@ lemma stalkMap_inv_hom_apply (e : X ≅ Y) (x : X) (y) : X.presheaf.stalkSpecializes (specializes_of_eq <| by simp) y := DFunLike.congr_fun (stalkMap_inv_hom e x) y -@[reassoc] -lemma stalkMap_germ (U : Opens Y) - (x : (Opens.map f.val.base).obj U) : - Y.presheaf.germ ⟨f.val.base x.val, x.property⟩ ≫ f.stalkMap x.val = - f.val.c.app (op U) ≫ X.presheaf.germ x := - PresheafedSpace.stalkMap_germ f.val U x - -lemma stalkMap_germ_apply (U : Opens Y) (x : (Opens.map f.val.base).obj U) (y) : - f.stalkMap x.val (Y.presheaf.germ ⟨f.val.base x.val, x.property⟩ y) = - X.presheaf.germ x (f.val.c.app (op U) y) := - PresheafedSpace.stalkMap_germ_apply f.val U x y - @[reassoc (attr := simp)] -lemma stalkMap_germ' (U : Opens Y) (x : X) (hx : f.val.base x ∈ U) : - Y.presheaf.germ ⟨f.val.base x, hx⟩ ≫ f.stalkMap x = - f.val.c.app (op U) ≫ X.presheaf.germ (U := (Opens.map f.val.base).obj U) ⟨x, hx⟩ := - PresheafedSpace.stalkMap_germ' f.val U x hx +lemma stalkMap_germ (U : Opens Y) (x : X) (hx : f.val.base x ∈ U) : + Y.presheaf.germ U (f.val.base x) hx ≫ f.stalkMap x = + f.val.c.app (op U) ≫ X.presheaf.germ ((Opens.map f.1.base).obj U) x hx := + PresheafedSpace.stalkMap_germ f.val U x hx -@[simp] -lemma stalkMap_germ'_apply - (U : Opens Y) (x : X) (hx : f.val.base x ∈ U) (y : Y.presheaf.obj (op U)) : - f.stalkMap x (Y.presheaf.germ (U := U) ⟨f.val.base x, hx⟩ y) = - X.presheaf.germ (U := (Opens.map f.val.base).obj U) ⟨x, hx⟩ (f.val.c.app (op U) y) := - PresheafedSpace.stalkMap_germ_apply f.val U ⟨x, hx⟩ y +lemma stalkMap_germ_apply (U : Opens Y) (x : X) (hx : f.val.base x ∈ U) (y) : + f.stalkMap x (Y.presheaf.germ U (f.val.base x) hx y) = + X.presheaf.germ ((Opens.map f.1.base).obj U) x hx (f.val.c.app (op U) y) := + PresheafedSpace.stalkMap_germ_apply f.val U x hx y + +theorem preimage_basicOpen {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) {U : Opens Y} + (s : Y.presheaf.obj (op U)) : + (Opens.map f.1.base).obj (Y.toRingedSpace.basicOpen s) = + @RingedSpace.basicOpen X.toRingedSpace ((Opens.map f.1.base).obj U) (f.1.c.app _ s) := by + ext x + constructor + · rintro ⟨hxU, hx⟩ + rw [SetLike.mem_coe, X.toRingedSpace.mem_basicOpen _ _ hxU] + delta toRingedSpace + rw [← stalkMap_germ_apply] + exact (f.val.stalkMap _).isUnit_map hx + · rintro ⟨hxU, hx⟩ + simp only [Opens.map_coe, Set.mem_preimage, SetLike.mem_coe, toRingedSpace] at hx ⊢ + rw [RingedSpace.mem_basicOpen _ s (f.1.base x) hxU] + rw [← stalkMap_germ_apply] at hx + exact (isUnit_map_iff (f.val.stalkMap _) _).mp hx variable {U : TopCat} (X : LocallyRingedSpace.{u}) {f : U ⟶ X.toTopCat} (h : OpenEmbedding f) (V : Opens U) (x : U) (hx : x ∈ V) @@ -434,25 +423,25 @@ def restrictStalkIso : (X.restrict h).presheaf.stalk x ≅ X.presheaf.stalk (f x @[reassoc (attr := simp)] lemma restrictStalkIso_hom_eq_germ : - (X.restrict h).presheaf.germ ⟨x, hx⟩ ≫ (X.restrictStalkIso h x).hom = - X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ := + (X.restrict h).presheaf.germ _ x hx ≫ (X.restrictStalkIso h x).hom = + X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ := PresheafedSpace.restrictStalkIso_hom_eq_germ X.toPresheafedSpace h V x hx lemma restrictStalkIso_hom_eq_germ_apply (y) : - (X.restrictStalkIso h x).hom ((X.restrict h).presheaf.germ ⟨x, hx⟩ y) = - X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ y := + (X.restrictStalkIso h x).hom ((X.restrict h).presheaf.germ _ x hx y) = + X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ y := PresheafedSpace.restrictStalkIso_hom_eq_germ_apply X.toPresheafedSpace h V x hx y @[reassoc (attr := simp)] lemma restrictStalkIso_inv_eq_germ : - X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ ≫ - (X.restrictStalkIso h x).inv = (X.restrict h).presheaf.germ ⟨x, hx⟩ := + X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ ≫ + (X.restrictStalkIso h x).inv = (X.restrict h).presheaf.germ _ x hx := PresheafedSpace.restrictStalkIso_inv_eq_germ X.toPresheafedSpace h V x hx lemma restrictStalkIso_inv_eq_germ_apply (y) : (X.restrictStalkIso h x).inv - (X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ y) = - (X.restrict h).presheaf.germ ⟨x, hx⟩ y := + (X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ y) = + (X.restrict h).presheaf.germ _ x hx y := PresheafedSpace.restrictStalkIso_inv_eq_germ_apply X.toPresheafedSpace h V x hx y lemma restrictStalkIso_inv_eq_ofRestrict : diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean index b94c92ea5a9a2..60b7cb47198e4 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/HasColimits.lean @@ -40,10 +40,9 @@ theorem colimit_exists_rep (x : colimit (C := SheafedSpace C) F) : (isColimitOfPreserves (SheafedSpace.forget _) (colimit.isColimit F)) x instance {X Y : SheafedSpace C} (f g : X ⟶ Y) : Epi (coequalizer.π f g).base := by - erw [← - show _ = (coequalizer.π f g).base from - ι_comp_coequalizerComparison f g (SheafedSpace.forget C)] - rw [← PreservesCoequalizer.iso_hom] + rw [← show _ = (coequalizer.π f g).base from + ι_comp_coequalizerComparison f g (SheafedSpace.forget C), + ← PreservesCoequalizer.iso_hom] apply epi_comp end SheafedSpace @@ -215,7 +214,7 @@ instance coequalizer_π_stalk_isLocalRingHom (x : Y) : constructor rintro a ha rcases TopCat.Presheaf.germ_exist _ _ a with ⟨U, hU, s, rfl⟩ - erw [PresheafedSpace.stalkMap_germ_apply (coequalizer.π f.1 g.1 : _) U ⟨_, hU⟩] at ha + rw [PresheafedSpace.stalkMap_germ_apply (coequalizer.π f.1 g.1 : _) U _ hU] at ha let V := imageBasicOpen f g U s have hV : (coequalizer.π f.1 g.1).base ⁻¹' ((coequalizer.π f.1 g.1).base '' V.1) = V.1 := imageBasicOpen_image_preimage f g U s @@ -226,10 +225,10 @@ instance coequalizer_π_stalk_isLocalRingHom (x : Y) : imageBasicOpen_image_open f g U s have VleU : (⟨(coequalizer.π f.val g.val).base '' V.1, V_open⟩ : TopologicalSpace.Opens _) ≤ U := Set.image_subset_iff.mpr (Y.toRingedSpace.basicOpen_le _) - have hxV : x ∈ V := ⟨⟨_, hU⟩, ha, rfl⟩ - erw [← - (coequalizer f.val g.val).presheaf.germ_res_apply (homOfLE VleU) - ⟨_, @Set.mem_image_of_mem _ _ (coequalizer.π f.val g.val).base x V.1 hxV⟩ s] + have hxV : x ∈ V := ⟨hU, ha⟩ + rw [← + (coequalizer f.val g.val).presheaf.germ_res_apply (homOfLE VleU) _ + (@Set.mem_image_of_mem _ _ (coequalizer.π f.val g.val).base x V.1 hxV) s] apply RingHom.isUnit_map rw [← isUnit_map_iff ((coequalizer.π f.val g.val : _).c.app _), ← comp_apply, NatTrans.naturality, comp_apply, ← isUnit_map_iff (Y.presheaf.map (eqToHom hV').op)] @@ -247,6 +246,8 @@ noncomputable def coequalizer : LocallyRingedSpace where localRing x := by obtain ⟨y, rfl⟩ := (TopCat.epi_iff_surjective (coequalizer.π f.val g.val).base).mp inferInstance x + -- TODO: this instance was found automatically before #6045 + have _ : IsLocalRingHom ((coequalizer.π f.val g.val).stalkMap y) := inferInstance exact ((coequalizer.π f.val g.val : _).stalkMap y).domain_localRing /-- The explicit coequalizer cofork of locally ringed spaces. -/ @@ -275,9 +276,12 @@ noncomputable def coequalizerCoforkIsColimit : IsColimit (coequalizerCofork f g) -- but this is no longer possible set h := _ change IsLocalRingHom h - suffices IsLocalRingHom (((coequalizerCofork f g).π.val.stalkMap _).comp h) from - isLocalRingHom_of_comp _ ((coequalizerCofork f g).π.val.stalkMap _) - change IsLocalRingHom (_ ≫ (coequalizerCofork f g).π.val.stalkMap y) + suffices _ : IsLocalRingHom (((coequalizerCofork f g).π.1.stalkMap _).comp h) by + apply isLocalRingHom_of_comp _ ((coequalizerCofork f g).π.1.stalkMap _) + -- note to reviewers: this `change` is now more brittle because it now has to fully resolve + -- the type to be able to search for `MonoidHomClass`, even though of course all homs in + -- `CommRingCat` are clearly such + change IsLocalRingHom (h ≫ (coequalizerCofork f g).π.val.stalkMap y) erw [← PresheafedSpace.stalkMap.comp] apply isLocalRingHom_stalkMap_congr _ _ (coequalizer.π_desc s.π.1 e).symm y infer_instance diff --git a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean index e4395a78b6708..44d7e9d141d92 100644 --- a/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean +++ b/Mathlib/Geometry/RingedSpace/LocallyRingedSpace/ResidueField.lean @@ -52,7 +52,7 @@ If we interpret sections over `U` as functions of `X` defined on `U`, then this corresponds to evaluation at `x`. -/ def evaluation (x : U) : X.presheaf.obj (op U) ⟶ X.residueField x := - X.presheaf.germ x ≫ LocalRing.residue _ + X.presheaf.germ U x.1 x.2 ≫ LocalRing.residue _ /-- The global evaluation map from `Γ(X, ⊤)` to the residue field at `x`. -/ def Γevaluation (x : X) : X.presheaf.obj (op ⊤) ⟶ X.residueField x := @@ -61,7 +61,7 @@ def Γevaluation (x : X) : X.presheaf.obj (op ⊤) ⟶ X.residueField x := @[simp] lemma evaluation_eq_zero_iff_not_mem_basicOpen (x : U) (f : X.presheaf.obj (op U)) : X.evaluation x f = 0 ↔ x.val ∉ X.toRingedSpace.basicOpen f := by - rw [X.toRingedSpace.mem_basicOpen f x, ← not_iff_not, not_not] + rw [X.toRingedSpace.mem_basicOpen f x.1 x.2, ← not_iff_not, not_not] exact (LocalRing.residue_ne_zero_iff_isUnit _) lemma evaluation_ne_zero_iff_mem_basicOpen (x : U) (f : X.presheaf.obj (op U)) : @@ -77,7 +77,15 @@ lemma Γevaluation_ne_zero_iff_mem_basicOpen (x : X) (f : X.presheaf.obj (op ⊤ X.Γevaluation x f ≠ 0 ↔ x ∈ X.toRingedSpace.basicOpen f := evaluation_ne_zero_iff_mem_basicOpen X ⟨x, show x ∈ ⊤ by trivial⟩ f -variable {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) +variable {X Y : LocallyRingedSpace.{u}} (f : X ⟶ Y) (x : X) + +-- TODO: This instance is found before #6045. +-- We need this strange instance for `residueFieldMap`, the type of `F` must be fixed +-- like this. The instance `IsLocalRingHom (f.stalkMap x)` already exists, but does not work for +-- `residueFieldMap`. +instance : IsLocalRingHom (F := Y.presheaf.stalk (f.val.base x) →+* X.presheaf.stalk x) + (f.stalkMap x) := + f.2 x /-- If `X ⟶ Y` is a morphism of locally ringed spaces and `x` a point of `X`, we obtain a morphism of residue fields in the other direction. -/ @@ -101,6 +109,8 @@ lemma residueFieldMap_comp {Z : LocallyRingedSpace.{u}} (g : Y ⟶ Z) (x : X) : simp only [comp_val, SheafedSpace.comp_base, Function.comp_apply, residueFieldMap] simp_rw [stalkMap_comp] haveI : IsLocalRingHom (g.stalkMap (f.val.base x)) := inferInstance + -- TODO: This instance is found before #6045. + haveI : IsLocalRingHom (f.stalkMap x) := inferInstance apply LocalRing.ResidueField.map_comp @[reassoc] @@ -112,7 +122,7 @@ lemma evaluation_naturality {V : Opens Y} (x : (Opens.map f.1.base).obj V) : rw [Category.assoc] ext a simp only [comp_apply] - erw [LocalRing.ResidueField.map_residue, PresheafedSpace.stalkMap_germ'_apply] + erw [LocalRing.ResidueField.map_residue, PresheafedSpace.stalkMap_germ_apply] rfl lemma evaluation_naturality_apply {V : Opens Y} (x : (Opens.map f.1.base).obj V) diff --git a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean index 5c5349f4adc95..408d39010d7d3 100644 --- a/Mathlib/Geometry/RingedSpace/OpenImmersion.lean +++ b/Mathlib/Geometry/RingedSpace/OpenImmersion.lean @@ -118,7 +118,7 @@ noncomputable def isoRestrict : X ≅ Y.restrict H.base_open := dsimp simp only [NatTrans.naturality_assoc, TopCat.Presheaf.pushforward_obj_obj, TopCat.Presheaf.pushforward_obj_map, Quiver.Hom.unop_op, Category.assoc] - erw [← X.presheaf.map_comp, ← X.presheaf.map_comp] + rw [← X.presheaf.map_comp, ← X.presheaf.map_comp] congr 1 @[reassoc (attr := simp)] @@ -167,7 +167,7 @@ noncomputable def invApp (U : Opens X) : @[simp, reassoc] theorem inv_naturality {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) : - X.presheaf.map i ≫ H.invApp (unop V) = + X.presheaf.map i ≫ H.invApp _ (unop V) = invApp f (unop U) ≫ Y.presheaf.map (opensFunctor f |>.op.map i) := by simp only [invApp, ← Category.assoc] rw [IsIso.comp_inv_eq] @@ -179,11 +179,11 @@ theorem inv_naturality {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) : instance (U : Opens X) : IsIso (invApp f U) := by delta invApp; infer_instance theorem inv_invApp (U : Opens X) : - inv (H.invApp U) = + inv (H.invApp _ U) = f.c.app (op (opensFunctor f |>.obj U)) ≫ X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := by - rw [← cancel_epi (H.invApp U), IsIso.hom_inv_id] + rw [← cancel_epi (H.invApp _ U), IsIso.hom_inv_id] delta invApp simp [← Functor.map_comp] @@ -195,7 +195,7 @@ theorem invApp_app (U : Opens X) : @[simp, reassoc] theorem app_invApp (U : Opens Y) : - f.c.app (op U) ≫ H.invApp ((Opens.map f.base).obj U) = + f.c.app (op U) ≫ H.invApp _ ((Opens.map f.base).obj U) = Y.presheaf.map ((homOfLE (Set.image_preimage_subset f.base U.1)).op : op U ⟶ op (opensFunctor f |>.obj ((Opens.map f.base).obj U))) := by @@ -244,7 +244,7 @@ instance ofRestrict {X : TopCat} (Y : PresheafedSpace C) {f : X ⟶ Y.carrier} @[elementwise, simp] theorem ofRestrict_invApp {C : Type*} [Category C] (X : PresheafedSpace C) {Y : TopCat} {f : Y ⟶ TopCat.of X.carrier} (h : OpenEmbedding f) (U : Opens (X.restrict h).carrier) : - (PresheafedSpace.IsOpenImmersion.ofRestrict X h).invApp U = 𝟙 _ := by + (PresheafedSpace.IsOpenImmersion.ofRestrict X h).invApp _ U = 𝟙 _ := by delta invApp rw [IsIso.comp_inv_eq, Category.id_comp] change X.presheaf.map _ = X.presheaf.map _ @@ -290,7 +290,7 @@ def pullbackConeOfLeftFst : base := pullback.fst _ _ c := { app := fun U => - hf.invApp (unop U) ≫ + hf.invApp _ (unop U) ≫ g.c.app (op (hf.base_open.isOpenMap.functor.obj (unop U))) ≫ Y.presheaf.map (eqToHom @@ -772,21 +772,21 @@ noncomputable def invApp (U : Opens X) : @[reassoc (attr := simp)] theorem inv_naturality {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) : - X.presheaf.map i ≫ H.invApp (unop V) = - H.invApp (unop U) ≫ Y.presheaf.map (opensFunctor f |>.op.map i) := + X.presheaf.map i ≫ H.invApp _ (unop V) = + H.invApp _ (unop U) ≫ Y.presheaf.map (opensFunctor f |>.op.map i) := PresheafedSpace.IsOpenImmersion.inv_naturality f i -instance (U : Opens X) : IsIso (H.invApp U) := by delta invApp; infer_instance +instance (U : Opens X) : IsIso (H.invApp _ U) := by delta invApp; infer_instance theorem inv_invApp (U : Opens X) : - inv (H.invApp U) = + inv (H.invApp _ U) = f.c.app (op (opensFunctor f |>.obj U)) ≫ X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := PresheafedSpace.IsOpenImmersion.inv_invApp f U @[reassoc (attr := simp)] theorem invApp_app (U : Opens X) : - H.invApp U ≫ f.c.app (op (opensFunctor f |>.obj U)) = + H.invApp _ U ≫ f.c.app (op (opensFunctor f |>.obj U)) = X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := PresheafedSpace.IsOpenImmersion.invApp_app f U @@ -794,7 +794,7 @@ attribute [elementwise] invApp_app @[reassoc (attr := simp)] theorem app_invApp (U : Opens Y) : - f.c.app (op U) ≫ H.invApp ((Opens.map f.base).obj U) = + f.c.app (op U) ≫ H.invApp _ ((Opens.map f.base).obj U) = Y.presheaf.map ((homOfLE (Set.image_preimage_subset f.base U.1)).op : op U ⟶ op (opensFunctor f |>.obj ((Opens.map f.base).obj U))) := @@ -818,7 +818,7 @@ instance ofRestrict {X : TopCat} (Y : SheafedSpace C) {f : X ⟶ Y.carrier} @[elementwise, simp] theorem ofRestrict_invApp {C : Type*} [Category C] (X : SheafedSpace C) {Y : TopCat} {f : Y ⟶ TopCat.of X.carrier} (h : OpenEmbedding f) (U : Opens (X.restrict h).carrier) : - (SheafedSpace.IsOpenImmersion.ofRestrict X h).invApp U = 𝟙 _ := + (SheafedSpace.IsOpenImmersion.ofRestrict X h).invApp _ U = 𝟙 _ := PresheafedSpace.IsOpenImmersion.ofRestrict_invApp _ h U /-- An open immersion is an iso if the underlying continuous map is epi. -/ @@ -946,6 +946,8 @@ instance mono : Mono f := instance : SheafedSpace.IsOpenImmersion (LocallyRingedSpace.forgetToSheafedSpace.map f) := H +-- note to reviewers: is there a `count_heartbeats` for this? +set_option synthInstance.maxHeartbeats 30000 in /-- An explicit pullback cone over `cospan f g` if `f` is an open immersion. -/ def pullbackConeOfLeft : PullbackCone f g := by refine PullbackCone.mk ?_ @@ -964,6 +966,7 @@ def pullbackConeOfLeft : PullbackCone f g := by instance : LocallyRingedSpace.IsOpenImmersion (pullbackConeOfLeft f g).snd := show PresheafedSpace.IsOpenImmersion (Y.toPresheafedSpace.ofRestrict _) by infer_instance +set_option synthInstance.maxHeartbeats 80000 in /-- The constructed `pullbackConeOfLeft` is indeed limiting. -/ def pullbackConeOfLeftIsLimit : IsLimit (pullbackConeOfLeft f g) := PullbackCone.isLimitAux' _ fun s => by @@ -982,7 +985,8 @@ def pullbackConeOfLeftIsLimit : IsLimit (pullbackConeOfLeft f g) := change _ = _ ≫ s.snd.1.stalkMap x at this rw [PresheafedSpace.stalkMap.comp, ← IsIso.eq_inv_comp] at this rw [this] - infer_instance + -- TODO: This instance is found by `infer_instance` before #6045. + apply CommRingCat.isLocalRingHom_comp · intro m _ h₂ rw [← cancel_mono (pullbackConeOfLeft f g).snd] exact h₂.trans <| LocallyRingedSpace.Hom.ext @@ -1154,7 +1158,7 @@ is an open immersion iff every stalk map is an iso. theorem of_stalk_iso {X Y : LocallyRingedSpace} (f : X ⟶ Y) (hf : OpenEmbedding f.1.base) [stalk_iso : ∀ x : X.1, IsIso (f.stalkMap x)] : LocallyRingedSpace.IsOpenImmersion f := - SheafedSpace.IsOpenImmersion.of_stalk_iso hf (H := stalk_iso) + SheafedSpace.IsOpenImmersion.of_stalk_iso _ hf (H := stalk_iso) end OfStalkIso @@ -1180,21 +1184,21 @@ noncomputable def invApp (U : Opens X) : @[reassoc (attr := simp)] theorem inv_naturality {U V : (Opens X)ᵒᵖ} (i : U ⟶ V) : - X.presheaf.map i ≫ H.invApp (unop V) = - H.invApp (unop U) ≫ Y.presheaf.map (opensFunctor f |>.op.map i) := + X.presheaf.map i ≫ H.invApp _ (unop V) = + H.invApp _ (unop U) ≫ Y.presheaf.map (opensFunctor f |>.op.map i) := PresheafedSpace.IsOpenImmersion.inv_naturality f.1 i -instance (U : Opens X) : IsIso (H.invApp U) := by delta invApp; infer_instance +instance (U : Opens X) : IsIso (H.invApp _ U) := by delta invApp; infer_instance theorem inv_invApp (U : Opens X) : - inv (H.invApp U) = + inv (H.invApp _ U) = f.1.c.app (op (opensFunctor f |>.obj U)) ≫ X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := PresheafedSpace.IsOpenImmersion.inv_invApp f.1 U @[reassoc (attr := simp)] theorem invApp_app (U : Opens X) : - H.invApp U ≫ f.1.c.app (op (opensFunctor f |>.obj U)) = + H.invApp _ U ≫ f.1.c.app (op (opensFunctor f |>.obj U)) = X.presheaf.map (eqToHom (by simp [Opens.map, Set.preimage_image_eq _ H.base_open.inj])) := PresheafedSpace.IsOpenImmersion.invApp_app f.1 U @@ -1202,7 +1206,7 @@ attribute [elementwise] invApp_app @[reassoc (attr := simp)] theorem app_invApp (U : Opens Y) : - f.1.c.app (op U) ≫ H.invApp ((Opens.map f.1.base).obj U) = + f.1.c.app (op U) ≫ H.invApp _ ((Opens.map f.1.base).obj U) = Y.presheaf.map ((homOfLE (Set.image_preimage_subset f.1.base U.1)).op : op U ⟶ op (opensFunctor f |>.obj ((Opens.map f.1.base).obj U))) := @@ -1211,7 +1215,7 @@ theorem app_invApp (U : Opens Y) : /-- A variant of `app_inv_app` that gives an `eqToHom` instead of `homOfLe`. -/ @[reassoc] theorem app_inv_app' (U : Opens Y) (hU : (U : Set Y) ⊆ Set.range f.1.base) : - f.1.c.app (op U) ≫ H.invApp ((Opens.map f.1.base).obj U) = + f.1.c.app (op U) ≫ H.invApp _ ((Opens.map f.1.base).obj U) = Y.presheaf.map (eqToHom <| le_antisymm (Set.image_preimage_subset f.1.base U.1) <| @@ -1226,7 +1230,7 @@ instance ofRestrict {X : TopCat} (Y : LocallyRingedSpace) {f : X ⟶ Y.carrier} @[elementwise, simp] theorem ofRestrict_invApp (X : LocallyRingedSpace) {Y : TopCat} {f : Y ⟶ TopCat.of X.carrier} (h : OpenEmbedding f) (U : Opens (X.restrict h).carrier) : - (LocallyRingedSpace.IsOpenImmersion.ofRestrict X h).invApp U = 𝟙 _ := + (LocallyRingedSpace.IsOpenImmersion.ofRestrict X h).invApp _ U = 𝟙 _ := PresheafedSpace.IsOpenImmersion.ofRestrict_invApp _ h U instance stalk_iso (x : X) : IsIso (f.stalkMap x) := diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean index dd988d85c537d..43d40b52b040c 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace.lean @@ -58,7 +58,7 @@ attribute [coe] PresheafedSpace.carrier -- Porting note: we add this instance, as Lean does not reliably use the `CoeOut` instance above -- in downstream files. -instance : CoeSort (PresheafedSpace C) Type* where coe := fun X => X.carrier +instance : CoeSort (PresheafedSpace C) Type* where coe X := X.carrier -- Porting note: the following lemma is removed because it is a syntactic tauto /-@[simp] diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean index b5ac976467db8..93d358233ae90 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/Gluing.lean @@ -140,16 +140,15 @@ theorem pullback_base (i j k : D.J) (S : Set (D.V (i, j)).carrier) : rw [Set.image_comp] -- Porting note: `rw` to `erw` on `coe_comp` erw [coe_comp] - erw [Set.preimage_comp, Set.image_preimage_eq, TopCat.pullback_snd_image_fst_preimage] - -- now `erw` after #13170 + rw [Set.preimage_comp, Set.image_preimage_eq, TopCat.pullback_snd_image_fst_preimage] · rfl - erw [← TopCat.epi_iff_surjective] -- now `erw` after #13170 + rw [← TopCat.epi_iff_surjective] infer_instance /-- The red and the blue arrows in ![this diagram](https://i.imgur.com/0GiBUh6.png) commute. -/ @[simp, reassoc] theorem f_invApp_f_app (i j k : D.J) (U : Opens (D.V (i, j)).carrier) : - (D.f_open i j).invApp U ≫ (D.f i k).c.app _ = + (D.f_open i j).invApp _ U ≫ (D.f i k).c.app _ = (π₁ i, j, k).c.app (op U) ≫ (π₂⁻¹ i, j, k) (unop _) ≫ (D.V _).presheaf.map @@ -161,7 +160,7 @@ theorem f_invApp_f_app (i j k : D.J) (U : Opens (D.V (i, j)).carrier) : apply pullback_base)) := by have := PresheafedSpace.congr_app (@pullback.condition _ _ _ _ _ (D.f i j) (D.f i k) _) dsimp only [comp_c_app] at this - rw [← cancel_epi (inv ((D.f_open i j).invApp U)), IsIso.inv_hom_id_assoc, + rw [← cancel_epi (inv ((D.f_open i j).invApp _ U)), IsIso.inv_hom_id_assoc, IsOpenImmersion.inv_invApp] simp_rw [Category.assoc] erw [(π₁ i, j, k).c.naturality_assoc, reassoc_of% this, ← Functor.map_comp_assoc, @@ -271,7 +270,7 @@ def opensImagePreimageMap (i j : D.J) (U : Opens (D.U i).carrier) : (Opens.map (𝖣.ι j).base).obj ((D.ι_openEmbedding i).isOpenMap.functor.obj U)) := (D.f i j).c.app (op U) ≫ (D.t j i).c.app _ ≫ - (D.f_open j i).invApp (unop _) ≫ + (D.f_open j i).invApp _ (unop _) ≫ (𝖣.U j).presheaf.map (eqToHom (D.ι_image_preimage_eq i j U)).op theorem opensImagePreimageMap_app' (i j k : D.J) (U : Opens (D.U i).carrier) : @@ -334,9 +333,9 @@ def ιInvAppπApp {i : D.J} (U : Opens (D.U i).carrier) (j) : rw [Set.preimage_preimage] change (D.f j k ≫ 𝖣.ι j).base ⁻¹' _ = _ -- Porting note: used to be `congr 3` - refine congr_arg (· ⁻¹' _) ?_ - convert congr_arg (ContinuousMap.toFun (α := D.V ⟨j, k⟩) (β := D.glued) ·) ?_ - refine congr_arg (PresheafedSpace.Hom.base (C := C) ·) ?_ + suffices D.f j k ≫ D.ι j = colimit.ι D.diagram.multispan (WalkingMultispan.left (j, k)) by + rw [this] + rfl exact colimit.w 𝖣.diagram.multispan (WalkingMultispan.Hom.fst (j, k)) · exact D.opensImagePreimageMap i j U @@ -368,11 +367,11 @@ def ιInvApp {i : D.J} (U : Opens (D.U i).carrier) : (D.f j k).c.app _ ≫ (D.V (j, k)).presheaf.map (eqToHom _) = D.opensImagePreimageMap _ _ _ ≫ ((D.f k j).c.app _ ≫ (D.t j k).c.app _) ≫ (D.V (j, k)).presheaf.map (eqToHom _) - erw [opensImagePreimageMap_app_assoc] + rw [opensImagePreimageMap_app_assoc] simp_rw [Category.assoc] - erw [opensImagePreimageMap_app_assoc, (D.t j k).c.naturality_assoc] - rw [snd_invApp_t_app_assoc] - erw [← PresheafedSpace.comp_c_app_assoc] + rw [opensImagePreimageMap_app_assoc, (D.t j k).c.naturality_assoc, + snd_invApp_t_app_assoc, + ← PresheafedSpace.comp_c_app_assoc] -- light-blue = green is relatively easy since the part that differs does not involve -- partial inverses. have : @@ -380,19 +379,21 @@ def ιInvApp {i : D.J} (U : Opens (D.U i).carrier) : (pullbackSymmetry _ _).hom ≫ (π₁ j, i, k) ≫ D.t j i ≫ D.f i j := by rw [← 𝖣.t_fac_assoc, 𝖣.t'_comp_eq_pullbackSymmetry_assoc, pullbackSymmetry_hom_comp_snd_assoc, pullback.condition, 𝖣.t_fac_assoc] - rw [congr_app this] - erw [PresheafedSpace.comp_c_app_assoc (pullbackSymmetry _ _).hom] + rw [congr_app this, + PresheafedSpace.comp_c_app_assoc (pullbackSymmetry _ _).hom] simp_rw [Category.assoc] congr 1 - rw [← IsIso.eq_inv_comp] - erw [IsOpenImmersion.inv_invApp] + rw [← IsIso.eq_inv_comp, + IsOpenImmersion.inv_invApp] simp_rw [Category.assoc] erw [NatTrans.naturality_assoc, ← PresheafedSpace.comp_c_app_assoc, congr_app (pullbackSymmetry_hom_comp_snd _ _)] simp_rw [Category.assoc] erw [IsOpenImmersion.inv_naturality_assoc, IsOpenImmersion.inv_naturality_assoc, IsOpenImmersion.inv_naturality_assoc, IsOpenImmersion.app_invApp_assoc] - repeat' erw [← (D.V (j, k)).presheaf.map_comp] + rw [← (D.V (j, k)).presheaf.map_comp] + erw [← (D.V (j, k)).presheaf.map_comp] + repeat rw [← (D.V (j, k)).presheaf.map_comp] -- Porting note: was just `congr` exact congr_arg ((D.V (j, k)).presheaf.map ·) rfl } } @@ -436,11 +437,27 @@ abbrev ιInvAppπEqMap {i : D.J} (U : Opens (D.U i).carrier) := theorem π_ιInvApp_π (i j : D.J) (U : Opens (D.U i).carrier) : D.diagramOverOpenπ U i ≫ D.ιInvAppπEqMap U ≫ D.ιInvApp U ≫ D.diagramOverOpenπ U j = D.diagramOverOpenπ U j := by - -- Porting note: originally, the proof of monotonicity was left a blank and proved in the end - -- but Lean 4 doesn't like this any more, so the proof is restructured - rw [← @cancel_mono (f := (componentwiseDiagram 𝖣.diagram.multispan _).map - (Quiver.Hom.op (WalkingMultispan.Hom.snd (i, j))) ≫ 𝟙 _) _ _ (by - rw [Category.comp_id] + rw [← @cancel_mono + (f := (componentwiseDiagram 𝖣.diagram.multispan _).map + (Quiver.Hom.op (WalkingMultispan.Hom.snd (i, j))) ≫ 𝟙 _) ..] + · simp_rw [Category.assoc] + rw [limit.w_assoc] + erw [limit.lift_π_assoc] + rw [Category.comp_id, Category.comp_id] + change _ ≫ _ ≫ (_ ≫ _) ≫ _ = _ + rw [congr_app (D.t_id _), id_c_app] + simp_rw [Category.assoc] + rw [← Functor.map_comp_assoc] + -- Porting note (#11224): change `rw` to `erw` + erw [IsOpenImmersion.inv_naturality_assoc] + erw [IsOpenImmersion.app_invApp_assoc] + iterate 3 rw [← Functor.map_comp_assoc] + rw [NatTrans.naturality_assoc] + erw [← (D.V (i, j)).presheaf.map_comp] + convert + limit.w (componentwiseDiagram 𝖣.diagram.multispan _) + (Quiver.Hom.op (WalkingMultispan.Hom.fst (i, j))) + · rw [Category.comp_id] apply (config := { allowSynthFailures := true }) mono_comp change Mono ((_ ≫ D.f j i).c.app _) rw [comp_c_app] @@ -448,24 +465,7 @@ theorem π_ιInvApp_π (i j : D.J) (U : Opens (D.U i).carrier) : · erw [D.ι_image_preimage_eq i j U] infer_instance · have : IsIso (D.t i j).c := by apply c_isIso_of_iso - infer_instance)] - simp_rw [Category.assoc] - rw [limit.w_assoc] - erw [limit.lift_π_assoc] - rw [Category.comp_id, Category.comp_id] - change _ ≫ _ ≫ (_ ≫ _) ≫ _ = _ - rw [congr_app (D.t_id _), id_c_app] - simp_rw [Category.assoc] - rw [← Functor.map_comp_assoc] - -- Porting note (#11224): change `rw` to `erw` - erw [IsOpenImmersion.inv_naturality_assoc] - erw [IsOpenImmersion.app_invApp_assoc] - iterate 3 rw [← Functor.map_comp_assoc] - rw [NatTrans.naturality_assoc] - erw [← (D.V (i, j)).presheaf.map_comp] - convert - limit.w (componentwiseDiagram 𝖣.diagram.multispan _) - (Quiver.Hom.op (WalkingMultispan.Hom.fst (i, j))) + infer_instance /-- `ιInvApp` is the inverse of `D.ι i` on `U`. -/ theorem π_ιInvApp_eq_id (i : D.J) (U : Opens (D.U i).carrier) : diff --git a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean index 3ce2bceb89768..ce942b2c84104 100644 --- a/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean +++ b/Mathlib/Geometry/RingedSpace/PresheafedSpace/HasColimits.lean @@ -326,9 +326,9 @@ theorem colimitPresheafObjIsoComponentwiseLimit_inv_ι_app (F : J ⥤ Presheafed rw [Iso.trans_inv, Iso.trans_inv, Iso.app_inv, sheafIsoOfIso_inv, pushforwardToOfIso_app, congr_app (Iso.symm_inv _)] dsimp - rw [map_id, comp_id, assoc, assoc, assoc, NatTrans.naturality] - erw [← comp_c_app_assoc] - rw [congr_app (colimit.isoColimitCocone_ι_hom _ _), assoc] + rw [map_id, comp_id, assoc, assoc, assoc, NatTrans.naturality, + ← comp_c_app_assoc, + congr_app (colimit.isoColimitCocone_ι_hom _ _), assoc] erw [limitObjIsoLimitCompEvaluation_inv_π_app_assoc, limMap_π_assoc] -- Porting note: `convert` doesn't work due to meta variable, so change to a `suffices` block set f := _ diff --git a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean index 637e73b1c7aaa..b77aabfada5a7 100644 --- a/Mathlib/Geometry/RingedSpace/SheafedSpace.lean +++ b/Mathlib/Geometry/RingedSpace/SheafedSpace.lean @@ -47,7 +47,7 @@ namespace SheafedSpace instance coeCarrier : CoeOut (SheafedSpace C) TopCat where coe X := X.carrier instance coeSort : CoeSort (SheafedSpace C) Type* where - coe := fun X => X.1 + coe X := X.1 /-- Extract the `sheaf C (X : Top)` from a `SheafedSpace C`. -/ def sheaf (X : SheafedSpace C) : Sheaf C (X : TopCat) := @@ -226,7 +226,8 @@ lemma hom_stalk_ext {X Y : SheafedSpace C} (f g : X ⟶ Y) (h : f.base = g.base) obtain rfl : f = g := h congr ext U s - refine section_ext X.sheaf _ _ _ fun x ↦ show X.presheaf.germ x _ = X.presheaf.germ x _ from ?_ + refine section_ext X.sheaf _ _ _ fun x hx ↦ + show X.presheaf.germ _ x _ _ = X.presheaf.germ _ x _ _ from ?_ erw [← PresheafedSpace.stalkMap_germ_apply ⟨f, fc⟩, ← PresheafedSpace.stalkMap_germ_apply ⟨f, gc⟩] simp [h'] diff --git a/Mathlib/Geometry/RingedSpace/Stalks.lean b/Mathlib/Geometry/RingedSpace/Stalks.lean index 858441ca519fa..12c20e0348392 100644 --- a/Mathlib/Geometry/RingedSpace/Stalks.lean +++ b/Mathlib/Geometry/RingedSpace/Stalks.lean @@ -43,16 +43,13 @@ def Hom.stalkMap {X Y : PresheafedSpace.{_, _, v} C} (α : Hom X Y) (x : X) : @[elementwise, reassoc] theorem stalkMap_germ {X Y : PresheafedSpace.{_, _, v} C} (α : X ⟶ Y) (U : Opens Y) - (x : (Opens.map α.base).obj U) : - Y.presheaf.germ ⟨α.base x.1, x.2⟩ ≫ α.stalkMap ↑x = α.c.app (op U) ≫ X.presheaf.germ x := by + (x : X) (hx : α x ∈ U) : + Y.presheaf.germ U (α x) hx ≫ α.stalkMap x = α.c.app (op U) ≫ + X.presheaf.germ ((Opens.map α.base).obj U) x hx := by rw [Hom.stalkMap, stalkFunctor_map_germ_assoc, stalkPushforward_germ] -@[simp, elementwise, reassoc] -theorem stalkMap_germ' {X Y : PresheafedSpace.{_, _, v} C} - (α : X ⟶ Y) (U : Opens Y) (x : X) (hx : α.base x ∈ U) : - Y.presheaf.germ ⟨α.base x, hx⟩ ≫ α.stalkMap x = α.c.app (op U) ≫ - X.presheaf.germ (U := (Opens.map α.base).obj U) ⟨x, hx⟩ := - stalkMap_germ α U ⟨x, hx⟩ +@[deprecated (since := "2024-07-30")] alias stalkMap_germ' := stalkMap_germ +@[deprecated (since := "2024-07-30")] alias stalkMap_germ'_assoc := stalkMap_germ section Restrict @@ -71,8 +68,8 @@ def restrictStalkIso {U : TopCat} (X : PresheafedSpace.{_, _, v} C) {f : U ⟶ ( @[elementwise, reassoc] theorem restrictStalkIso_hom_eq_germ {U : TopCat} (X : PresheafedSpace.{_, _, v} C) {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (V : Opens U) (x : U) (hx : x ∈ V) : - (X.restrict h).presheaf.germ ⟨x, hx⟩ ≫ (restrictStalkIso X h x).hom = - X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ := + (X.restrict h).presheaf.germ _ x hx ≫ (restrictStalkIso X h x).hom = + X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ := colimit.ι_pre ((OpenNhds.inclusion (f x)).op ⋙ X.presheaf) (h.isOpenMap.functorNhds x).op (op ⟨V, hx⟩) @@ -81,9 +78,9 @@ theorem restrictStalkIso_hom_eq_germ {U : TopCat} (X : PresheafedSpace.{_, _, v} @[simp, elementwise, reassoc] theorem restrictStalkIso_inv_eq_germ {U : TopCat} (X : PresheafedSpace.{_, _, v} C) {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (V : Opens U) (x : U) (hx : x ∈ V) : - X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ ≫ + X.presheaf.germ (h.isOpenMap.functor.obj V) (f x) ⟨x, hx, rfl⟩ ≫ (restrictStalkIso X h x).inv = - (X.restrict h).presheaf.germ ⟨x, hx⟩ := by + (X.restrict h).presheaf.germ _ x hx := by rw [← restrictStalkIso_hom_eq_germ, Category.assoc, Iso.hom_inv_id, Category.comp_id] theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C) @@ -115,7 +112,7 @@ theorem id (X : PresheafedSpace.{_, _, v} C) (x : X) : (𝟙 X : X ⟶ X).stalkMap x = 𝟙 (X.presheaf.stalk x) := by dsimp [Hom.stalkMap] simp only [stalkPushforward.id] - erw [← map_comp] + rw [← map_comp] convert (stalkFunctor C x).map_id X.presheaf ext simp only [id_c, id_comp, Pushforward.id_hom_app, op_obj, eqToHom_refl, map_id] diff --git a/Mathlib/GroupTheory/CommutingProbability.lean b/Mathlib/GroupTheory/CommutingProbability.lean index c02743ac71a50..dc3739fd84c36 100644 --- a/Mathlib/GroupTheory/CommutingProbability.lean +++ b/Mathlib/GroupTheory/CommutingProbability.lean @@ -68,7 +68,7 @@ theorem commProb_pos [h : Nonempty M] : 0 < commProb M := (pow_pos (Nat.cast_pos.mpr Finite.card_pos) 2) theorem commProb_le_one : commProb M ≤ 1 := by - refine div_le_one_of_le ?_ (sq_nonneg (Nat.card M : ℚ)) + refine div_le_one_of_le₀ ?_ (sq_nonneg (Nat.card M : ℚ)) rw [← Nat.cast_pow, Nat.cast_le, sq, ← Nat.card_prod] apply Finite.card_subtype_le @@ -118,7 +118,7 @@ theorem Subgroup.commProb_quotient_le [H.Normal] : commProb (G ⧸ H) ≤ commPr variable (G) theorem inv_card_commutator_le_commProb : (↑(Nat.card (commutator G)))⁻¹ ≤ commProb G := - (inv_pos_le_iff_one_le_mul (Nat.cast_pos.mpr Finite.card_pos)).mpr + (inv_le_iff_one_le_mul₀ (Nat.cast_pos.mpr Finite.card_pos)).mpr (le_trans (ge_of_eq (commProb_eq_one_iff.mpr ⟨(Abelianization.commGroup G).mul_comm⟩)) (commutator G).commProb_quotient_le) @@ -131,6 +131,7 @@ lemma commProb_odd {n : ℕ} (hn : Odd n) : qify [show 2 ∣ n + 3 by rw [Nat.dvd_iff_mod_eq_zero, Nat.add_mod, Nat.odd_iff.mp hn]] rw [div_div, ← mul_assoc] congr + norm_num private lemma div_two_lt {n : ℕ} (h0 : n ≠ 0) : n / 2 < n := Nat.div_lt_self (Nat.pos_of_ne_zero h0) (lt_add_one 1) diff --git a/Mathlib/GroupTheory/Congruence/Basic.lean b/Mathlib/GroupTheory/Congruence/Basic.lean index a3011ab4ba7d6..fe6cfe5261d0a 100644 --- a/Mathlib/GroupTheory/Congruence/Basic.lean +++ b/Mathlib/GroupTheory/Congruence/Basic.lean @@ -110,12 +110,11 @@ variable [Mul M] [Mul N] [Mul P] (c : Con M) instance : Inhabited (Con M) := ⟨conGen EmptyRelation⟩ --- 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 (M → Prop) where coe c := c.r - coe_injective' := fun x y h => by + coe_injective' x y h := by rcases x with ⟨⟨x, _⟩, _⟩ rcases y with ⟨⟨y, _⟩, _⟩ have : x = y := h diff --git a/Mathlib/GroupTheory/Coset/Basic.lean b/Mathlib/GroupTheory/Coset/Basic.lean index 6143225812daa..44bb4b0f21528 100644 --- a/Mathlib/GroupTheory/Coset/Basic.lean +++ b/Mathlib/GroupTheory/Coset/Basic.lean @@ -235,7 +235,7 @@ def leftRel : Setoid α := variable {s} @[to_additive] -theorem leftRel_apply {x y : α} : @Setoid.r _ (leftRel s) x y ↔ x⁻¹ * y ∈ s := +theorem leftRel_apply {x y : α} : leftRel s x y ↔ x⁻¹ * y ∈ s := calc (∃ a : s.op, y * MulOpposite.unop a = x) ↔ ∃ a : s, y * a = x := s.equivOp.symm.exists_congr_left @@ -246,13 +246,13 @@ theorem leftRel_apply {x y : α} : @Setoid.r _ (leftRel s) x y ↔ x⁻¹ * y variable (s) @[to_additive] -theorem leftRel_eq : @Setoid.r _ (leftRel s) = fun x y => x⁻¹ * y ∈ s := +theorem leftRel_eq : ⇑(leftRel s) = fun x y => x⁻¹ * y ∈ s := funext₂ <| by simp only [eq_iff_iff] apply leftRel_apply theorem leftRel_r_eq_leftCosetEquivalence : - @Setoid.r _ (QuotientGroup.leftRel s) = LeftCosetEquivalence s := by + ⇑(QuotientGroup.leftRel s) = LeftCosetEquivalence s := by ext rw [leftRel_eq] exact (leftCoset_eq_iff s).symm @@ -279,7 +279,7 @@ def rightRel : Setoid α := variable {s} @[to_additive] -theorem rightRel_apply {x y : α} : @Setoid.r _ (rightRel s) x y ↔ y * x⁻¹ ∈ s := +theorem rightRel_apply {x y : α} : rightRel s x y ↔ y * x⁻¹ ∈ s := calc (∃ a : s, (a : α) * y = x) ↔ ∃ a : s, y * x⁻¹ = a⁻¹ := by simp only [mul_inv_eq_iff_eq_mul, Subgroup.coe_inv, eq_inv_mul_iff_mul_eq] @@ -288,13 +288,13 @@ theorem rightRel_apply {x y : α} : @Setoid.r _ (rightRel s) x y ↔ y * x⁻¹ variable (s) @[to_additive] -theorem rightRel_eq : @Setoid.r _ (rightRel s) = fun x y => y * x⁻¹ ∈ s := +theorem rightRel_eq : ⇑(rightRel s) = fun x y => y * x⁻¹ ∈ s := funext₂ <| by simp only [eq_iff_iff] apply rightRel_apply theorem rightRel_r_eq_rightCosetEquivalence : - @Setoid.r _ (QuotientGroup.rightRel s) = RightCosetEquivalence s := by + ⇑(QuotientGroup.rightRel s) = RightCosetEquivalence s := by ext rw [rightRel_eq] exact (rightCoset_eq_iff s).symm @@ -391,7 +391,7 @@ instance (s : Subgroup α) : Inhabited (α ⧸ s) := @[to_additive] protected theorem eq {a b : α} : (a : α ⧸ s) = b ↔ a⁻¹ * b ∈ s := calc - _ ↔ @Setoid.r _ (leftRel s) a b := Quotient.eq'' + _ ↔ leftRel s a b := Quotient.eq'' _ ↔ _ := by rw [leftRel_apply] @[to_additive (attr := deprecated (since := "2024-08-04"))] alias eq' := QuotientGroup.eq @@ -402,6 +402,21 @@ theorem out_eq' (a : α ⧸ s) : mk a.out' = a := variable (s) +/-- Given a subgroup `s`, the function that sends a subgroup `t` to the pair consisting of +its intersection with `s` and its image in the quotient `α ⧸ s` is strictly monotone, even though +it is not injective in general. -/ +@[to_additive QuotientAddGroup.strictMono_comap_prod_image "Given an additive subgroup `s`, +the function that sends an additive subgroup `t` to the pair consisting of +its intersection with `s` and its image in the quotient `α ⧸ s` +is strictly monotone, even though it is not injective in general."] +theorem strictMono_comap_prod_image : + StrictMono fun t : Subgroup α ↦ (t.comap s.subtype, mk (s := s) '' t) := by + refine fun t₁ t₂ h ↦ ⟨⟨Subgroup.comap_mono h.1, Set.image_mono h.1⟩, + mt (fun ⟨le1, le2⟩ a ha ↦ ?_) h.2⟩ + obtain ⟨a', h', eq⟩ := le2 ⟨_, ha, rfl⟩ + convert ← t₁.mul_mem h' (@le1 ⟨_, QuotientGroup.eq.1 eq⟩ <| t₂.mul_mem (t₂.inv_mem <| h.1 h') ha) + apply mul_inv_cancel_left + /- It can be useful to write `obtain ⟨h, H⟩ := mk_out'_eq_mul ...`, and then `rw [H]` or `simp_rw [H]` or `simp only [H]`. In order for `simp_rw` and `simp only` to work, this lemma is stated in terms of an arbitrary `h : s`, rather than the specific `h = g⁻¹ * (mk g).out'`. -/ diff --git a/Mathlib/GroupTheory/CosetCover.lean b/Mathlib/GroupTheory/CosetCover.lean index c9cefdcb06558..03164c5973c5e 100644 --- a/Mathlib/GroupTheory/CosetCover.lean +++ b/Mathlib/GroupTheory/CosetCover.lean @@ -343,7 +343,7 @@ theorem exists_index_le_card_of_leftCoset_cover : | inl hindex => rwa [hindex, Nat.cast_zero, inv_zero, inv_pos, Nat.cast_pos] | inr hindex => - exact inv_lt_inv_of_lt (by exact_mod_cast hs') (by exact_mod_cast h i hi ⟨hindex⟩) + exact inv_strictAnti₀ (by exact_mod_cast hs') (by exact_mod_cast h i hi ⟨hindex⟩) apply (Finset.sum_lt_sum_of_nonempty hs hlt).trans_eq rw [Finset.sum_const, nsmul_eq_mul, mul_inv_cancel₀ (Nat.cast_ne_zero.mpr hs'.ne')] diff --git a/Mathlib/GroupTheory/Coxeter/Inversion.lean b/Mathlib/GroupTheory/Coxeter/Inversion.lean index b07693855316a..18946d5bd27dc 100644 --- a/Mathlib/GroupTheory/Coxeter/Inversion.lean +++ b/Mathlib/GroupTheory/Coxeter/Inversion.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mitchell Lee -/ import Mathlib.GroupTheory.Coxeter.Length -import Mathlib.Data.ZMod.Parity import Mathlib.Data.List.GetD /-! diff --git a/Mathlib/GroupTheory/DoubleCoset.lean b/Mathlib/GroupTheory/DoubleCoset.lean index 5973451afc4e5..771be71a00bb9 100644 --- a/Mathlib/GroupTheory/DoubleCoset.lean +++ b/Mathlib/GroupTheory/DoubleCoset.lean @@ -131,7 +131,7 @@ theorem mk_eq_of_doset_eq {H K : Subgroup G} {a b : G} (h : doset a H K = doset rw [eq] exact mem_doset.mp (h.symm ▸ mem_doset_self H K b) -theorem disjoint_out' {H K : Subgroup G} {a b : Quotient H.1 K} : +theorem disjoint_out' {H K : Subgroup G} {a b : Quotient H K} : a ≠ b → Disjoint (doset a.out' H K) (doset b.out' (H : Set G) K) := by contrapose! intro h @@ -172,19 +172,17 @@ theorem doset_union_leftCoset (H K : Subgroup G) (a : G) : simp only [hxy, ← mul_assoc, hy, one_mul, inv_mul_cancel, Subgroup.coe_mk, inv_mul_cancel_right] theorem left_bot_eq_left_quot (H : Subgroup G) : - Quotient (⊥ : Subgroup G).1 (H : Set G) = (G ⧸ H) := by + Quotient (⊥ : Subgroup G) (H : Set G) = (G ⧸ H) := by unfold Quotient congr ext simp_rw [← bot_rel_eq_leftRel H] - rfl theorem right_bot_eq_right_quot (H : Subgroup G) : - Quotient (H.1 : Set G) (⊥ : Subgroup G) = _root_.Quotient (QuotientGroup.rightRel H) := by + Quotient (H : Set G) (⊥ : Subgroup G) = _root_.Quotient (QuotientGroup.rightRel H) := by unfold Quotient congr ext simp_rw [← rel_bot_eq_right_group_rel H] - rfl end Doset diff --git a/Mathlib/GroupTheory/Exponent.lean b/Mathlib/GroupTheory/Exponent.lean index 94ce55d4cf069..f408bce7cb363 100644 --- a/Mathlib/GroupTheory/Exponent.lean +++ b/Mathlib/GroupTheory/Exponent.lean @@ -452,7 +452,7 @@ theorem exists_orderOf_eq_exponent (hG : ExponentExists G) : ∃ g : G, orderOf rw [(Commute.all _ g).orderOf_mul_eq_mul_orderOf_of_coprime hcoprime, hpk', hg, ha, hk, pow_add, pow_add, pow_one, ← mul_assoc, ← mul_assoc, Nat.div_mul_cancel, mul_assoc, lt_mul_iff_one_lt_right <| hG.orderOf_pos t, ← pow_succ] - · exact one_lt_pow hp.one_lt a.succ_ne_zero + · exact one_lt_pow₀ hp.one_lt a.succ_ne_zero · exact hpk @[to_additive] diff --git a/Mathlib/GroupTheory/FiniteAbelian.lean b/Mathlib/GroupTheory/FiniteAbelian.lean index 0e74393883b9e..8ac8ceb36aec7 100644 --- a/Mathlib/GroupTheory/FiniteAbelian.lean +++ b/Mathlib/GroupTheory/FiniteAbelian.lean @@ -148,7 +148,7 @@ lemma equiv_directSum_zmod_of_finite' (G : Type*) [AddCommGroup G] [Finite G] : refine ⟨{i : ι // n i ≠ 0}, inferInstance, fun i ↦ p i ^ n i, ?_, ⟨e.trans (directSumNeZeroMulEquiv ι _ _).symm⟩⟩ rintro ⟨i, hi⟩ - exact one_lt_pow (hp _).one_lt hi + exact one_lt_pow₀ (hp _).one_lt hi theorem finite_of_fg_torsion [hG' : AddGroup.FG G] (hG : AddMonoid.IsTorsion G) : Finite G := @Module.finite_of_fg_torsion _ _ _ (Module.Finite.iff_addGroup_fg.mpr hG') <| diff --git a/Mathlib/GroupTheory/FixedPointFree.lean b/Mathlib/GroupTheory/FixedPointFree.lean index 2f9fb7c2c40f9..a91326561faf5 100644 --- a/Mathlib/GroupTheory/FixedPointFree.lean +++ b/Mathlib/GroupTheory/FixedPointFree.lean @@ -54,8 +54,8 @@ theorem prod_pow_eq_one (hφ : FixedPointFree φ) {n : ℕ} (hn : φ^[n] = _root theorem coe_eq_inv_of_sq_eq_one (hφ : FixedPointFree φ) (h2 : φ^[2] = _root_.id) : ⇑φ = (·⁻¹) := by ext g - have key : 1 * g * φ g = 1 := hφ.prod_pow_eq_one h2 g - rwa [one_mul, ← inv_eq_iff_mul_eq_one, eq_comm] at key + have key : g * φ g = 1 := by simpa [List.range_succ] using hφ.prod_pow_eq_one h2 g + rwa [← inv_eq_iff_mul_eq_one, eq_comm] at key section Involutive diff --git a/Mathlib/GroupTheory/FreeAbelianGroup.lean b/Mathlib/GroupTheory/FreeAbelianGroup.lean index 2fc7ca86f0f66..475386ea7d3df 100644 --- a/Mathlib/GroupTheory/FreeAbelianGroup.lean +++ b/Mathlib/GroupTheory/FreeAbelianGroup.lean @@ -419,7 +419,7 @@ instance ring : Ring (FreeAbelianGroup α) := dsimp only [(· * ·), Mul.mul, OfNat.ofNat, One.one] rw [lift.of] refine FreeAbelianGroup.induction_on x rfl (fun L ↦ ?_) (fun L ih ↦ ?_) fun x1 x2 ih1 ih2 ↦ ?_ - · erw [lift.of] + · rw [lift.of] congr 1 exact mul_one L · rw [map_neg, ih] diff --git a/Mathlib/GroupTheory/FreeGroup/Basic.lean b/Mathlib/GroupTheory/FreeGroup/Basic.lean index 0718b7ca18057..4dfea2fbf13f6 100644 --- a/Mathlib/GroupTheory/FreeGroup/Basic.lean +++ b/Mathlib/GroupTheory/FreeGroup/Basic.lean @@ -128,7 +128,7 @@ theorem not_step_nil : ¬Step [] L := by generalize h' : [] = L' intro h cases' h with L₁ L₂ - simp [List.nil_eq_append] at h' + simp [List.nil_eq_append_iff] at h' @[to_additive] theorem Step.cons_left_iff {a : α} {b : Bool} : @@ -287,7 +287,8 @@ theorem red_iff_irreducible {x1 b1 x2 b2} (h : (x1, b1) ≠ (x2, b2)) : generalize eq : [(x1, not b1), (x2, b2)] = L' intro L h' cases h' - simp [List.cons_eq_append, List.nil_eq_append] at eq + simp only [List.cons_eq_append_iff, List.cons.injEq, Prod.mk.injEq, and_false, + List.nil_eq_append_iff, exists_const, or_self, or_false, List.cons_ne_nil] at eq rcases eq with ⟨rfl, ⟨rfl, rfl⟩, ⟨rfl, rfl⟩, rfl⟩ simp at h @@ -571,7 +572,7 @@ def lift : (α → β) ≃ (FreeGroup α →* β) where MonoidHom.mk' (Quot.lift (Lift.aux f) fun L₁ L₂ => Red.Step.lift) <| by rintro ⟨L₁⟩ ⟨L₂⟩; simp [Lift.aux] invFun g := g ∘ of - left_inv f := one_mul _ + left_inv f := List.prod_singleton right_inv g := MonoidHom.ext <| by rintro ⟨L⟩ @@ -592,7 +593,7 @@ theorem lift.mk : lift f (mk L) = List.prod (L.map fun x => cond x.2 (f x.1) (f @[to_additive (attr := simp)] theorem lift.of {x} : lift f (of x) = f x := - one_mul _ + List.prod_singleton @[to_additive] theorem lift.unique (g : FreeGroup α →* β) (hg : ∀ x, g (FreeGroup.of x) = f x) {x} : diff --git a/Mathlib/GroupTheory/GroupAction/Hom.lean b/Mathlib/GroupTheory/GroupAction/Hom.lean index 2a9db62dd963a..e2fc5be8f79d8 100644 --- a/Mathlib/GroupTheory/GroupAction/Hom.lean +++ b/Mathlib/GroupTheory/GroupAction/Hom.lean @@ -2,7 +2,6 @@ Copyright (c) 2020 Kenny Lau. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau, Antoine Chambert-Loir - -/ import Mathlib.Algebra.Module.Defs diff --git a/Mathlib/GroupTheory/GroupAction/Pointwise.lean b/Mathlib/GroupTheory/GroupAction/Pointwise.lean index b5537fe937116..4a0bf768bba53 100644 --- a/Mathlib/GroupTheory/GroupAction/Pointwise.lean +++ b/Mathlib/GroupTheory/GroupAction/Pointwise.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro, Anne Baanen, Frédéric Dupuis, Heather Macbeth, Antoine Chambert-Loir -/ -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic import Mathlib.GroupTheory.GroupAction.Hom /-! diff --git a/Mathlib/GroupTheory/GroupAction/Quotient.lean b/Mathlib/GroupTheory/GroupAction/Quotient.lean index f036e80ab2244..3cd5bab40dafd 100644 --- a/Mathlib/GroupTheory/GroupAction/Quotient.lean +++ b/Mathlib/GroupTheory/GroupAction/Quotient.lean @@ -402,7 +402,7 @@ noncomputable def equivSubgroupOrbitsQuotientGroup [IsPretransitive α β] rw [Quotient.eq'', leftRel_eq] simp only convert one_mem H - rw [inv_mul_eq_one, eq_comm, ← inv_mul_eq_one, ← Subgroup.mem_bot, ← free (g⁻¹ • x), + · rw [inv_mul_eq_one, eq_comm, ← inv_mul_eq_one, ← Subgroup.mem_bot, ← free (g⁻¹ • x), mem_stabilizer_iff, mul_smul, (exists_smul_eq α (g⁻¹ • x) x).choose_spec] end MulAction diff --git a/Mathlib/GroupTheory/GroupAction/Support.lean b/Mathlib/GroupTheory/GroupAction/Support.lean index c2bd6a25eddf5..392881eb03ad9 100644 --- a/Mathlib/GroupTheory/GroupAction/Support.lean +++ b/Mathlib/GroupTheory/GroupAction/Support.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Algebra.Group.Action.Basic -import Mathlib.Algebra.Group.Pointwise.Set +import Mathlib.Algebra.Group.Pointwise.Set.Basic /-! # Support of an element under an action action diff --git a/Mathlib/GroupTheory/HNNExtension.lean b/Mathlib/GroupTheory/HNNExtension.lean index d4c6a1677d248..2ba02b333a426 100644 --- a/Mathlib/GroupTheory/HNNExtension.lean +++ b/Mathlib/GroupTheory/HNNExtension.lean @@ -174,7 +174,7 @@ namespace NormalWord variable (G A B) /-- To put word in the HNN Extension into a normal form, we must choose an element of each right coset of both `A` and `B`, such that the chosen element of the subgroup itself is `1`. -/ -structure TransversalPair : Type _ := +structure TransversalPair : Type _ where /-- The transversal of each subgroup -/ set : ℤˣ → Set G /-- We have exactly one element of each coset of the subgroup -/ @@ -187,7 +187,7 @@ instance TransversalPair.nonempty : Nonempty (TransversalPair G A B) := by /-- A reduced word is a `head`, which is an element of `G`, followed by the product list of pairs. There should also be no sequences of the form `t^u * g * t^-u`, where `g` is in `toSubgroup A B u` This is a less strict condition than required for `NormalWord`. -/ -structure ReducedWord : Type _ := +structure ReducedWord : Type _ where /-- Every `ReducedWord` is the product of an element of the group and a word made up of letters each of which is in the transversal. `head` is that element of the base group. -/ head : G @@ -215,7 +215,7 @@ The normal form is a `head`, which is an element of `G`, followed by the product `toSubgroup A B u`. There should also be no sequences of the form `t^u * g * t^-u` where `g ∈ toSubgroup A B u` -/ structure _root_.HNNExtension.NormalWord (d : TransversalPair G A B) - extends ReducedWord G A B : Type _ := + extends ReducedWord G A B : Type _ where /-- Every element `g : G` in the list is the chosen element of its coset -/ mem_set : ∀ (u : ℤˣ) (g : G), (u, g) ∈ toList → g ∈ d.set u diff --git a/Mathlib/GroupTheory/Index.lean b/Mathlib/GroupTheory/Index.lean index 9085d649c8d8c..99284c35f6952 100644 --- a/Mathlib/GroupTheory/Index.lean +++ b/Mathlib/GroupTheory/Index.lean @@ -56,9 +56,8 @@ noncomputable def relindex : ℕ := @[to_additive] theorem index_comap_of_surjective {f : G' →* G} (hf : Function.Surjective f) : (H.comap f).index = H.index := by - letI := QuotientGroup.leftRel H - letI := QuotientGroup.leftRel (H.comap f) - have key : ∀ x y : G', Setoid.r x y ↔ Setoid.r (f x) (f y) := by + have key : ∀ x y : G', + QuotientGroup.leftRel (H.comap f) x y ↔ QuotientGroup.leftRel H (f x) (f y) := by simp only [QuotientGroup.leftRel_apply] exact fun x y => iff_of_eq (congr_arg (· ∈ H) (by rw [f.map_mul, f.map_inv])) refine Cardinal.toNat_congr (Equiv.ofBijective (Quotient.map' f fun x y => (key x y).mp) ⟨?_, ?_⟩) diff --git a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean index 988928ee6d456..aae0ac762fc97 100644 --- a/Mathlib/GroupTheory/MonoidLocalization/Basic.lean +++ b/Mathlib/GroupTheory/MonoidLocalization/Basic.lean @@ -268,8 +268,6 @@ theorem ndrec_mk {p : Localization S → Sort u} (f : ∀ (a : M) (b : S), p (mk /-- Non-dependent recursion principle for localizations: given elements `f a b : p` for all `a b`, such that `r S (a, b) (c, d)` implies `f a b = f c d`, then `f` is defined on the whole `Localization S`. -/ --- Porting note: the attribute `elab_as_elim` fails with `unexpected eliminator resulting type p` --- @[to_additive (attr := elab_as_elim) @[to_additive "Non-dependent recursion principle for `AddLocalization`s: given elements `f a b : p` for all `a b`, such that `r S (a, b) (c, d)` implies `f a b = f c d`, @@ -293,8 +291,6 @@ theorem induction_on {p : Localization S → Prop} (x) (H : ∀ y : M × S, p (m /-- Non-dependent recursion principle for localizations: given elements `f x y : p` for all `x` and `y`, such that `r S x x'` and `r S y y'` implies `f x y = f x' y'`, then `f` is defined on the whole `Localization S`. -/ --- Porting note: the attribute `elab_as_elim` fails with `unexpected eliminator resulting type p` --- @[to_additive (attr := elab_as_elim) @[to_additive "Non-dependent recursion principle for localizations: given elements `f x y : p` for all `x` and `y`, such that `r S x x'` and `r S y y'` implies `f x y = f x' y'`, @@ -548,7 +544,7 @@ theorem mk'_spec' (x) (y : S) : f.toMap y * f.mk' x y = f.toMap x := by rw [mul_ @[to_additive] theorem eq_mk'_iff_mul_eq {x} {y : S} {z} : z = f.mk' x y ↔ z * f.toMap y = f.toMap x := - ⟨fun H ↦ by rw [H, mk'_spec], fun H ↦ by erw [mul_inv_right, H]⟩ + ⟨fun H ↦ by rw [H, mk'_spec], fun H ↦ by rw [mk', mul_inv_right, H]⟩ @[to_additive] theorem mk'_eq_iff_eq_mul {x} {y : S} {z} : f.mk' x y = z ↔ f.toMap x = z * f.toMap y := by @@ -773,9 +769,7 @@ theorem lift_comp : (f.lift hg).comp f.toMap = g := by ext; exact f.lift_eq hg _ @[to_additive (attr := simp)] theorem lift_of_comp (j : N →* P) : f.lift (f.isUnit_comp j) = j := by ext - rw [lift_spec] - show j _ = j _ * _ - erw [← j.map_mul, sec_spec'] + simp_rw [lift_spec, MonoidHom.comp_apply, ← j.map_mul, sec_spec'] @[to_additive] theorem epic_of_localizationMap {j k : N →* P} (h : ∀ a, j.comp f.toMap a = k.comp f.toMap a) : @@ -834,8 +828,8 @@ theorem lift_surjective_iff : obtain ⟨z, hz⟩ := H v obtain ⟨x, hx⟩ := f.surj z use x - rw [← hz, f.eq_mk'_iff_mul_eq.2 hx, lift_mk', mul_assoc, mul_comm _ (g ↑x.2)] - erw [IsUnit.mul_liftRight_inv (g.restrict S) hg, mul_one] + rw [← hz, f.eq_mk'_iff_mul_eq.2 hx, lift_mk', mul_assoc, mul_comm _ (g ↑x.2), + ← MonoidHom.restrict_apply, IsUnit.mul_liftRight_inv (g.restrict S) hg, mul_one] · intro H v obtain ⟨x, hx⟩ := H v use f.mk' x.1 x.2 @@ -1131,9 +1125,9 @@ of `AddCommMonoid`s, `k ∘ f` is a Localization map for `M` at `S`."] def ofMulEquivOfLocalizations (k : N ≃* P) : LocalizationMap S P := (k.toMonoidHom.comp f.toMap).toLocalizationMap (fun y ↦ isUnit_comp f k.toMonoidHom y) (fun v ↦ - let ⟨z, hz⟩ := k.toEquiv.surjective v + let ⟨z, hz⟩ := k.surjective v let ⟨x, hx⟩ := f.surj z - ⟨x, show v * k _ = k _ by rw [← hx, map_mul, ← hz]; rfl⟩) + ⟨x, show v * k _ = k _ by rw [← hx, map_mul, ← hz]⟩) fun x y ↦ (k.apply_eq_iff_eq.trans f.eq_iff_exists).1 @[to_additive (attr := simp)] @@ -1203,18 +1197,17 @@ def ofMulEquivOfDom {k : P ≃* M} (H : T.map k.toMonoidHom = S) : LocalizationM ⟨z, hz⟩) (fun z ↦ let ⟨x, hx⟩ := f.surj z - let ⟨v, hv⟩ := k.toEquiv.surjective x.1 - let ⟨w, hw⟩ := k.toEquiv.surjective x.2 - ⟨(v, ⟨w, H' ▸ show k w ∈ S from hw.symm ▸ x.2.2⟩), - show z * f.toMap (k.toEquiv w) = f.toMap (k.toEquiv v) by erw [hv, hw, hx]⟩) - fun x y ↦ - show f.toMap _ = f.toMap _ → _ by - erw [f.eq_iff_exists] - exact - fun ⟨c, hc⟩ ↦ - let ⟨d, hd⟩ := k.toEquiv.surjective c - ⟨⟨d, H' ▸ show k d ∈ S from hd.symm ▸ c.2⟩, by - erw [← hd, ← map_mul k, ← map_mul k] at hc; exact k.toEquiv.injective hc⟩ + let ⟨v, hv⟩ := k.surjective x.1 + let ⟨w, hw⟩ := k.surjective x.2 + ⟨(v, ⟨w, H' ▸ show k w ∈ S from hw.symm ▸ x.2.2⟩), by + simp_rw [MonoidHom.comp_apply, MulEquiv.toMonoidHom_eq_coe, MonoidHom.coe_coe, hv, hw, hx]⟩) + fun x y ↦ by + rw [MonoidHom.comp_apply, MonoidHom.comp_apply, MulEquiv.toMonoidHom_eq_coe, + MonoidHom.coe_coe, f.eq_iff_exists] + rintro ⟨c, hc⟩ + let ⟨d, hd⟩ := k.surjective c + refine ⟨⟨d, H' ▸ show k d ∈ S from hd.symm ▸ c.2⟩, ?_⟩ + rw [← hd, ← map_mul k, ← map_mul k] at hc; exact k.injective hc @[to_additive (attr := simp)] theorem ofMulEquivOfDom_apply {k : P ≃* M} (H : T.map k.toMonoidHom = S) (x) : diff --git a/Mathlib/GroupTheory/OrderOfElement.lean b/Mathlib/GroupTheory/OrderOfElement.lean index 462873bca532e..9e33d48b21996 100644 --- a/Mathlib/GroupTheory/OrderOfElement.lean +++ b/Mathlib/GroupTheory/OrderOfElement.lean @@ -717,7 +717,7 @@ automatic in the case of a finite cancellative monoid. -/ `addOrderOf_nsmul` but with one assumption less which is automatic in the case of a finite cancellative additive monoid."] theorem orderOf_pow (x : G) : orderOf (x ^ n) = orderOf x / gcd (orderOf x) n := - (isOfFinOrder_of_finite _).orderOf_pow _ + (isOfFinOrder_of_finite _).orderOf_pow .. @[to_additive] theorem mem_powers_iff_mem_range_orderOf [DecidableEq G] : @@ -1031,8 +1031,8 @@ theorem orderOf_abs_ne_one (h : |x| ≠ 1) : orderOf x = 0 := by intro n hn hx replace hx : |x| ^ n = 1 := by simpa only [abs_one, abs_pow] using congr_arg abs hx cases' h.lt_or_lt with h h - · exact ((pow_lt_one (abs_nonneg x) h hn.ne').ne hx).elim - · exact ((one_lt_pow h hn.ne').ne' hx).elim + · exact ((pow_lt_one₀ (abs_nonneg x) h hn.ne').ne hx).elim + · exact ((one_lt_pow₀ h hn.ne').ne' hx).elim theorem LinearOrderedRing.orderOf_le_two : orderOf x ≤ 2 := by cases' ne_or_eq |x| 1 with h h diff --git a/Mathlib/GroupTheory/PGroup.lean b/Mathlib/GroupTheory/PGroup.lean index 48adfd8c9bacd..52fcaf2fb7a60 100644 --- a/Mathlib/GroupTheory/PGroup.lean +++ b/Mathlib/GroupTheory/PGroup.lean @@ -136,7 +136,7 @@ theorem nontrivial_iff_card [Finite G] : Nontrivial G ↔ ∃ n > 0, Nat.card G hk⟩, fun ⟨k, hk0, hk⟩ => Finite.one_lt_card_iff_nontrivial.1 <| - hk.symm ▸ one_lt_pow (Fact.out (p := p.Prime)).one_lt (ne_of_gt hk0)⟩ + hk.symm ▸ one_lt_pow₀ (Fact.out (p := p.Prime)).one_lt (ne_of_gt hk0)⟩ variable {α : Type*} [MulAction G α] diff --git a/Mathlib/GroupTheory/Perm/Closure.lean b/Mathlib/GroupTheory/Perm/Closure.lean index 6fa1105deb178..9564bafaf6fcc 100644 --- a/Mathlib/GroupTheory/Perm/Closure.lean +++ b/Mathlib/GroupTheory/Perm/Closure.lean @@ -40,7 +40,7 @@ theorem closure_isCycle : closure { σ : Perm β | IsCycle σ } = ⊤ := by variable [DecidableEq α] [Fintype α] -theorem closure_cycle_adjacent_swap {σ : Perm α} (h1 : IsCycle σ) (h2 : σ.support = ⊤) (x : α) : +theorem closure_cycle_adjacent_swap {σ : Perm α} (h1 : IsCycle σ) (h2 : σ.support = univ) (x : α) : closure ({σ, swap x (σ x)} : Set (Perm α)) = ⊤ := by let H := closure ({σ, swap x (σ x)} : Set (Perm α)) have h3 : σ ∈ H := subset_closure (Set.mem_insert σ _) @@ -51,8 +51,7 @@ theorem closure_cycle_adjacent_swap {σ : Perm α} (h1 : IsCycle σ) (h2 : σ.su | zero => exact subset_closure (Set.mem_insert_of_mem _ (Set.mem_singleton _)) | succ n ih => convert H.mul_mem (H.mul_mem h3 ih) (H.inv_mem h3) - simp_rw [mul_swap_eq_swap_mul, mul_inv_cancel_right, pow_succ'] - rfl + simp_rw [mul_swap_eq_swap_mul, mul_inv_cancel_right, pow_succ', coe_mul, comp_apply] have step2 : ∀ n : ℕ, swap x ((σ ^ n) x) ∈ H := by intro n induction n with @@ -70,9 +69,9 @@ theorem closure_cycle_adjacent_swap {σ : Perm α} (h1 : IsCycle σ) (h2 : σ.su exact H.mul_mem (H.mul_mem (step1 n) ih) (step1 n) have step3 : ∀ y : α, swap x y ∈ H := by intro y - have hx : x ∈ (⊤ : Finset α) := Finset.mem_univ x + have hx : x ∈ univ := Finset.mem_univ x rw [← h2, mem_support] at hx - have hy : y ∈ (⊤ : Finset α) := Finset.mem_univ y + have hy : y ∈ univ := Finset.mem_univ y rw [← h2, mem_support] at hy cases' IsCycle.exists_pow_eq h1 hx hy with n hn rw [← hn] @@ -97,7 +96,7 @@ theorem closure_cycle_coprime_swap {n : ℕ} {σ : Perm α} (h0 : Nat.Coprime n closure ({σ, swap x ((σ ^ n) x)} : Set (Perm α)) = ⊤ := by rw [← Finset.card_univ, ← h2, ← h1.orderOf] at h0 cases' exists_pow_eq_self_of_coprime h0 with m hm - have h2' : (σ ^ n).support = ⊤ := Eq.trans (support_pow_coprime h0) h2 + have h2' : (σ ^ n).support = univ := Eq.trans (support_pow_coprime h0) h2 have h1' : IsCycle ((σ ^ n) ^ (m : ℤ)) := by rwa [← hm] at h1 replace h1' : IsCycle (σ ^ n) := h1'.of_pow (le_trans (support_pow_le σ n) (ge_of_eq (congr_arg support hm))) diff --git a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean index 57afc2d245faf..624873b85abc2 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Concrete.lean @@ -316,7 +316,7 @@ theorem toList_formPerm_nontrivial (l : List α) (hl : 2 ≤ l.length) (hn : Nod · refine ext_getElem (by simp) fun k hk hk' => ?_ simp only [get_eq_getElem, formPerm_pow_apply_getElem _ hn, zero_add, getElem_map, getElem_range, Nat.mod_eq_of_lt hk'] - · simpa [hs] using get_mem _ _ _ + · simp [hs] theorem toList_formPerm_isRotated_self (l : List α) (hl : 2 ≤ l.length) (hn : Nodup l) (x : α) (hx : x ∈ l) : toList (formPerm l) x ~r l := by @@ -325,7 +325,7 @@ theorem toList_formPerm_isRotated_self (l : List α) (hl : 2 ≤ l.length) (hn : rw [formPerm_eq_of_isRotated hn hr] rw [get_eq_get_rotate l k k] simp only [Nat.mod_eq_of_lt k.2, tsub_add_cancel_of_le (le_of_lt k.2), Nat.mod_self] - erw [toList_formPerm_nontrivial] + rw [toList_formPerm_nontrivial] · simp · simpa using hl · simpa using hn diff --git a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean index 421192a904fdc..e2fc3224e97be 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Factors.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Factors.lean @@ -502,6 +502,11 @@ theorem cycleOf_mem_cycleFactorsFinset_iff {f : Perm α} {x : α} : · rw [cycleOf_apply_of_not_sameCycle H] at hy contradiction +lemma cycleOf_ne_one_iff_mem_cycleFactorsFinset {g : Equiv.Perm α} {x : α} : + g.cycleOf x ≠ 1 ↔ g.cycleOf x ∈ g.cycleFactorsFinset := by + rw [Equiv.Perm.cycleOf_mem_cycleFactorsFinset_iff, Equiv.Perm.mem_support, + ne_eq, Equiv.Perm.cycleOf_eq_one_iff] + theorem mem_cycleFactorsFinset_support_le {p f : Perm α} (h : p ∈ cycleFactorsFinset f) : p.support ≤ f.support := by rw [mem_cycleFactorsFinset_iff] at h @@ -757,7 +762,6 @@ theorem commute_iff_of_mem_cycleFactorsFinset [DecidableEq α] [Fintype α]{g k intro n rw [Equiv.Perm.subtypePerm_on_cycleFactorsFinset hc] - end cycleFactors end Perm diff --git a/Mathlib/GroupTheory/Perm/Cycle/Type.lean b/Mathlib/GroupTheory/Perm/Cycle/Type.lean index 34e77ea5584a0..5a823f43577e4 100644 --- a/Mathlib/GroupTheory/Perm/Cycle/Type.lean +++ b/Mathlib/GroupTheory/Perm/Cycle/Type.lean @@ -134,6 +134,11 @@ theorem sum_cycleType (σ : Perm α) : σ.cycleType.sum = σ.support.card := by | base_cycles σ hσ => rw [hσ.cycleType, sum_coe, List.sum_singleton] | induction_disjoint σ τ hd _ hσ hτ => rw [hd.cycleType, sum_add, hσ, hτ, hd.card_support_mul] +theorem card_fixedPoints (σ : Equiv.Perm α) : + Fintype.card (Function.fixedPoints σ) = Fintype.card α - σ.cycleType.sum := by + rw [Equiv.Perm.sum_cycleType, ← Finset.card_compl, Fintype.card_ofFinset] + congr; aesop + theorem sign_of_cycleType' (σ : Perm α) : sign σ = (σ.cycleType.map fun n => -(-1 : ℤˣ) ^ n).prod := by induction σ using cycle_induction_on with diff --git a/Mathlib/GroupTheory/Perm/DomMulAct.lean b/Mathlib/GroupTheory/Perm/DomMulAct.lean index 716f2084d8364..4bfd4c758ab0d 100644 --- a/Mathlib/GroupTheory/Perm/DomMulAct.lean +++ b/Mathlib/GroupTheory/Perm/DomMulAct.lean @@ -6,9 +6,9 @@ Authors: Junyan Xu, Antoine Chambert-Loir import Mathlib.Algebra.Group.Subgroup.Basic import Mathlib.GroupTheory.GroupAction.DomAct.Basic import Mathlib.GroupTheory.GroupAction.Basic - import Mathlib.Data.Fintype.Basic import Mathlib.Data.Fintype.Perm +import Mathlib.Data.Set.Card import Mathlib.SetTheory.Cardinal.Finite /-! Subgroup of `Equiv.Perm α` preserving a function @@ -29,6 +29,8 @@ Let `α` and `ι` by types and let `f : α → ι` the cardinality of the type of permutations preserving `p` : `Fintype.card {g : Perm α // f ∘ g = f} = ∏ i, (Fintype.card {a // f a = i})!`. +* Without `Fintype ι`, `DomMulAct.stabilizer_card' p` gives an equivalent + formula, where the product is restricted to `Finset.univ.image f`. -/ variable {α ι : Type*} {f : α → ι} @@ -86,22 +88,62 @@ lemma stabilizerMulEquiv_apply (g : (stabilizer (Perm α)ᵈᵐᵃ f)ᵐᵒᵖ) section Fintype -variable [Fintype α] [Fintype ι] [DecidableEq α] [DecidableEq ι] +variable [Fintype α] open Nat variable (f) /-- The cardinality of the type of permutations preserving a function -/ -theorem stabilizer_card : +theorem stabilizer_card [DecidableEq α] [DecidableEq ι] [Fintype ι] : 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 _ ↦ ?_), + 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 +/-- The cardinality of the set of permutations preserving a function -/ +theorem stabilizer_ncard [Fintype ι] : + Set.ncard {g : Perm α | f ∘ g = f} = ∏ i, (Set.ncard {a | f a = i})! := by + classical + simp only [← Set.Nat.card_coe_set_eq, Set.coe_setOf, card_eq_fintype_card] + exact stabilizer_card f + +variable [DecidableEq α] [DecidableEq ι] + +/-- The cardinality of the type of permutations preserving a function + (without the finiteness assumption on target)-/ +theorem stabilizer_card': + Fintype.card {g : Perm α // f ∘ g = f} = + ∏ i in Finset.univ.image f, (Fintype.card ({a // f a = i}))! := by + set φ : α → Finset.univ.image f := + Set.codRestrict f (Finset.univ.image f) (fun a => by simp) + suffices ∀ g : Perm α, f ∘ g = f ↔ φ ∘ g = φ by + simp only [this, stabilizer_card] + apply Finset.prod_bij (fun g _ => g.val) + · exact fun g _ => Finset.coe_mem g + · exact fun g _ g' _ => SetCoe.ext + · exact fun g hg => by + rw [Finset.mem_image] at hg + obtain ⟨a, _, rfl⟩ := hg + use ⟨f a, by simp only [Finset.mem_image, Finset.mem_univ, true_and, exists_apply_eq_apply]⟩ + simp only [Finset.univ_eq_attach, Finset.mem_attach, exists_const] + · intro i _ + apply congr_arg + apply Fintype.card_congr + apply Equiv.subtypeEquiv (Equiv.refl α) + intro a + rw [refl_apply, ← Subtype.coe_inj] + simp only [φ, Set.val_codRestrict_apply] + · intro g + simp only [Function.funext_iff] + apply forall_congr' + intro a + simp only [Function.comp_apply, φ, ← Subtype.coe_inj, Set.val_codRestrict_apply] + end Fintype end DomMulAct diff --git a/Mathlib/GroupTheory/Perm/Sign.lean b/Mathlib/GroupTheory/Perm/Sign.lean index a7d22e67b1e55..269920ef0aab3 100644 --- a/Mathlib/GroupTheory/Perm/Sign.lean +++ b/Mathlib/GroupTheory/Perm/Sign.lean @@ -417,7 +417,7 @@ theorem sign_trans_trans_symm [DecidableEq β] [Fintype β] (f : Perm β) (e : theorem sign_prod_list_swap {l : List (Perm α)} (hl : ∀ g ∈ l, IsSwap g) : sign l.prod = (-1) ^ l.length := by have h₁ : l.map sign = List.replicate l.length (-1) := - List.eq_replicate.2 + List.eq_replicate_iff.2 ⟨by simp, fun u hu => let ⟨g, hg⟩ := List.mem_map.1 hu hg.2 ▸ (hl _ hg.1).sign_eq⟩ diff --git a/Mathlib/GroupTheory/QuotientGroup/Basic.lean b/Mathlib/GroupTheory/QuotientGroup/Basic.lean index 7857eb080a61d..2172f44a0ecee 100644 --- a/Mathlib/GroupTheory/QuotientGroup/Basic.lean +++ b/Mathlib/GroupTheory/QuotientGroup/Basic.lean @@ -167,6 +167,11 @@ theorem mk_prod {G ι : Type*} [CommGroup G] (N : Subgroup G) (s : Finset ι) {f @[to_additive (attr := simp)] lemma map_mk'_self : N.map (mk' N) = ⊥ := by aesop +@[to_additive QuotientAddGroup.strictMono_comap_prod_map] +theorem strictMono_comap_prod_map : + StrictMono fun H : Subgroup G ↦ (H.comap N.subtype, H.map (mk' N)) := + strictMono_comap_prod_image N + /-- A group homomorphism `φ : G →* M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) to a group homomorphism `G/N →* M`. -/ @[to_additive "An `AddGroup` homomorphism `φ : G →+ M` with `N ⊆ ker(φ)` descends (i.e. `lift`s) @@ -519,7 +524,7 @@ noncomputable def quotientInfEquivProdNormalQuotient (H N : Subgroup G) [N.Norma (@leftRel ↑(H ⊔ N) (H ⊔ N : Subgroup G).toGroup (N.subgroupOf (H ⊔ N))) -- Porting note: Lean couldn't find this automatically refine Quotient.eq.mpr ?_ - change Setoid.r _ _ + change leftRel _ _ _ rw [leftRel_apply] change h⁻¹ * (h * n) ∈ N rwa [← mul_assoc, inv_mul_cancel, one_mul] diff --git a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean index eda2a253359f6..38b5ab4ee0b07 100644 --- a/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean +++ b/Mathlib/GroupTheory/SpecificGroups/Cyclic.lean @@ -656,7 +656,7 @@ lemma not_isCyclic_iff_exponent_eq_prime [Group α] {p : ℕ} (hp : p.Prime) let _inst : Fintype α := @Fintype.ofFinite α <| Nat.finite_of_card_ne_zero <| by aesop have hα' : Fintype.card α = p ^ 2 := by simpa using hα have := (Fintype.one_lt_card_iff_nontrivial (α := α)).mp <| - hα' ▸ one_lt_pow hp.one_lt two_ne_zero + hα' ▸ one_lt_pow₀ hp.one_lt two_ne_zero /- in the forward direction, we apply `exponent_eq_prime_iff`, and the reverse direction follows immediately because if `α` has exponent `p`, it has no element of order `p ^ 2`. -/ refine ⟨fun h_cyc ↦ (Monoid.exponent_eq_prime_iff hp).mpr fun g hg ↦ ?_, fun h_exp h_cyc ↦ by diff --git a/Mathlib/GroupTheory/Torsion.lean b/Mathlib/GroupTheory/Torsion.lean index 1fe565875fe91..08d223f5db3ba 100644 --- a/Mathlib/GroupTheory/Torsion.lean +++ b/Mathlib/GroupTheory/Torsion.lean @@ -297,7 +297,7 @@ end CommGroup end CommGroup namespace Monoid - +section Monoid variable (G) [Monoid G] /-- A predicate on a monoid saying that only 1 is of finite order. -/ @@ -326,22 +326,17 @@ lemma isTorsionFree_iff_torsion_eq_bot {G} [CommGroup G] : end Monoid section Group - -open Monoid - variable [Group G] /-- A nontrivial torsion group is not torsion-free. -/ -@[to_additive AddMonoid.IsTorsion.not_torsion_free - "A nontrivial additive torsion group is not torsion-free."] +@[to_additive "A nontrivial additive torsion group is not torsion-free."] theorem IsTorsion.not_torsion_free [hN : Nontrivial G] : IsTorsion G → ¬IsTorsionFree G := fun tG => not_isTorsionFree_iff.mpr <| by obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN exact ⟨x, hx, tG x⟩ /-- A nontrivial torsion-free group is not torsion. -/ -@[to_additive AddMonoid.IsTorsionFree.not_torsion - "A nontrivial torsion-free additive group is not torsion."] +@[to_additive "A nontrivial torsion-free additive group is not torsion."] theorem IsTorsionFree.not_torsion [hN : Nontrivial G] : IsTorsionFree G → ¬IsTorsion G := fun tfG => (not_isTorsion_iff _).mpr <| by obtain ⟨x, hx⟩ := (nontrivial_iff_exists_ne (1 : G)).mp hN @@ -371,8 +366,8 @@ open CommGroup (torsion) variable (G) [CommGroup G] /-- Quotienting a group by its torsion subgroup yields a torsion free group. -/ -@[to_additive AddIsTorsionFree.quotient_torsion - "Quotienting a group by its additive torsion subgroup yields an additive torsion free group."] +@[to_additive +"Quotienting a group by its additive torsion subgroup yields an additive torsion free group."] theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun g hne hfin => hne <| by induction' g using QuotientGroup.induction_on with g @@ -383,21 +378,26 @@ theorem IsTorsionFree.quotient_torsion : IsTorsionFree <| G ⧸ torsion G := fun (isOfFinOrder_iff_pow_eq_one.mpr ⟨m * n, mul_pos mpos npos, (pow_mul g m n).symm ▸ hn⟩) end CommGroup +end Monoid + +namespace AddMonoid lemma isTorsionFree_iff_noZeroSMulDivisors_nat {M : Type*} [AddMonoid M] : - AddMonoid.IsTorsionFree M ↔ NoZeroSMulDivisors ℕ M := by + IsTorsionFree M ↔ NoZeroSMulDivisors ℕ M := by simp_rw [AddMonoid.IsTorsionFree, isOfFinAddOrder_iff_nsmul_eq_zero, not_exists, not_and, pos_iff_ne_zero, noZeroSMulDivisors_iff, forall_swap (β := ℕ)] exact forall₂_congr fun _ _ ↦ by tauto lemma isTorsionFree_iff_noZeroSMulDivisors_int [AddGroup G] : - AddMonoid.IsTorsionFree G ↔ NoZeroSMulDivisors ℤ G := by + IsTorsionFree G ↔ NoZeroSMulDivisors ℤ G := by simp_rw [AddMonoid.IsTorsionFree, isOfFinAddOrder_iff_zsmul_eq_zero, not_exists, not_and, noZeroSMulDivisors_iff, forall_swap (β := ℤ)] exact forall₂_congr fun _ _ ↦ by tauto -@[deprecated (since := "2024-02-29")] -alias AddMonoid.IsTorsionFree_iff_noZeroSMulDivisors := isTorsionFree_iff_noZeroSMulDivisors_int - lemma IsTorsionFree.of_noZeroSMulDivisors {M : Type*} [AddMonoid M] [NoZeroSMulDivisors ℕ M] : - AddMonoid.IsTorsionFree M := isTorsionFree_iff_noZeroSMulDivisors_nat.2 ‹_› + IsTorsionFree M := isTorsionFree_iff_noZeroSMulDivisors_nat.2 ‹_› + +alias ⟨IsTorsionFree.noZeroSMulDivisors_nat, _⟩ := isTorsionFree_iff_noZeroSMulDivisors_nat +alias ⟨IsTorsionFree.noZeroSMulDivisors_int, _⟩ := isTorsionFree_iff_noZeroSMulDivisors_int + +end AddMonoid diff --git a/Mathlib/Init.lean b/Mathlib/Init.lean index fc6135c7832d0..dff297db373ea 100644 --- a/Mathlib/Init.lean +++ b/Mathlib/Init.lean @@ -1,3 +1,4 @@ +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.HashCommandLinter import Mathlib.Tactic.Linter.GlobalAttributeIn -- This file imports Batteries.Tactic.Lint, where the `env_linter` attribute is defined. diff --git a/Mathlib/Init/Algebra/Classes.lean b/Mathlib/Init/Algebra/Classes.lean index 98fbccbde3cf3..bb4475917a4fd 100644 --- a/Mathlib/Init/Algebra/Classes.lean +++ b/Mathlib/Init/Algebra/Classes.lean @@ -25,7 +25,7 @@ set_option linter.deprecated false universe u v -variable {α : Sort u} {β : Sort v} +variable {α : Sort u} @[deprecated (since := "2024-09-11")] class IsLeftCancel (α : Sort u) (op : α → α → α) : Prop where @@ -57,7 +57,7 @@ instance (priority := 100) (α : Sort u) (lt : α → α → Prop) [IsStrictWeak section -variable {α : Sort u} {r : α → α → Prop} +variable {r : α → α → Prop} local infixl:50 " ≺ " => r @@ -83,7 +83,7 @@ namespace StrictWeakOrder section -variable {α : Sort u} {r : α → α → Prop} +variable {r : α → α → Prop} local infixl:50 " ≺ " => r diff --git a/Mathlib/Lean/Expr/Basic.lean b/Mathlib/Lean/Expr/Basic.lean index add7ca2edafdb..5991b42748293 100644 --- a/Mathlib/Lean/Expr/Basic.lean +++ b/Mathlib/Lean/Expr/Basic.lean @@ -324,6 +324,13 @@ otherwise, it returns `none`. -/ let (type, _, lhs, rhs) ← p.app4? ``LE.le return (type, lhs, rhs) +/-- `Lean.Expr.lt? e` takes `e : Expr` as input. +If `e` represents `a < b`, then it returns `some (t, a, b)`, where `t` is the Type of `a`, +otherwise, it returns `none`. -/ +@[inline] def lt? (p : Expr) : Option (Expr × Expr × Expr) := do + let (type, _, lhs, rhs) ← p.app4? ``LT.lt + return (type, lhs, rhs) + /-- Given a proposition `ty` that is an `Eq`, `Iff`, or `HEq`, returns `(tyLhs, lhs, tyRhs, rhs)`, where `lhs : tyLhs` and `rhs : tyRhs`, and where `lhs` is related to `rhs` by the respective relation. diff --git a/Mathlib/Lean/PrettyPrinter/Delaborator.lean b/Mathlib/Lean/PrettyPrinter/Delaborator.lean index bcc547afa2239..557bdf947198a 100644 --- a/Mathlib/Lean/PrettyPrinter/Delaborator.lean +++ b/Mathlib/Lean/PrettyPrinter/Delaborator.lean @@ -14,13 +14,6 @@ namespace Lean.PrettyPrinter.Delaborator open Lean.Meta Lean.SubExpr SubExpr -namespace SubExpr - -variable {α : Type} [Inhabited α] -variable {m : Type → Type} [Monad m] - -end SubExpr - /-- Assuming the current expression in a lambda or pi, descend into the body using an unused name generated from the binder's name. Provides `d` with both `Syntax` for the bound name as an identifier diff --git a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean index b66ea39b78a5a..7f6518bb77f2e 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/AffineMap.lean @@ -65,7 +65,7 @@ instance AffineMap.instFunLike (k : Type*) {V1 : Type*} (P1 : Type*) {V2 : Type* cases' (AddTorsor.nonempty : Nonempty P1) with p congr with v apply vadd_right_cancel (f p) - erw [← f_add, h, ← g_add] + rw [← f_add, h, ← g_add] 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] @@ -565,6 +565,13 @@ theorem lineMap_vsub_lineMap (p₁ p₂ p₃ p₄ : P1) (c : k) : lineMap p₁ p₂ c -ᵥ lineMap p₃ p₄ c = lineMap (p₁ -ᵥ p₃) (p₂ -ᵥ p₄) c := ((fst : P1 × P1 →ᵃ[k] P1) -ᵥ (snd : P1 × P1 →ᵃ[k] P1)).apply_lineMap (_, _) (_, _) c +@[simp] lemma lineMap_lineMap_right (p₀ p₁ : P1) (c d : k) : + lineMap p₀ (lineMap p₀ p₁ c) d = lineMap p₀ p₁ (d * c) := by simp [lineMap_apply, mul_smul] + +@[simp] lemma lineMap_lineMap_left (p₀ p₁ : P1) (c d : k) : + lineMap (lineMap p₀ p₁ c) p₁ d = lineMap p₀ p₁ (1 - (1 - d) * (1 - c)) := by + simp_rw [lineMap_apply_one_sub, ← lineMap_apply_one_sub p₁, lineMap_lineMap_right] + /-- Decomposition of an affine map in the special case when the point space and vector space are the same. -/ theorem decomp (f : V1 →ᵃ[k] V2) : (f : V1 → V2) = ⇑f.linear + fun _ => f 0 := by diff --git a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean index 74aad257f2367..8d58836617812 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Combination.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Combination.lean @@ -122,7 +122,7 @@ theorem weightedVSubOfPoint_eq_of_sum_eq_zero (w : ι → k) (p : ι → P) (h : base point when the sum of the weights is 1. -/ theorem weightedVSubOfPoint_vadd_eq_of_sum_eq_one (w : ι → k) (p : ι → P) (h : ∑ i ∈ s, w i = 1) (b₁ b₂ : P) : s.weightedVSubOfPoint p b₁ w +ᵥ b₁ = s.weightedVSubOfPoint p b₂ w +ᵥ b₂ := by - erw [weightedVSubOfPoint_apply, weightedVSubOfPoint_apply, ← @vsub_eq_zero_iff_eq V, + rw [weightedVSubOfPoint_apply, weightedVSubOfPoint_apply, ← @vsub_eq_zero_iff_eq V, vadd_vsub_assoc, vsub_vadd_eq_vsub_sub, ← add_sub_assoc, add_comm, add_sub_assoc, ← sum_sub_distrib] conv_lhs => diff --git a/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean b/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean index e59a26e0c1ce5..935dc82abfb3b 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/FiniteDimensional.lean @@ -29,14 +29,14 @@ section AffineSpace' variable (k : Type*) {V : Type*} {P : Type*} variable {ι : Type*} -open AffineSubspace FiniteDimensional Module +open AffineSubspace Module variable [DivisionRing k] [AddCommGroup V] [Module k V] [AffineSpace V P] /-- The `vectorSpan` of a finite set is finite-dimensional. -/ theorem finiteDimensional_vectorSpan_of_finite {s : Set P} (h : Set.Finite s) : FiniteDimensional k (vectorSpan k s) := - span_of_finite k <| h.vsub h + .span_of_finite k <| h.vsub h /-- The `vectorSpan` of a family indexed by a `Fintype` is finite-dimensional. -/ @@ -202,7 +202,7 @@ theorem finrank_vectorSpan_le_iff_not_affineIndependent [Fintype ι] (p : ι → variable {k} lemma AffineIndependent.card_le_finrank_succ [Fintype ι] {p : ι → P} (hp : AffineIndependent k p) : - Fintype.card ι ≤ FiniteDimensional.finrank k (vectorSpan k (Set.range p)) + 1 := by + Fintype.card ι ≤ Module.finrank k (vectorSpan k (Set.range p)) + 1 := by cases isEmpty_or_nonempty ι · simp [Fintype.card_eq_zero] rw [← tsub_le_iff_right] @@ -224,7 +224,7 @@ lemma AffineIndependent.card_le_card_of_subset_affineSpan {s t : Finset V} 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 + have finrank_le := add_le_add_right (Submodule.finrank_mono 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 _ _ @@ -257,7 +257,7 @@ theorem AffineIndependent.vectorSpan_image_finset_eq_of_le_of_card_eq_finrank_ad (hi : AffineIndependent k p) {s : Finset ι} {sm : Submodule k V} [FiniteDimensional k sm] (hle : vectorSpan k (s.image p : Set P) ≤ sm) (hc : Finset.card s = finrank k sm + 1) : vectorSpan k (s.image p : Set P) = sm := - eq_of_le_of_finrank_eq hle <| hi.finrank_vectorSpan_image_finset hc + Submodule.eq_of_le_of_finrank_eq hle <| hi.finrank_vectorSpan_image_finset hc /-- If the `vectorSpan` of a finite affinely independent family lies in a submodule with dimension one less than its @@ -266,7 +266,7 @@ theorem AffineIndependent.vectorSpan_eq_of_le_of_card_eq_finrank_add_one [Fintyp (hi : AffineIndependent k p) {sm : Submodule k V} [FiniteDimensional k sm] (hle : vectorSpan k (Set.range p) ≤ sm) (hc : Fintype.card ι = finrank k sm + 1) : vectorSpan k (Set.range p) = sm := - eq_of_le_of_finrank_eq hle <| hi.finrank_vectorSpan hc + Submodule.eq_of_le_of_finrank_eq hle <| hi.finrank_vectorSpan hc /-- If the `affineSpan` of a finite subset of an affinely independent family lies in an affine subspace whose direction has dimension one @@ -371,7 +371,7 @@ alias ⟨Collinear.finrank_le_one, _⟩ := collinear_iff_finrank_le_one /-- A subset of a collinear set is collinear. -/ theorem Collinear.subset {s₁ s₂ : Set P} (hs : s₁ ⊆ s₂) (h : Collinear k s₂) : Collinear k s₁ := - (rank_le_of_submodule (vectorSpan k s₁) (vectorSpan k s₂) (vectorSpan_mono k hs)).trans h + (Submodule.rank_mono (vectorSpan_mono k hs)).trans h /-- The `vectorSpan` of collinear points is finite-dimensional. -/ theorem Collinear.finiteDimensional_vectorSpan {s : Set P} (h : Collinear k s) : @@ -634,7 +634,7 @@ alias ⟨Coplanar.finrank_le_two, _⟩ := coplanar_iff_finrank_le_two /-- A subset of a coplanar set is coplanar. -/ theorem Coplanar.subset {s₁ s₂ : Set P} (hs : s₁ ⊆ s₂) (h : Coplanar k s₂) : Coplanar k s₁ := - (rank_le_of_submodule (vectorSpan k s₁) (vectorSpan k s₂) (vectorSpan_mono k hs)).trans h + (Submodule.rank_mono (vectorSpan_mono k hs)).trans h /-- Collinear points are coplanar. -/ theorem Collinear.coplanar {s : Set P} (h : Collinear k s) : Coplanar k s := @@ -669,7 +669,7 @@ section DivisionRing variable {k : Type*} {V : Type*} {P : Type*} -open AffineSubspace FiniteDimensional Module +open AffineSubspace Module Module variable [DivisionRing k] [AddCommGroup V] [Module k V] [AffineSpace V P] @@ -764,12 +764,12 @@ protected theorem finite_set [FiniteDimensional k V] {s : Set ι} (b : AffineBas finite_set_of_fin_dim_affineIndependent k b.ind theorem card_eq_finrank_add_one [Fintype ι] (b : AffineBasis ι k P) : - Fintype.card ι = FiniteDimensional.finrank k V + 1 := + Fintype.card ι = Module.finrank k V + 1 := have : FiniteDimensional k V := b.finiteDimensional b.ind.affineSpan_eq_top_iff_card_eq_finrank_add_one.mp b.tot theorem exists_affineBasis_of_finiteDimensional [Fintype ι] [FiniteDimensional k V] - (h : Fintype.card ι = FiniteDimensional.finrank k V + 1) : Nonempty (AffineBasis ι k P) := by + (h : Fintype.card ι = Module.finrank k V + 1) : Nonempty (AffineBasis ι k P) := by obtain ⟨s, b, hb⟩ := AffineBasis.exists_affineBasis k V P lift s to Finset P using b.finite_set refine ⟨b.reindex <| Fintype.equivOfCardEq ?_⟩ diff --git a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean index 0adb6c8ef435b..24d2fdd76c35b 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Independent.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Independent.lean @@ -104,7 +104,7 @@ theorem affineIndependent_iff_linearIndependent_vsub (p : ι → P) (i1 : ι) : intro x rw [hfdef] dsimp only - erw [dif_neg x.property, Subtype.coe_eta] + rw [dif_neg x.property, Subtype.coe_eta] rw [hfg] have hf : ∑ ι ∈ s2, f ι = 0 := by rw [Finset.sum_insert diff --git a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean index bc28ee54454cb..9f3c4c81c015f 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Ordered.lean @@ -134,15 +134,13 @@ theorem lineMap_le_right_iff_le (h : r < 1) : lineMap a b r ≤ b ↔ a ≤ b := Iff.trans (by rw [lineMap_apply_one]) (lineMap_le_lineMap_iff_of_lt h) @[simp] -theorem midpoint_le_right : midpoint k a b ≤ b ↔ a ≤ b := - lineMap_le_right_iff_le <| inv_lt_one one_lt_two +theorem midpoint_le_right : midpoint k a b ≤ b ↔ a ≤ b := lineMap_le_right_iff_le two_inv_lt_one theorem right_le_lineMap_iff_le (h : r < 1) : b ≤ lineMap a b r ↔ b ≤ a := lineMap_le_right_iff_le (E := Eᵒᵈ) h @[simp] -theorem right_le_midpoint : b ≤ midpoint k a b ↔ b ≤ a := - right_le_lineMap_iff_le <| inv_lt_one one_lt_two +theorem right_le_midpoint : b ≤ midpoint k a b ↔ b ≤ a := right_le_lineMap_iff_le two_inv_lt_one end diff --git a/Mathlib/LinearAlgebra/AffineSpace/Pointwise.lean b/Mathlib/LinearAlgebra/AffineSpace/Pointwise.lean index d7a79d2cfd7b2..3ad614ee09a53 100644 --- a/Mathlib/LinearAlgebra/AffineSpace/Pointwise.lean +++ b/Mathlib/LinearAlgebra/AffineSpace/Pointwise.lean @@ -69,7 +69,7 @@ theorem pointwise_vadd_span (v : V) (s : Set P) : v +ᵥ affineSpan k s = affine theorem map_pointwise_vadd (f : P₁ →ᵃ[k] P₂) (v : V₁) (s : AffineSubspace k P₁) : (v +ᵥ s).map f = f.linear v +ᵥ s.map f := by - erw [pointwise_vadd_eq_map, pointwise_vadd_eq_map, map_map, map_map] + rw [pointwise_vadd_eq_map, pointwise_vadd_eq_map, map_map, map_map] congr 1 ext exact f.map_vadd _ _ diff --git a/Mathlib/LinearAlgebra/Alternating/Basic.lean b/Mathlib/LinearAlgebra/Alternating/Basic.lean index 1c884e7f3cd86..007a27d357368 100644 --- a/Mathlib/LinearAlgebra/Alternating/Basic.lean +++ b/Mathlib/LinearAlgebra/Alternating/Basic.lean @@ -88,7 +88,7 @@ section Coercions instance instFunLike : FunLike (M [⋀^ι]→ₗ[R] N) (ι → M) N where coe f := f.toFun - coe_injective' := fun f g h ↦ by + coe_injective' f g h := by rcases f with ⟨⟨_, _, _⟩, _⟩ rcases g with ⟨⟨_, _, _⟩, _⟩ congr diff --git a/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean b/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean index 7ae6931a6aa29..847afe49e999e 100644 --- a/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean +++ b/Mathlib/LinearAlgebra/Alternating/DomCoprod.lean @@ -225,8 +225,8 @@ theorem MultilinearMap.domCoprod_alternization [DecidableEq ιa] [DecidableEq ι refine Quotient.inductionOn' σ fun σ => ?_ -- unfold the quotient mess left by `Finset.sum_partition` -- Porting note: Was `conv in .. => ..`. - erw - [@Finset.filter_congr _ _ (fun a => @Quotient.decidableEq _ _ + rw + [@Finset.filter_congr _ _ _ (fun a => @Quotient.decidableEq _ _ (QuotientGroup.leftRelDecidable (MonoidHom.range (Perm.sumCongrHom ιa ιb))) (Quotient.mk (QuotientGroup.leftRel (MonoidHom.range (Perm.sumCongrHom ιa ιb))) a) (Quotient.mk'' σ)) _ (s := Finset.univ) diff --git a/Mathlib/LinearAlgebra/Basis/Basic.lean b/Mathlib/LinearAlgebra/Basis/Basic.lean index 67204421b86e3..46ed8282bcd9a 100644 --- a/Mathlib/LinearAlgebra/Basis/Basic.lean +++ b/Mathlib/LinearAlgebra/Basis/Basic.lean @@ -280,7 +280,7 @@ protected noncomputable def span : Basis ι R (span R (range v)) := rfl have h₂ : map (Submodule.subtype (span R (range v))) (span R (range fun i => ⟨v i, this i⟩)) = span R (range v) := by - rw [← span_image, Submodule.coeSubtype] + rw [← span_image, Submodule.coe_subtype] -- Porting note: why doesn't `rw [h₁]` work here? exact congr_arg _ h₁ have h₃ : (x : M) ∈ map (Submodule.subtype (span R (range v))) diff --git a/Mathlib/LinearAlgebra/Basis/VectorSpace.lean b/Mathlib/LinearAlgebra/Basis/VectorSpace.lean index 5ffcc1cc36b43..e7a219e569dab 100644 --- a/Mathlib/LinearAlgebra/Basis/VectorSpace.lean +++ b/Mathlib/LinearAlgebra/Basis/VectorSpace.lean @@ -86,6 +86,61 @@ theorem subset_extend {s : Set V} (hs : LinearIndependent K ((↑) : s → V)) : s ⊆ hs.extend (Set.subset_univ _) := hs.subset_extend _ +/-- If `s` is a family of linearly independent vectors contained in a set `t` spanning `V`, +then one can get a basis of `V` containing `s` and contained in `t`. -/ +noncomputable def extendLe (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) : + Basis (hs.extend hst) K V := + Basis.mk + (@LinearIndependent.restrict_of_comp_subtype _ _ _ id _ _ _ _ (hs.linearIndependent_extend _)) + (le_trans ht <| Submodule.span_le.2 <| by simpa using hs.subset_span_extend hst) + +theorem extendLe_apply_self (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) (x : hs.extend hst) : + Basis.extendLe hs hst ht x = x := + Basis.mk_apply _ _ _ + +@[simp] +theorem coe_extendLe (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) : ⇑(Basis.extendLe hs hst ht) = ((↑) : _ → _) := + funext (extendLe_apply_self hs hst ht) + +theorem range_extendLe (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) : + range (Basis.extendLe hs hst ht) = hs.extend hst := by + rw [coe_extendLe, Subtype.range_coe_subtype, setOf_mem_eq] + +theorem subset_extendLe (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) : + s ⊆ range (Basis.extendLe hs hst ht) := + (range_extendLe hs hst ht).symm ▸ hs.subset_extend hst + +theorem extendLe_subset (hs : LinearIndependent K ((↑) : s → V)) + (hst : s ⊆ t) (ht : ⊤ ≤ span K t) : + range (Basis.extendLe hs hst ht) ⊆ t := + (range_extendLe hs hst ht).symm ▸ hs.extend_subset hst + +/-- If a set `s` spans the space, this is a basis contained in `s`. -/ +noncomputable def ofSpan (hs : ⊤ ≤ span K s) : + Basis ((linearIndependent_empty K V).extend (empty_subset s)) K V := + extendLe (linearIndependent_empty K V) (empty_subset s) hs + +theorem ofSpan_apply_self (hs : ⊤ ≤ span K s) + (x : (linearIndependent_empty K V).extend (empty_subset s)) : + Basis.ofSpan hs x = x := + extendLe_apply_self (linearIndependent_empty K V) (empty_subset s) hs x + +@[simp] +theorem coe_ofSpan (hs : ⊤ ≤ span K s) : ⇑(ofSpan hs) = ((↑) : _ → _) := + funext (ofSpan_apply_self hs) + +theorem range_ofSpan (hs : ⊤ ≤ span K s) : + range (ofSpan hs) = (linearIndependent_empty K V).extend (empty_subset s) := by + rw [coe_ofSpan, Subtype.range_coe_subtype, setOf_mem_eq] + +theorem ofSpan_subset (hs : ⊤ ≤ span K s) : range (ofSpan hs) ⊆ s := + extendLe_subset (linearIndependent_empty K V) (empty_subset s) hs + section variable (K V) diff --git a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean index f4d1dcbf680e7..bff969f2c534c 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Orthogonal.lean @@ -283,7 +283,7 @@ lemma ker_restrict_eq_of_codisjoint {p q : Submodule R M} (hpq : Codisjoint p q) {B : LinearMap.BilinForm R M} (hB : ∀ x ∈ p, ∀ y ∈ q, B x y = 0) : LinearMap.ker (B.restrict p) = (LinearMap.ker B).comap p.subtype := by ext ⟨z, hz⟩ - simp only [LinearMap.mem_ker, Submodule.mem_comap, Submodule.coeSubtype] + simp only [LinearMap.mem_ker, Submodule.mem_comap, Submodule.coe_subtype] refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ · ext w obtain ⟨x, hx, y, hy, rfl⟩ := Submodule.exists_add_eq_of_codisjoint hpq w @@ -294,7 +294,7 @@ lemma ker_restrict_eq_of_codisjoint {p q : Submodule R M} (hpq : Codisjoint p q) lemma inf_orthogonal_self_le_ker_restrict {W : Submodule R M} (b₁ : B.IsRefl) : W ⊓ B.orthogonal W ≤ (LinearMap.ker <| B.restrict W).map W.subtype := by rintro v ⟨hv : v ∈ W, hv' : v ∈ B.orthogonal W⟩ - simp only [Submodule.mem_map, mem_ker, restrict_apply, Submodule.coeSubtype, Subtype.exists, + simp only [Submodule.mem_map, mem_ker, restrict_apply, Submodule.coe_subtype, Subtype.exists, exists_and_left, exists_prop, exists_eq_right_right] refine ⟨?_, hv⟩ ext ⟨w, hw⟩ @@ -302,7 +302,7 @@ lemma inf_orthogonal_self_le_ker_restrict {W : Submodule R M} (b₁ : B.IsRefl) variable [FiniteDimensional K V] -open FiniteDimensional Submodule +open Module Submodule variable {B : BilinForm K V} diff --git a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean index 47f62c2cd1587..65f1bea36c373 100644 --- a/Mathlib/LinearAlgebra/BilinearForm/Properties.lean +++ b/Mathlib/LinearAlgebra/BilinearForm/Properties.lean @@ -464,7 +464,7 @@ noncomputable def symmCompOfNondegenerate (B₁ B₂ : BilinForm K V) (b₂ : B theorem comp_symmCompOfNondegenerate_apply (B₁ : BilinForm K V) {B₂ : BilinForm K V} (b₂ : B₂.Nondegenerate) (v : V) : B₂ (B₁.symmCompOfNondegenerate B₂ b₂ v) = B₁ v := by - erw [symmCompOfNondegenerate] + rw [symmCompOfNondegenerate] simp only [coe_comp, LinearEquiv.coe_coe, Function.comp_apply, DFunLike.coe_fn_eq] erw [LinearEquiv.apply_symm_apply (B₂.toDual b₂)] diff --git a/Mathlib/LinearAlgebra/BilinearMap.lean b/Mathlib/LinearAlgebra/BilinearMap.lean index b9e49faf0456c..10c008423626e 100644 --- a/Mathlib/LinearAlgebra/BilinearMap.lean +++ b/Mathlib/LinearAlgebra/BilinearMap.lean @@ -37,16 +37,15 @@ variable {R : Type*} [Semiring R] {S : Type*} [Semiring S] variable {R₂ : Type*} [Semiring R₂] {S₂ : Type*} [Semiring S₂] variable {M : Type*} {N : Type*} {P : Type*} variable {M₂ : Type*} {N₂ : Type*} {P₂ : Type*} -variable {Nₗ : Type*} {Pₗ : Type*} -variable {M' : Type*} {N' : Type*} {P' : Type*} +variable {Pₗ : Type*} +variable {M' : Type*} {P' : Type*} variable [AddCommMonoid M] [AddCommMonoid N] [AddCommMonoid P] -variable [AddCommMonoid M₂] [AddCommMonoid N₂] [AddCommMonoid P₂] -variable [AddCommMonoid Nₗ] [AddCommMonoid Pₗ] -variable [AddCommGroup M'] [AddCommGroup N'] [AddCommGroup P'] +variable [AddCommMonoid M₂] [AddCommMonoid N₂] [AddCommMonoid P₂] [AddCommMonoid Pₗ] +variable [AddCommGroup M'] [AddCommGroup P'] variable [Module R M] [Module S N] [Module R₂ P] [Module S₂ P] variable [Module R M₂] [Module S N₂] [Module R P₂] [Module S₂ P₂] variable [Module R Pₗ] [Module S Pₗ] -variable [Module R M'] [Module S N'] [Module R₂ P'] [Module S₂ P'] +variable [Module R M'] [Module R₂ P'] [Module S₂ P'] variable [SMulCommClass S₂ R₂ P] [SMulCommClass S R Pₗ] [SMulCommClass S₂ R₂ P'] variable [SMulCommClass S₂ R P₂] variable {ρ₁₂ : R →+* R₂} {σ₁₂ : S →+* S₂} @@ -376,14 +375,11 @@ end CommSemiring section CommRing -variable {R R₂ S S₂ M N P : Type*} -variable {Mₗ Nₗ Pₗ : Type*} -variable [CommRing R] [CommRing S] [CommRing R₂] [CommRing S₂] +variable {R M : Type*} [CommRing R] section AddCommGroup -variable [AddCommGroup M] [AddCommGroup N] [AddCommGroup P] -variable [Module R M] [Module S N] [Module R₂ P] [Module S₂ P] +variable [AddCommGroup M] [Module R M] theorem lsmul_injective [NoZeroSMulDivisors R M] {x : R} (hx : x ≠ 0) : Function.Injective (lsmul R M x) := diff --git a/Mathlib/LinearAlgebra/Charpoly/Basic.lean b/Mathlib/LinearAlgebra/Charpoly/Basic.lean index eff887d7c175d..a54a424f7f68e 100644 --- a/Mathlib/LinearAlgebra/Charpoly/Basic.lean +++ b/Mathlib/LinearAlgebra/Charpoly/Basic.lean @@ -51,7 +51,7 @@ section Coeff theorem charpoly_monic : f.charpoly.Monic := Matrix.charpoly_monic _ -open FiniteDimensional in +open Module in lemma charpoly_natDegree [Nontrivial R] [StrongRankCondition R] : natDegree (charpoly f) = finrank R M := by rw [charpoly, Matrix.charpoly_natDegree_eq_dim, finrank_eq_card_chooseBasisIndex] diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean index 4359ba5b328d0..e5f6c2be85383 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Grading.lean @@ -154,7 +154,7 @@ theorem evenOdd_induction (n : ZMod 2) {motive : ∀ x, x ∈ evenOdd Q n → Pr motive (ι Q m₁ * ι Q m₂ * x) (zero_add n ▸ SetLike.mul_mem_graded (ι_mul_ι_mem_evenOdd_zero Q m₁ m₂) hx)) (x : CliffordAlgebra Q) (hx : x ∈ evenOdd Q n) : motive x hx := by - apply Submodule.iSup_induction' (C := motive) _ (range_ι_pow 0 (Submodule.zero_mem _)) add + apply Submodule.iSup_induction' (C := motive) _ _ (range_ι_pow 0 (Submodule.zero_mem _)) add refine Subtype.rec ?_ simp_rw [ZMod.natCast_eq_iff, add_comm n.val] rintro n' ⟨k, rfl⟩ xv @@ -197,7 +197,7 @@ theorem even_induction {motive : ∀ x, x ∈ evenOdd Q 0 → Prop} motive (ι Q m₁ * ι Q m₂ * x) (zero_add (0 : ZMod 2) ▸ SetLike.mul_mem_graded (ι_mul_ι_mem_evenOdd_zero Q m₁ m₂) hx)) (x : CliffordAlgebra Q) (hx : x ∈ evenOdd Q 0) : motive x hx := by - refine evenOdd_induction (motive := motive) (fun rx => ?_) add ι_mul_ι_mul x hx + refine evenOdd_induction _ _ (motive := motive) (fun rx => ?_) add ι_mul_ι_mul x hx rintro ⟨r, rfl⟩ exact algebraMap r @@ -213,7 +213,7 @@ theorem odd_induction {P : ∀ x, x ∈ evenOdd Q 1 → Prop} P (CliffordAlgebra.ι Q m₁ * CliffordAlgebra.ι Q m₂ * x) (zero_add (1 : ZMod 2) ▸ SetLike.mul_mem_graded (ι_mul_ι_mem_evenOdd_zero Q m₁ m₂) hx)) (x : CliffordAlgebra Q) (hx : x ∈ evenOdd Q 1) : P x hx := by - refine evenOdd_induction (motive := P) (fun ιv => ?_) add ι_mul_ι_mul x hx + refine evenOdd_induction _ _ (motive := P) (fun ιv => ?_) add ι_mul_ι_mul x hx -- Porting note: was `simp_rw [ZMod.val_one, pow_one]`, lean4#1926 intro h; rw [ZMod.val_one, pow_one] at h; revert h rintro ⟨v, rfl⟩ diff --git a/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean b/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean index 1e9ee43c0a118..e06d940aa2396 100644 --- a/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/CliffordAlgebra/Prod.lean @@ -116,7 +116,7 @@ def ofProd : CliffordAlgebra (Q₁.prod Q₂) →ₐ[R] (evenOdd Q₁ ᵍ⊗[R] ∘ₗ (evenOdd Q₂ 1).subtype ∘ₗ (ι Q₂).codRestrict _ (ι_mem_evenOdd_one Q₂)), fun m => by simp_rw [LinearMap.coprod_apply, LinearMap.coe_comp, Function.comp_apply, - AlgHom.toLinearMap_apply, QuadraticMap.prod_apply, Submodule.coeSubtype, + AlgHom.toLinearMap_apply, QuadraticMap.prod_apply, Submodule.coe_subtype, GradedTensorProduct.includeLeft_apply, GradedTensorProduct.includeRight_apply, map_add, add_mul, mul_add, GradedTensorProduct.algebraMap_def, GradedTensorProduct.tmul_one_mul_one_tmul, GradedTensorProduct.tmul_one_mul_coe_tmul, diff --git a/Mathlib/LinearAlgebra/Coevaluation.lean b/Mathlib/LinearAlgebra/Coevaluation.lean index bd0df67099a43..31b64ef5ce5f8 100644 --- a/Mathlib/LinearAlgebra/Coevaluation.lean +++ b/Mathlib/LinearAlgebra/Coevaluation.lean @@ -25,7 +25,7 @@ noncomputable section section coevaluation -open TensorProduct FiniteDimensional +open TensorProduct Module open TensorProduct diff --git a/Mathlib/LinearAlgebra/Contraction.lean b/Mathlib/LinearAlgebra/Contraction.lean index 8ba1276a30496..0e7e5c811a68a 100644 --- a/Mathlib/LinearAlgebra/Contraction.lean +++ b/Mathlib/LinearAlgebra/Contraction.lean @@ -201,7 +201,7 @@ section CommRing variable [CommRing R] variable [AddCommGroup M] [AddCommGroup N] [AddCommGroup P] [AddCommGroup Q] variable [Module R M] [Module R N] [Module R P] [Module R Q] -variable [Free R M] [Finite R M] [Free R N] [Finite R N] +variable [Free R M] [Module.Finite R M] [Free R N] [Module.Finite R N] /-- When `M` is a finite free module, the map `lTensorHomToHomLTensor` is an equivalence. Note that `lTensorHomEquivHomLTensor` is not defined directly in terms of diff --git a/Mathlib/LinearAlgebra/CrossProduct.lean b/Mathlib/LinearAlgebra/CrossProduct.lean index b422330a52d9c..8fb6567b4ec21 100644 --- a/Mathlib/LinearAlgebra/CrossProduct.lean +++ b/Mathlib/LinearAlgebra/CrossProduct.lean @@ -154,8 +154,8 @@ lemma crossProduct_ne_zero_iff_linearIndependent {F : Type*} [Field F] {v w : Fi · rw [LinearIndependent.pair_iff' hv, not_forall_not] rintro ⟨a, rfl⟩ rw [LinearMap.map_smul, cross_self, smul_zero] - have hv' : v = ![v 0, v 1, v 2] := List.ofFn_inj.mp rfl - have hw' : w = ![w 0, w 1, w 2] := List.ofFn_inj.mp rfl + have hv' : v = ![v 0, v 1, v 2] := by simp [← List.ofFn_inj] + have hw' : w = ![w 0, w 1, w 2] := by simp [← List.ofFn_inj] intro h1 h2 simp_rw [cross_apply, cons_eq_zero_iff, zero_empty, and_true, sub_eq_zero] at h1 have h20 := LinearIndependent.pair_iff.mp h2 (- w 0) (v 0) diff --git a/Mathlib/LinearAlgebra/DFinsupp.lean b/Mathlib/LinearAlgebra/DFinsupp.lean index fde50b6846a2f..7f631f041c8c3 100644 --- a/Mathlib/LinearAlgebra/DFinsupp.lean +++ b/Mathlib/LinearAlgebra/DFinsupp.lean @@ -299,7 +299,7 @@ theorem biSup_eq_range_dfinsupp_lsum (p : ι → Prop) [DecidablePred p] (S : ι apply le_antisymm · refine iSup₂_le fun i hi y hy => ⟨DFinsupp.single i ⟨y, hy⟩, ?_⟩ rw [LinearMap.comp_apply, filterLinearMap_apply, filter_single_pos _ _ hi] - simp only [lsum_apply_apply, sumAddHom_single, LinearMap.toAddMonoidHom_coe, coeSubtype] + simp only [lsum_apply_apply, sumAddHom_single, LinearMap.toAddMonoidHom_coe, coe_subtype] · rintro x ⟨v, rfl⟩ refine dfinsupp_sumAddHom_mem _ _ _ fun i _ => ?_ refine mem_iSup_of_mem i ?_ @@ -322,7 +322,7 @@ theorem mem_iSup_iff_exists_dfinsupp' (p : ι → Submodule R N) [∀ (i) (x : p (x : N) : x ∈ iSup p ↔ ∃ f : Π₀ i, p i, (f.sum fun i xi => ↑xi) = x := by rw [mem_iSup_iff_exists_dfinsupp] simp_rw [DFinsupp.lsum_apply_apply, DFinsupp.sumAddHom_apply, - LinearMap.toAddMonoidHom_coe, coeSubtype] + LinearMap.toAddMonoidHom_coe, coe_subtype] theorem mem_biSup_iff_exists_dfinsupp (p : ι → Prop) [DecidablePred p] (S : ι → Submodule R N) (x : N) : diff --git a/Mathlib/LinearAlgebra/Determinant.lean b/Mathlib/LinearAlgebra/Determinant.lean index ce891c2dddd94..dc9936ab62f2a 100644 --- a/Mathlib/LinearAlgebra/Determinant.lean +++ b/Mathlib/LinearAlgebra/Determinant.lean @@ -207,7 +207,7 @@ theorem det_toLin' (f : Matrix ι ι R) : LinearMap.det (Matrix.toLin' f) = Matr /-- To show `P (LinearMap.det f)` it suffices to consider `P (Matrix.det (toMatrix _ _ f))` and `P 1`. -/ --- @[elab_as_elim] -- Porting note: This attr can't be applied. +@[elab_as_elim] theorem det_cases [DecidableEq M] {P : A → Prop} (f : M →ₗ[A] M) (hb : ∀ (s : Finset M) (b : Basis s A M), P (Matrix.det (toMatrix b b f))) (h1 : P 1) : P (LinearMap.det f) := by @@ -231,15 +231,15 @@ theorem det_id : LinearMap.det (LinearMap.id : M →ₗ[A] M) = 1 := @[simp] theorem det_smul {𝕜 : Type*} [Field 𝕜] {M : Type*} [AddCommGroup M] [Module 𝕜 M] (c : 𝕜) (f : M →ₗ[𝕜] M) : - LinearMap.det (c • f) = c ^ FiniteDimensional.finrank 𝕜 M * LinearMap.det f := by + LinearMap.det (c • f) = c ^ Module.finrank 𝕜 M * LinearMap.det f := by by_cases H : ∃ s : Finset M, Nonempty (Basis s 𝕜 M) · have : FiniteDimensional 𝕜 M := by rcases H with ⟨s, ⟨hs⟩⟩ exact FiniteDimensional.of_fintype_basis hs - simp only [← det_toMatrix (FiniteDimensional.finBasis 𝕜 M), LinearEquiv.map_smul, + simp only [← det_toMatrix (Module.finBasis 𝕜 M), LinearEquiv.map_smul, Fintype.card_fin, Matrix.det_smul] · classical - have : FiniteDimensional.finrank 𝕜 M = 0 := finrank_eq_zero_of_not_exists_basis H + have : Module.finrank 𝕜 M = 0 := finrank_eq_zero_of_not_exists_basis H simp [coe_det, H, this] theorem det_zero' {ι : Type*} [Finite ι] [Nonempty ι] (b : Basis ι A M) : @@ -253,7 +253,7 @@ and `0` otherwise. We give a formula that also works in infinite dimension, wher the determinant to be `1`. -/ @[simp] theorem det_zero {𝕜 : Type*} [Field 𝕜] {M : Type*} [AddCommGroup M] [Module 𝕜 M] : - LinearMap.det (0 : M →ₗ[𝕜] M) = (0 : 𝕜) ^ FiniteDimensional.finrank 𝕜 M := by + LinearMap.det (0 : M →ₗ[𝕜] M) = (0 : 𝕜) ^ Module.finrank 𝕜 M := by simp only [← zero_smul 𝕜 (1 : M →ₗ[𝕜] M), det_smul, mul_one, MonoidHom.map_one] theorem det_eq_one_of_subsingleton [Subsingleton M] (f : M →ₗ[R] M) : @@ -263,14 +263,14 @@ theorem det_eq_one_of_subsingleton [Subsingleton M] (f : M →ₗ[R] M) : exact Matrix.det_isEmpty theorem det_eq_one_of_finrank_eq_zero {𝕜 : Type*} [Field 𝕜] {M : Type*} [AddCommGroup M] - [Module 𝕜 M] (h : FiniteDimensional.finrank 𝕜 M = 0) (f : M →ₗ[𝕜] M) : + [Module 𝕜 M] (h : Module.finrank 𝕜 M = 0) (f : M →ₗ[𝕜] M) : LinearMap.det (f : M →ₗ[𝕜] M) = 1 := by classical refine @LinearMap.det_cases M _ 𝕜 _ _ _ (fun t => t = 1) f ?_ rfl intro s b have : IsEmpty s := by rw [← Fintype.card_eq_zero_iff] - exact (FiniteDimensional.finrank_eq_card_basis b).symm.trans h + exact (Module.finrank_eq_card_basis b).symm.trans h exact Matrix.det_isEmpty /-- Conjugating a linear map by a linear equiv does not change its determinant. -/ @@ -423,8 +423,8 @@ theorem LinearEquiv.coe_ofIsUnitDet {f : M →ₗ[R] M'} {v : Basis ι R M} {v' determinant is nonzero. -/ abbrev LinearMap.equivOfDetNeZero {𝕜 : Type*} [Field 𝕜] {M : Type*} [AddCommGroup M] [Module 𝕜 M] [FiniteDimensional 𝕜 M] (f : M →ₗ[𝕜] M) (hf : LinearMap.det f ≠ 0) : M ≃ₗ[𝕜] M := - have : IsUnit (LinearMap.toMatrix (FiniteDimensional.finBasis 𝕜 M) - (FiniteDimensional.finBasis 𝕜 M) f).det := by + have : IsUnit (LinearMap.toMatrix (Module.finBasis 𝕜 M) + (Module.finBasis 𝕜 M) f).det := by rw [LinearMap.det_toMatrix] exact isUnit_iff_ne_zero.2 hf LinearEquiv.ofIsUnitDet this diff --git a/Mathlib/LinearAlgebra/Dimension/Basic.lean b/Mathlib/LinearAlgebra/Dimension/Basic.lean index 9508cc5b7d60c..6da291d1211aa 100644 --- a/Mathlib/LinearAlgebra/Dimension/Basic.lean +++ b/Mathlib/LinearAlgebra/Dimension/Basic.lean @@ -93,15 +93,6 @@ theorem cardinal_le_rank' {s : Set M} end LinearIndependent -@[deprecated (since := "2023-12-27")] -alias cardinal_lift_le_rank_of_linearIndependent := LinearIndependent.cardinal_lift_le_rank -@[deprecated (since := "2023-12-27")] -alias cardinal_lift_le_rank_of_linearIndependent' := LinearIndependent.cardinal_lift_le_rank -@[deprecated (since := "2023-12-27")] -alias cardinal_le_rank_of_linearIndependent := LinearIndependent.cardinal_le_rank -@[deprecated (since := "2023-12-27")] -alias cardinal_le_rank_of_linearIndependent' := LinearIndependent.cardinal_le_rank' - section SurjectiveInjective section Module @@ -285,11 +276,12 @@ theorem lift_rank_map_le (f : M →ₗ[R] M') (p : Submodule R M) : theorem rank_map_le (f : M →ₗ[R] M₁) (p : Submodule R M) : Module.rank R (p.map f) ≤ Module.rank R p := by simpa using lift_rank_map_le f p -theorem rank_le_of_submodule (s t : Submodule R M) (h : s ≤ t) : - Module.rank R s ≤ Module.rank R t := +lemma Submodule.rank_mono {s t : Submodule R M} (h : s ≤ t) : Module.rank R s ≤ Module.rank R t := (Submodule.inclusion h).rank_le_of_injective fun ⟨x, _⟩ ⟨y, _⟩ eq => Subtype.eq <| show x = y from Subtype.ext_iff_val.1 eq +@[deprecated (since := "2024-09-30")] alias rank_le_of_submodule := Submodule.rank_mono + /-- Two linearly equivalent vector spaces have the same dimension, a version with different universes. -/ theorem LinearEquiv.lift_rank_eq (f : M ≃ₗ[R] M') : @@ -331,9 +323,11 @@ theorem rank_range_of_surjective (f : M →ₗ[R] M') (h : Surjective f) : Module.rank R (LinearMap.range f) = Module.rank R M' := by rw [LinearMap.range_eq_top.2 h, rank_top] -theorem rank_submodule_le (s : Submodule R M) : Module.rank R s ≤ Module.rank R M := by +theorem Submodule.rank_le (s : Submodule R M) : Module.rank R s ≤ Module.rank R M := by rw [← rank_top R M] - exact rank_le_of_submodule _ _ le_top + exact rank_mono le_top + +@[deprecated (since := "2024-10-02")] alias rank_submodule_le := Submodule.rank_le theorem LinearMap.lift_rank_le_of_surjective (f : M →ₗ[R] M') (h : Surjective f) : lift.{v} (Module.rank R M') ≤ lift.{v'} (Module.rank R M) := by diff --git a/Mathlib/LinearAlgebra/Dimension/Constructions.lean b/Mathlib/LinearAlgebra/Dimension/Constructions.lean index 2cf63df0ef942..9a7b997644973 100644 --- a/Mathlib/LinearAlgebra/Dimension/Constructions.lean +++ b/Mathlib/LinearAlgebra/Dimension/Constructions.lean @@ -35,7 +35,7 @@ universe u v v' u₁' w w' variable {R S : Type u} {M : Type v} {M' : Type v'} {M₁ : Type v} variable {ι : Type w} {ι' : Type w'} {η : Type u₁'} {φ : η → Type*} -open Cardinal Basis Submodule Function Set FiniteDimensional DirectSum +open Basis Cardinal DirectSum Function Module Set Submodule variable [Ring R] [CommRing S] [AddCommGroup M] [AddCommGroup M'] [AddCommGroup M₁] variable [Module R M] @@ -142,7 +142,7 @@ theorem rank_prod' : Module.rank R (M × M₁) = Module.rank R M + Module.rank R /-- The finrank of `M × M'` is `(finrank R M) + (finrank R M')`. -/ @[simp] -theorem FiniteDimensional.finrank_prod [Module.Finite R M] [Module.Finite R M'] : +theorem Module.finrank_prod [Module.Finite R M] [Module.Finite R M'] : finrank R (M × M') = finrank R M + finrank R M' := by simp [finrank, rank_lt_aleph0 R M, rank_lt_aleph0 R M'] @@ -209,7 +209,7 @@ theorem rank_matrix'' (m n : Type u) [Finite m] [Finite n] : open Fintype -namespace FiniteDimensional +namespace Module @[simp] theorem finrank_finsupp {ι : Type v} [Fintype ι] : finrank R (ι →₀ M) = card ι * finrank R M := by @@ -234,7 +234,7 @@ theorem finrank_directSum {ι : Type v} [Fintype ι] (M : ι → Type w) [∀ i theorem finrank_matrix (m n : Type*) [Fintype m] [Fintype n] : finrank R (Matrix m n R) = card m * card n := by simp [finrank] -end FiniteDimensional +end Module end Finsupp @@ -260,13 +260,13 @@ theorem rank_pi [Finite η] : Module.rank R (∀ i, φ i) = variable (R) /-- The finrank of `(ι → R)` is `Fintype.card ι`. -/ -theorem FiniteDimensional.finrank_pi {ι : Type v} [Fintype ι] : +theorem Module.finrank_pi {ι : Type v} [Fintype ι] : finrank R (ι → R) = Fintype.card ι := by simp [finrank] --TODO: this should follow from `LinearEquiv.finrank_eq`, that is over a field. /-- The finrank of a finite product is the sum of the finranks. -/ -theorem FiniteDimensional.finrank_pi_fintype +theorem Module.finrank_pi_fintype {ι : Type v} [Fintype ι] {M : ι → Type w} [∀ i : ι, AddCommGroup (M i)] [∀ i : ι, Module R (M i)] [∀ i : ι, Module.Free R (M i)] [∀ i : ι, Module.Finite R (M i)] : finrank R (∀ i, M i) = ∑ i, finrank R (M i) := by @@ -294,12 +294,12 @@ variable (R) /-- The vector space of functions on a `Fintype ι` has finrank equal to the cardinality of `ι`. -/ @[simp] -theorem FiniteDimensional.finrank_fintype_fun_eq_card : finrank R (η → R) = Fintype.card η := +theorem Module.finrank_fintype_fun_eq_card : finrank R (η → R) = Fintype.card η := finrank_eq_of_rank_eq rank_fun' /-- The vector space of functions on `Fin n` has finrank equal to `n`. -/ -- @[simp] -- Porting note (#10618): simp already proves this -theorem FiniteDimensional.finrank_fin_fun {n : ℕ} : finrank R (Fin n → R) = n := by simp +theorem Module.finrank_fin_fun {n : ℕ} : finrank R (Fin n → R) = n := by simp variable {R} @@ -343,7 +343,7 @@ theorem rank_tensorProduct' : /-- The `S`-finrank of `M ⊗[R] M'` is `(finrank S M) * (finrank R M')`. -/ @[simp] -theorem FiniteDimensional.finrank_tensorProduct : +theorem Module.finrank_tensorProduct : finrank R (M ⊗[S] M') = finrank R M * finrank S M' := by simp [finrank] end TensorProduct @@ -352,7 +352,7 @@ section SubmoduleRank section -open FiniteDimensional +open Module namespace Submodule @@ -372,7 +372,7 @@ variable [StrongRankCondition R] /-- The dimension of a submodule is bounded by the dimension of the ambient space. -/ theorem Submodule.finrank_le [Module.Finite R M] (s : Submodule R M) : finrank R s ≤ finrank R M := - toNat_le_toNat (rank_submodule_le s) (rank_lt_aleph0 _ _) + toNat_le_toNat (Submodule.rank_le s) (rank_lt_aleph0 _ _) /-- The dimension of a quotient is bounded by the dimension of the ambient space. -/ theorem Submodule.finrank_quotient_le [Module.Finite R M] (s : Submodule R M) : @@ -386,12 +386,12 @@ theorem Submodule.finrank_map_le finrank R (p.map f) ≤ finrank R p := finrank_le_finrank_of_rank_le_rank (lift_rank_map_le _ _) (rank_lt_aleph0 _ _) -theorem Submodule.finrank_le_finrank_of_le {s t : Submodule R M} [Module.Finite R t] (hst : s ≤ t) : +theorem Submodule.finrank_mono {s t : Submodule R M} [Module.Finite R t] (hst : s ≤ t) : finrank R s ≤ finrank R t := - calc - finrank R s = finrank R (s.comap t.subtype) := - (Submodule.comapSubtypeEquivOfLe hst).finrank_eq.symm - _ ≤ finrank R t := Submodule.finrank_le _ + Cardinal.toNat_le_toNat (Submodule.rank_mono hst) (rank_lt_aleph0 R ↥t) + +@[deprecated (since := "2024-09-30")] +alias Submodule.finrank_le_finrank_of_le := Submodule.finrank_mono end @@ -413,7 +413,7 @@ theorem rank_span_finset_le (s : Finset M) : Module.rank R (span R (s : Set M)) 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 _) -open Submodule FiniteDimensional +open Submodule Module variable (R) diff --git a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean index 81356f0bed052..cf1afda61d172 100644 --- a/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean +++ b/Mathlib/LinearAlgebra/Dimension/DivisionRing.lean @@ -12,7 +12,7 @@ import Mathlib.LinearAlgebra.Dimension.RankNullity /-! # Dimension of vector spaces -In this file we provide results about `Module.rank` and `FiniteDimensional.finrank` of vector spaces +In this file we provide results about `Module.rank` and `Module.finrank` of vector spaces over division rings. ## Main statements @@ -112,7 +112,7 @@ end Module section Basis -open FiniteDimensional +open Module variable [DivisionRing K] [AddCommGroup V] [Module K V] diff --git a/Mathlib/LinearAlgebra/Dimension/Finite.lean b/Mathlib/LinearAlgebra/Dimension/Finite.lean index 32cbe00cac733..90c82db1cfcc3 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finite.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finite.lean @@ -26,7 +26,7 @@ variable [Module R M] [Module R M'] [Module R M₁] attribute [local instance] nontrivial_of_invariantBasisNumber -open Cardinal Basis Submodule Function Set FiniteDimensional +open Basis Cardinal Function Module Set Submodule theorem rank_le {n : ℕ} (H : ∀ s : Finset M, (LinearIndependent R fun i : s => (i : M)) → s.card ≤ n) : @@ -191,15 +191,6 @@ theorem setFinite [Module.Finite R M] {b : Set M} end LinearIndependent -@[deprecated (since := "2023-12-27")] -alias cardinal_mk_le_finrank_of_linearIndependent := LinearIndependent.cardinal_mk_le_finrank -@[deprecated (since := "2023-12-27")] -alias fintype_card_le_finrank_of_linearIndependent := LinearIndependent.fintype_card_le_finrank -@[deprecated (since := "2023-12-27")] -alias finset_card_le_finrank_of_linearIndependent := LinearIndependent.finset_card_le_finrank -@[deprecated (since := "2023-12-27")] -alias Module.Finite.lt_aleph0_of_linearIndependent := LinearIndependent.lt_aleph0_of_finite - lemma exists_set_linearIndependent_of_lt_rank {n : Cardinal} (hn : n < Module.rank R M) : ∃ s : Set M, #s = n ∧ LinearIndependent R ((↑) : s → M) := by obtain ⟨⟨s, hs⟩, hs'⟩ := exists_lt_of_lt_ciSup' (hn.trans_eq (Module.rank_def R M)) @@ -363,7 +354,7 @@ variable [Nontrivial R] /-- A (finite dimensional) space that is a subsingleton has zero `finrank`. -/ @[nontriviality] -theorem FiniteDimensional.finrank_zero_of_subsingleton [Subsingleton M] : +theorem Module.finrank_zero_of_subsingleton [Subsingleton M] : finrank R M = 0 := by rw [finrank, rank_subsingleton', _root_.map_zero] @@ -374,12 +365,12 @@ section variable [NoZeroSMulDivisors R M] /-- A finite dimensional space is nontrivial if it has positive `finrank`. -/ -theorem FiniteDimensional.nontrivial_of_finrank_pos (h : 0 < finrank R M) : Nontrivial M := +theorem Module.nontrivial_of_finrank_pos (h : 0 < finrank R M) : Nontrivial M := rank_pos_iff_nontrivial.mp (lt_rank_of_lt_finrank h) /-- A finite dimensional space is nontrivial if it has `finrank` equal to the successor of a natural number. -/ -theorem FiniteDimensional.nontrivial_of_finrank_eq_succ {n : ℕ} +theorem Module.nontrivial_of_finrank_eq_succ {n : ℕ} (hn : finrank R M = n.succ) : Nontrivial M := nontrivial_of_finrank_pos (R := R) (by rw [hn]; exact n.succ_pos) @@ -398,31 +389,31 @@ section StrongRankCondition 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] : +theorem Module.finrank_pos_iff_exists_ne_zero [NoZeroSMulDivisors 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 /-- An `R`-finite torsion-free module has positive `finrank` iff it is nontrivial. -/ -theorem FiniteDimensional.finrank_pos_iff [NoZeroSMulDivisors R M] : +theorem Module.finrank_pos_iff [NoZeroSMulDivisors R M] : 0 < finrank R M ↔ Nontrivial M := by rw [← rank_pos_iff_nontrivial (R := R), ← finrank_eq_rank] norm_cast /-- A nontrivial finite dimensional space has positive `finrank`. -/ -theorem FiniteDimensional.finrank_pos [NoZeroSMulDivisors R M] [h : Nontrivial M] : +theorem Module.finrank_pos [NoZeroSMulDivisors R M] [h : Nontrivial M] : 0 < finrank R M := finrank_pos_iff.mpr h -/-- See `FiniteDimensional.finrank_zero_iff` +/-- See `Module.finrank_zero_iff` for the stronger version with `NoZeroSMulDivisors R M`. -/ -theorem FiniteDimensional.finrank_eq_zero_iff : +theorem Module.finrank_eq_zero_iff : 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] +theorem Module.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 := by rw [← rank_eq_zero_iff_isTorsion (R := R), ← finrank_eq_rank] @@ -430,14 +421,14 @@ theorem FiniteDimensional.finrank_eq_zero_iff_isTorsion {R} [CommRing R] [Strong /-- 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] : +theorem Module.finrank_zero_iff [NoZeroSMulDivisors R M] : finrank R M = 0 ↔ Subsingleton M := by rw [← rank_zero_iff (R := R), ← finrank_eq_rank] norm_cast end StrongRankCondition -theorem FiniteDimensional.finrank_eq_zero_of_rank_eq_zero (h : Module.rank R M = 0) : +theorem Module.finrank_eq_zero_of_rank_eq_zero (h : Module.rank R M = 0) : finrank R M = 0 := by delta finrank rw [h, zero_toNat] diff --git a/Mathlib/LinearAlgebra/Dimension/Finrank.lean b/Mathlib/LinearAlgebra/Dimension/Finrank.lean index 9bf3954c81775..69668ef8b667a 100644 --- a/Mathlib/LinearAlgebra/Dimension/Finrank.lean +++ b/Mathlib/LinearAlgebra/Dimension/Finrank.lean @@ -13,7 +13,7 @@ Definition of the rank of a module, or dimension of a vector space, as a natural ## Main definitions -Defined is `FiniteDimensional.finrank`, the dimension of a finite dimensional space, returning a +Defined is `Module.finrank`, the dimension of a finite dimensional space, returning a `Nat`, as opposed to `Module.rank`, which returns a `Cardinal`. When the space has infinite dimension, its `finrank` is by convention set to `0`. @@ -38,7 +38,7 @@ open Cardinal Submodule Module Function variable {R : Type u} {M : Type v} {N : Type w} variable [Ring R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] -namespace FiniteDimensional +namespace Module section Ring @@ -52,6 +52,8 @@ of `M` over `R`. noncomputable def finrank (R M : Type*) [Semiring R] [AddCommGroup M] [Module R M] : ℕ := Cardinal.toNat (Module.rank R M) +@[deprecated (since := "2024-10-01")] protected alias _root_.FiniteDimensional.finrank := finrank + theorem finrank_eq_of_rank_eq {n : ℕ} (h : Module.rank R M = ↑n) : finrank R M = n := by apply_fun toNat at h rw [toNat_natCast] at h @@ -92,9 +94,9 @@ theorem finrank_le_finrank_of_rank_le_rank end Ring -end FiniteDimensional +end Module -open FiniteDimensional +open Module namespace LinearEquiv diff --git a/Mathlib/LinearAlgebra/Dimension/Free.lean b/Mathlib/LinearAlgebra/Dimension/Free.lean index 3b06f6f965e75..af3007b4da717 100644 --- a/Mathlib/LinearAlgebra/Dimension/Free.lean +++ b/Mathlib/LinearAlgebra/Dimension/Free.lean @@ -14,7 +14,7 @@ import Mathlib.SetTheory.Cardinal.Finsupp ## Main result - `LinearEquiv.nonempty_equiv_iff_lift_rank_eq`: Two free modules are isomorphic iff they have the same dimension. -- `FiniteDimensional.finBasis`: +- `Module.finBasis`: An arbitrary basis of a finite free module indexed by `Fin n` given `finrank R M = n`. -/ @@ -24,7 +24,7 @@ noncomputable section universe u v v' w -open Cardinal Basis Submodule Function Set DirectSum FiniteDimensional +open Cardinal Basis Submodule Function Set DirectSum Module section Tower @@ -57,7 +57,7 @@ theorem rank_mul_rank (A : Type v) [AddCommGroup 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 FiniteDimensional.finrank_mul_finrank : finrank F K * finrank K A = finrank F A := by +theorem Module.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] @@ -79,7 +79,7 @@ theorem rank_eq_card_chooseBasisIndex : Module.rank R M = #(ChooseBasisIndex R M (chooseBasis R M).mk_eq_rank''.symm /-- The finrank of a free module `M` over `R` is the cardinality of `ChooseBasisIndex R M`. -/ -theorem _root_.FiniteDimensional.finrank_eq_card_chooseBasisIndex [Module.Finite R M] : +theorem _root_.Module.finrank_eq_card_chooseBasisIndex [Module.Finite R M] : finrank R M = Fintype.card (ChooseBasisIndex R M) := by simp [finrank, rank_eq_card_chooseBasisIndex] @@ -161,35 +161,30 @@ noncomputable def LinearEquiv.ofFinrankEq [Module.Finite R M] [Module.Finite R M variable {M M'} +namespace Module + /-- See `rank_lt_aleph0` for the inverse direction without `Module.Free R M`. -/ -lemma Module.rank_lt_alpeh0_iff : - Module.rank R M < ℵ₀ ↔ Module.Finite R M := by +lemma rank_lt_aleph0_iff : Module.rank R M < ℵ₀ ↔ Module.Finite R M := by rw [Free.rank_eq_card_chooseBasisIndex, mk_lt_aleph0_iff] exact ⟨fun h ↦ Finite.of_basis (Free.chooseBasis R M), fun I ↦ Finite.of_fintype (Free.ChooseBasisIndex R M)⟩ -theorem FiniteDimensional.finrank_of_not_finite - (h : ¬Module.Finite R M) : - finrank R M = 0 := by - rw [finrank, toNat_eq_zero, ← not_lt, Module.rank_lt_alpeh0_iff] +theorem finrank_of_not_finite (h : ¬Module.Finite R M) : finrank R M = 0 := by + rw [finrank, toNat_eq_zero, ← not_lt, Module.rank_lt_aleph0_iff] exact .inr h -theorem Module.finite_of_finrank_pos (h : 0 < finrank R M) : - Module.Finite R M := by +theorem finite_of_finrank_pos (h : 0 < finrank R M) : Module.Finite R M := by contrapose h simp [finrank_of_not_finite h] -theorem Module.finite_of_finrank_eq_succ {n : ℕ} - (hn : finrank R M = n.succ) : Module.Finite R M := - Module.finite_of_finrank_pos <| by rw [hn]; exact n.succ_pos +theorem finite_of_finrank_eq_succ {n : ℕ} (hn : finrank R M = n.succ) : Module.Finite R M := + finite_of_finrank_pos <| by rw [hn]; exact n.succ_pos -theorem Module.finite_iff_of_rank_eq_nsmul {W} [AddCommGroup W] - [Module R W] [Module.Free R W] {n : ℕ} (hn : n ≠ 0) - (hVW : Module.rank R M = n • Module.rank R W) : +theorem finite_iff_of_rank_eq_nsmul {W} [AddCommGroup W] [Module R W] [Module.Free R W] {n : ℕ} + (hn : n ≠ 0) (hVW : Module.rank R M = n • Module.rank R W) : Module.Finite R M ↔ Module.Finite R W := by - simp only [← rank_lt_alpeh0_iff, hVW, nsmul_lt_aleph0_iff_of_ne_zero hn] + simp only [← rank_lt_aleph0_iff, hVW, nsmul_lt_aleph0_iff_of_ne_zero hn] -namespace FiniteDimensional variable (R M) /-- A finite rank free module has a basis indexed by `Fin (finrank R M)`. -/ @@ -220,4 +215,4 @@ theorem basisUnique_repr_eq_zero_iff {ι : Type*} [Unique ι] (basisUnique ι h).repr.map_eq_zero_iff.mp (Finsupp.ext fun j => Subsingleton.elim i j ▸ hv), fun hv => by rw [hv, LinearEquiv.map_zero, Finsupp.zero_apply]⟩ -end FiniteDimensional +end Module diff --git a/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean index 507f9e3b737de..17254b66084e3 100644 --- a/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/FreeAndStrongRankCondition.lean @@ -17,7 +17,7 @@ and `Mathlib/LinearAlgebra/FiniteDimensional.lean`. -/ -open Cardinal Submodule Set FiniteDimensional +open Cardinal Module Module Set Submodule universe u v @@ -27,7 +27,7 @@ variable {K : Type u} {V : Type v} [Ring K] [StrongRankCondition K] [AddCommGrou /-- The `ι` indexed basis on `V`, where `ι` is an empty type and `V` is zero-dimensional. -See also `FiniteDimensional.finBasis`. +See also `Module.finBasis`. -/ noncomputable def Basis.ofRankEqZero [Module.Free K V] {ι : Type*} [IsEmpty ι] (hV : Module.rank K V = 0) : Basis ι K V := @@ -186,7 +186,7 @@ theorem finrank_eq_one_iff [Module.Free K V] (ι : Type*) [Unique ι] : finrank K V = 1 ↔ Nonempty (Basis ι K V) := by constructor · intro h - exact ⟨basisUnique ι h⟩ + exact ⟨Module.basisUnique ι h⟩ · rintro ⟨b⟩ simpa using finrank_eq_card_basis b diff --git a/Mathlib/LinearAlgebra/Dimension/LinearMap.lean b/Mathlib/LinearAlgebra/Dimension/LinearMap.lean index 418403e43f094..ca2cb869a8ec5 100644 --- a/Mathlib/LinearAlgebra/Dimension/LinearMap.lean +++ b/Mathlib/LinearAlgebra/Dimension/LinearMap.lean @@ -34,7 +34,7 @@ abbrev rank (f : V →ₗ[K] V') : Cardinal := Module.rank K (LinearMap.range f) theorem rank_le_range (f : V →ₗ[K] V') : rank f ≤ Module.rank K V' := - rank_submodule_le _ + Submodule.rank_le _ theorem rank_le_domain (f : V →ₗ[K] V₁) : rank f ≤ Module.rank K V := rank_range_le _ @@ -46,7 +46,7 @@ theorem rank_zero [Nontrivial K] : rank (0 : V →ₗ[K] V') = 0 := by variable [AddCommGroup V''] [Module K V''] theorem rank_comp_le_left (g : V →ₗ[K] V') (f : V' →ₗ[K] V'') : rank (f.comp g) ≤ rank f := by - refine rank_le_of_submodule _ _ ?_ + refine Submodule.rank_mono ?_ rw [LinearMap.range_comp] exact LinearMap.map_le_range @@ -82,7 +82,7 @@ variable [AddCommGroup V'] [Module K V'] theorem rank_add_le (f g : V →ₗ[K] V') : rank (f + g) ≤ rank f + rank g := calc rank (f + g) ≤ Module.rank K (LinearMap.range f ⊔ LinearMap.range g : Submodule K V') := by - refine rank_le_of_submodule _ _ ?_ + refine Submodule.rank_mono ?_ exact LinearMap.range_le_iff_comap.2 <| eq_top_iff'.2 fun x => show f x + g x ∈ (LinearMap.range f ⊔ LinearMap.range g : Submodule K V') from mem_sup.2 ⟨_, ⟨x, rfl⟩, _, ⟨x, rfl⟩, rfl⟩ diff --git a/Mathlib/LinearAlgebra/Dimension/Localization.lean b/Mathlib/LinearAlgebra/Dimension/Localization.lean index 215eca3c7a657..b6445fadfe529 100644 --- a/Mathlib/LinearAlgebra/Dimension/Localization.lean +++ b/Mathlib/LinearAlgebra/Dimension/Localization.lean @@ -15,9 +15,9 @@ import Mathlib.RingTheory.OreLocalization.OreSet - `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 + +open Cardinal Module nonZeroDivisors section CommRing diff --git a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean index 79cac4a7d7ba4..2e6cb6ba25096 100644 --- a/Mathlib/LinearAlgebra/Dimension/RankNullity.lean +++ b/Mathlib/LinearAlgebra/Dimension/RankNullity.lean @@ -136,7 +136,7 @@ theorem exists_linearIndependent_pair_of_one_lt_rank [StrongRankCondition R] [NoZeroSMulDivisors R M] (h : 1 < Module.rank R M) {x : M} (hx : x ≠ 0) : ∃ y, LinearIndependent R ![x, y] := by obtain ⟨y, hy⟩ := exists_linearIndependent_snoc_of_lt_rank (linearIndependent_unique ![x] hx) h - have : Fin.snoc ![x] y = ![x, y] := Iff.mp List.ofFn_inj rfl + have : Fin.snoc ![x] y = ![x, y] := by simp [Fin.snoc, ← List.ofFn_inj] rw [this] at hy exact ⟨y, hy⟩ @@ -171,7 +171,7 @@ theorem Submodule.rank_add_le_rank_add_rank (s t : Submodule R M) : section Finrank -open Submodule FiniteDimensional +open Submodule Module variable [StrongRankCondition R] diff --git a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean index aecd0ad209da8..26dc00965d15b 100644 --- a/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean +++ b/Mathlib/LinearAlgebra/Dimension/StrongRankCondition.lean @@ -376,14 +376,12 @@ theorem Ideal.rank_eq {R S : Type*} [CommRing R] [StrongRankCondition R] [Ring S ((LinearMap.ker_eq_bot (f := (Submodule.subtype I : I →ₗ[R] S))).mpr Subtype.coe_injective))) (c.card_le_card_of_linearIndependent this) -open FiniteDimensional +namespace Module theorem finrank_eq_nat_card_basis (h : Basis ι R M) : finrank R M = Nat.card ι := by rw [Nat.card, ← toNat_lift.{v}, h.mk_eq_rank, toNat_lift, finrank] -namespace FiniteDimensional - /-- If a vector space (or module) has a finite basis, then its dimension (or rank) is equal to the cardinality of the basis. -/ theorem finrank_eq_card_basis {ι : Type w} [Fintype ι] (h : Basis ι R M) : @@ -392,8 +390,8 @@ theorem finrank_eq_card_basis {ι : Type w} [Fintype ι] (h : Basis ι R M) : /-- If a free module is of finite rank, then the cardinality of any basis is equal to its `finrank`. -/ -theorem _root_.Module.mk_finrank_eq_card_basis [Module.Finite R M] - {ι : Type w} (h : Basis ι R M) : (finrank R M : Cardinal.{w}) = #ι := by +theorem mk_finrank_eq_card_basis [Module.Finite R M] {ι : Type w} (h : Basis ι R M) : + (finrank R M : Cardinal.{w}) = #ι := by cases @nonempty_fintype _ (Module.Finite.finite_basis h) rw [Cardinal.mk_fintype, finrank_eq_card_basis h] @@ -402,10 +400,6 @@ cardinality of the basis. This lemma uses a `Finset` instead of indexed types. - theorem finrank_eq_card_finset_basis {ι : Type w} {b : Finset ι} (h : Basis b R M) : finrank R M = Finset.card b := by rw [finrank_eq_card_basis h, Fintype.card_coe] -end FiniteDimensional - -open FiniteDimensional - variable (R) @[simp] @@ -415,15 +409,15 @@ theorem rank_self : Module.rank R R = 1 := by /-- A ring satisfying `StrongRankCondition` (such as a `DivisionRing`) is one-dimensional as a module over itself. -/ @[simp] -theorem FiniteDimensional.finrank_self : finrank R R = 1 := +theorem finrank_self : finrank R R = 1 := finrank_eq_of_rank_eq (by simp) /-- Given a basis of a ring over itself indexed by a type `ι`, then `ι` is `Unique`. -/ -noncomputable def Basis.unique {ι : Type*} (b : Basis ι R R) : Unique ι := by - have A : Cardinal.mk ι = ↑(FiniteDimensional.finrank R R) := +noncomputable def _root_.Basis.unique {ι : Type*} (b : Basis ι R R) : Unique ι := by + have A : Cardinal.mk ι = ↑(Module.finrank R R) := (Module.mk_finrank_eq_card_basis b).symm -- Porting note: replace `algebraMap.coe_one` with `Nat.cast_one` - simp only [Cardinal.eq_one_iff_unique, FiniteDimensional.finrank_self, Nat.cast_one] at A + simp only [Cardinal.eq_one_iff_unique, Module.finrank_self, Nat.cast_one] at A exact Nonempty.some ((unique_iff_subsingleton_and_nonempty _).2 A) variable (M) @@ -436,19 +430,23 @@ theorem rank_lt_aleph0 [Module.Finite R M] : Module.rank R M < ℵ₀ := by refine (ciSup_le' fun i => ?_).trans_lt (nat_lt_aleph0 S.card) exact linearIndependent_le_span_finset _ i.prop S hS -@[deprecated (since := "2024-01-01")] -protected alias FiniteDimensional.rank_lt_aleph0 := rank_lt_aleph0 +noncomputable instance {R M : Type*} [DivisionRing R] [AddCommGroup M] [Module R M] + {s t : Set M} [Module.Finite R (span R t)] + (hs : LinearIndependent R ((↑) : s → M)) (hst : s ⊆ t) : + Fintype (hs.extend hst) := by + refine Classical.choice (Cardinal.lt_aleph0_iff_fintype.1 ?_) + rw [← rank_span_set (hs.linearIndependent_extend hst), hs.span_extend_eq_span] + exact Module.rank_lt_aleph0 .. /-- If `M` is finite, `finrank M = rank M`. -/ @[simp] -theorem finrank_eq_rank [Module.Finite R M] : - ↑(FiniteDimensional.finrank R M) = Module.rank R M := by - rw [FiniteDimensional.finrank, cast_toNat_of_lt_aleph0 (rank_lt_aleph0 R M)] +theorem finrank_eq_rank [Module.Finite R M] : ↑(finrank R M) = Module.rank R M := by + rw [Module.finrank, cast_toNat_of_lt_aleph0 (rank_lt_aleph0 R M)] + +end Module -@[deprecated (since := "2024-01-01")] -protected alias FiniteDimensional.finrank_eq_rank := finrank_eq_rank +open Module -variable {R M} variable {M'} [AddCommGroup M'] [Module R M'] theorem LinearMap.finrank_le_finrank_of_injective [Module.Finite R M'] {f : M →ₗ[R] M'} diff --git a/Mathlib/LinearAlgebra/Dual.lean b/Mathlib/LinearAlgebra/Dual.lean index b4d2e69e8d184..5d556906e958a 100644 --- a/Mathlib/LinearAlgebra/Dual.lean +++ b/Mathlib/LinearAlgebra/Dual.lean @@ -91,6 +91,8 @@ The dual space of an $R$-module $M$ is the $R$-module of $R$-linear maps $M \to splitting of `V₁`. -/ +open Module Submodule + noncomputable section namespace Module @@ -181,7 +183,7 @@ def LinearMap.dualMap (f : M₁ →ₗ[R] M₂) : Dual R M₂ →ₗ[R] Dual R M -- Porting note: with reducible def need to specify some parameters to transpose explicitly Module.Dual.transpose (R := R) f -lemma LinearMap.dualMap_eq_lcomp (f : M₁ →ₗ[R] M₂) : f.dualMap = f.lcomp R := rfl +lemma LinearMap.dualMap_eq_lcomp (f : M₁ →ₗ[R] M₂) : f.dualMap = f.lcomp R R := rfl -- Porting note: with reducible def need to specify some parameters to transpose explicitly theorem LinearMap.dualMap_def (f : M₁ →ₗ[R] M₂) : f.dualMap = Module.Dual.transpose (R := R) f := @@ -384,7 +386,7 @@ theorem toDualEquiv_apply (m : M) : b.toDualEquiv m = b.toDual m := theorem linearEquiv_dual_iff_finiteDimensional [Field K] [AddCommGroup V] [Module K V] : Nonempty (V ≃ₗ[K] Dual K V) ↔ FiniteDimensional K V := by refine ⟨fun ⟨e⟩ ↦ ?_, fun h ↦ ⟨(Module.Free.chooseBasis K V).toDualEquiv⟩⟩ - rw [FiniteDimensional, ← Module.rank_lt_alpeh0_iff] + rw [FiniteDimensional, ← Module.rank_lt_aleph0_iff] by_contra! apply (lift_rank_lt_rank_dual this).ne have := e.lift_rank_eq @@ -449,12 +451,12 @@ theorem eval_range {ι : Type*} [Finite ι] (b : Basis ι R M) : section -variable [Finite R M] [Free R M] +variable [Module.Finite R M] [Free R M] instance dual_free : Free R (Dual R M) := Free.of_basis (Free.chooseBasis R M).dualBasis -instance dual_finite : Finite R (Dual R M) := +instance dual_finite : Module.Finite R (Dual R M) := Finite.of_basis (Free.chooseBasis R M).dualBasis end @@ -482,7 +484,7 @@ universe uK uV variable {K : Type uK} {V : Type uV} variable [CommRing K] [AddCommGroup V] [Module K V] [Module.Free K V] -open Module Module.Dual Submodule LinearMap Cardinal Basis FiniteDimensional +open Module Module.Dual Submodule LinearMap Cardinal Basis Module section @@ -540,7 +542,7 @@ theorem nontrivial_dual_iff : instance instNontrivialDual [Nontrivial V] : Nontrivial (Dual K V) := (nontrivial_dual_iff K).mpr inferInstance -theorem finite_dual_iff : Finite K (Dual K V) ↔ Finite K V := by +theorem finite_dual_iff : Module.Finite K (Dual K V) ↔ Module.Finite K V := by constructor <;> intro h · obtain ⟨⟨ι, b⟩⟩ := Module.Free.exists_basis (R := K) (M := V) nontriviality K @@ -578,7 +580,8 @@ class IsReflexive : Prop where lemma bijective_dual_eval [IsReflexive R M] : Bijective (Dual.eval R M) := IsReflexive.bijective_dual_eval' -instance IsReflexive.of_finite_of_free [Finite R M] [Free R M] : IsReflexive R M where +/-- See also `Module.instFiniteDimensionalOfIsReflexive` for the converse over a field. -/ +instance IsReflexive.of_finite_of_free [Module.Finite R M] [Free R M] : IsReflexive R M where bijective_dual_eval' := ⟨LinearMap.ker_eq_bot.mp (Free.chooseBasis R M).eval_ker, LinearMap.range_eq_top.mp (Free.chooseBasis R M).eval_range⟩ @@ -648,6 +651,22 @@ instance _root_.MulOpposite.instModuleIsReflexive : IsReflexive R (MulOpposite M instance _root_.ULift.instModuleIsReflexive.{w} : IsReflexive R (ULift.{w} M) := equiv ULift.moduleEquiv.symm +instance instFiniteDimensionalOfIsReflexive (K V : Type*) + [Field K] [AddCommGroup V] [Module K V] [IsReflexive K V] : + FiniteDimensional K V := by + rw [FiniteDimensional, ← rank_lt_aleph0_iff] + by_contra! contra + suffices lift (Module.rank K V) < Module.rank K (Dual K (Dual K V)) by + have heq := lift_rank_eq_of_equiv_equiv (R := K) (R' := K) (M := V) (M' := Dual K (Dual K V)) + (ZeroHom.id K) (evalEquiv K V) bijective_id (fun r v ↦ (evalEquiv K V).map_smul _ _) + rw [← lift_umax, heq, lift_id'] at this + exact lt_irrefl _ this + have h₁ : lift (Module.rank K V) < Module.rank K (Dual K V) := lift_rank_lt_rank_dual contra + have h₂ : Module.rank K (Dual K V) < Module.rank K (Dual K (Dual K V)) := by + convert lift_rank_lt_rank_dual <| le_trans (by simpa) h₁.le + rw [lift_id'] + exact lt_trans h₁ h₂ + end IsReflexive end Module @@ -671,6 +690,47 @@ theorem exists_dual_map_eq_bot_of_lt_top (hp : p < ⊤) (hp' : Free R (M ⧸ p)) obtain ⟨f, hf, hf'⟩ := p.exists_dual_map_eq_bot_of_nmem hx hp' exact ⟨f, by aesop, hf'⟩ +variable {ι 𝕜 E : Type*} [Field 𝕜] [AddCommGroup E] [Module 𝕜 E] + +open LinearMap Set FiniteDimensional + +theorem _root_.FiniteDimensional.mem_span_of_iInf_ker_le_ker [FiniteDimensional 𝕜 E] + {L : ι → E →ₗ[𝕜] 𝕜} {K : E →ₗ[𝕜] 𝕜} + (h : ⨅ i, LinearMap.ker (L i) ≤ ker K) : K ∈ span 𝕜 (range L) := by + by_contra hK + rcases exists_dual_map_eq_bot_of_nmem hK inferInstance with ⟨φ, φne, hφ⟩ + let φs := (Module.evalEquiv 𝕜 E).symm φ + have : K φs = 0 := by + refine h <| (Submodule.mem_iInf _).2 fun i ↦ (mem_bot 𝕜).1 ?_ + rw [← hφ, Submodule.mem_map] + exact ⟨L i, Submodule.subset_span ⟨i, rfl⟩, (apply_evalEquiv_symm_apply 𝕜 E _ φ).symm⟩ + simp only [apply_evalEquiv_symm_apply, φs, φne] at this + +/-- Given some linear forms $L_1, ..., L_n, K$ over a vector space $E$, if +$\bigcap_{i=1}^n \mathrm{ker}(L_i) \subseteq \mathrm{ker}(K)$, then $K$ is in the space generated +by $L_1, ..., L_n$. -/ +theorem _root_.mem_span_of_iInf_ker_le_ker [Finite ι] {L : ι → E →ₗ[𝕜] 𝕜} {K : E →ₗ[𝕜] 𝕜} + (h : ⨅ i, ker (L i) ≤ ker K) : K ∈ span 𝕜 (range L) := by + have _ := Fintype.ofFinite ι + let φ : E →ₗ[𝕜] ι → 𝕜 := LinearMap.pi L + let p := ⨅ i, ker (L i) + have p_eq : p = ker φ := (ker_pi L).symm + let ψ : (E ⧸ p) →ₗ[𝕜] ι → 𝕜 := p.liftQ φ p_eq.le + have _ : FiniteDimensional 𝕜 (E ⧸ p) := of_injective ψ (ker_eq_bot.1 (ker_liftQ_eq_bot' p φ p_eq)) + let L' i : (E ⧸ p) →ₗ[𝕜] 𝕜 := p.liftQ (L i) (iInf_le _ i) + let K' : (E ⧸ p) →ₗ[𝕜] 𝕜 := p.liftQ K h + have : ⨅ i, ker (L' i) ≤ ker K' := by + simp_rw [← ker_pi, L', pi_liftQ_eq_liftQ_pi, ker_liftQ_eq_bot' p φ p_eq] + exact bot_le + obtain ⟨c, hK'⟩ := + (mem_span_range_iff_exists_fun 𝕜).1 (FiniteDimensional.mem_span_of_iInf_ker_le_ker this) + refine (mem_span_range_iff_exists_fun 𝕜).2 ⟨c, ?_⟩ + conv_lhs => enter [2]; intro i; rw [← p.liftQ_mkQ (L i) (iInf_le _ i)] + rw [← p.liftQ_mkQ K h] + ext x + convert LinearMap.congr_fun hK' (p.mkQ x) + simp only [coeFn_sum, Finset.sum_apply, smul_apply, coe_comp, Function.comp_apply, smul_eq_mul] + end Submodule section DualBases @@ -1057,7 +1117,7 @@ theorem dualEquivDual_apply (φ : Module.Dual K W) : section -open FiniteDimensional +open FiniteDimensional Module instance instModuleDualFiniteDimensional [FiniteDimensional K V] : FiniteDimensional K (Module.Dual K V) := by @@ -1096,7 +1156,7 @@ noncomputable def quotEquivAnnihilator (W : Subspace K V) : (V ⧸ W) ≃ₗ[K] -- refine' LinearEquiv.quot_equiv_of_equiv _ (Basis.ofVectorSpace K V).toDualEquiv -- exact (Basis.ofVectorSpace K W).toDualEquiv.trans W.dual_equiv_dual -open FiniteDimensional +open Module @[simp] theorem finrank_dualCoannihilator_eq {Φ : Subspace K (Module.Dual K V)} : @@ -1164,12 +1224,12 @@ def dualCopairing (W : Submodule R M) : W.dualAnnihilator →ₗ[R] M ⧸ W → exact (mem_dualAnnihilator φ).mp hφ w hw) -- Porting note: helper instance -instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M R := - { coe := fun φ => φ.val, - coe_injective' := fun φ ψ h => by - ext - simp only [Function.funext_iff] at h - exact h _ } +instance (W : Submodule R M) : FunLike (W.dualAnnihilator) M R where + coe φ := φ.val + coe_injective' φ ψ h := by + ext + simp only [Function.funext_iff] at h + exact h _ @[simp] theorem dualCopairing_apply {W : Submodule R M} (φ : W.dualAnnihilator) (x : M) : @@ -1231,7 +1291,7 @@ theorem dualQuotEquivDualAnnihilator_symm_apply_mk (W : Submodule R M) (φ : W.d rfl theorem finite_dualAnnihilator_iff {W : Submodule R M} [Free R (M ⧸ W)] : - Finite R W.dualAnnihilator ↔ Finite R (M ⧸ W) := + Module.Finite R W.dualAnnihilator ↔ Module.Finite R (M ⧸ W) := (Finite.equiv_iff W.dualQuotEquivDualAnnihilator.symm).trans (finite_dual_iff R) open LinearMap in @@ -1324,7 +1384,6 @@ lemma range_eq_top_of_ne_zero : rw [eq_top_iff] exact fun x _ ↦ ⟨x • (f v)⁻¹ • v, by simp [inv_mul_cancel₀ hv]⟩ -open FiniteDimensional variable [FiniteDimensional K V₁] lemma finrank_ker_add_one_of_ne_zero : @@ -1479,7 +1538,7 @@ end Subspace section FiniteDimensional -open FiniteDimensional LinearMap +open Module LinearMap namespace LinearMap @@ -1610,7 +1669,7 @@ theorem dualAnnihilator_dualAnnihilator_eq_map (W : Subspace K V) [FiniteDimensi haveI := e1.finiteDimensional let e2 := (Free.chooseBasis K _).toDualEquiv ≪≫ₗ W.dualAnnihilator.dualQuotEquivDualAnnihilator haveI := LinearEquiv.finiteDimensional (V₂ := W.dualAnnihilator.dualAnnihilator) e2 - rw [FiniteDimensional.eq_of_le_of_finrank_eq (map_le_dualAnnihilator_dualAnnihilator W)] + rw [eq_of_le_of_finrank_eq (map_le_dualAnnihilator_dualAnnihilator W)] rw [← (equivMapOfInjective _ (eval_apply_injective K (V := V)) W).finrank_eq, e1.finrank_eq] exact e2.finrank_eq diff --git a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean index e5c7fcb4b592f..e2e7aa9fcb4c9 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Basic.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Basic.lean @@ -53,232 +53,530 @@ namespace Module namespace End -open FiniteDimensional Set +open Module Set variable {K R : Type v} {V M : Type w} [CommRing R] [AddCommGroup M] [Module R M] [Field K] [AddCommGroup V] [Module K V] +/-- The submodule `unifEigenspace f μ k` for a linear map `f`, a scalar `μ`, +and a number `k : ℕ∞` is the kernel of `(f - μ • id) ^ k` if `k` is a natural number, +or the union of all these kernels if `k = ∞`. -/ +def unifEigenspace (f : End R M) (μ : R) : ℕ∞ →o Submodule R M where + toFun k := ⨆ l : ℕ, ⨆ _ : l ≤ k, LinearMap.ker ((f - μ • 1) ^ l) + monotone' _ _ hkl := biSup_mono fun _ hi ↦ hi.trans hkl + +lemma mem_unifEigenspace {f : End R M} {μ : R} {k : ℕ∞} {x : M} : + x ∈ f.unifEigenspace μ k ↔ ∃ l : ℕ, l ≤ k ∧ x ∈ LinearMap.ker ((f - μ • 1) ^ l) := by + have : Nonempty {l : ℕ // l ≤ k} := ⟨⟨0, zero_le _⟩⟩ + have : Directed (ι := { i : ℕ // i ≤ k }) (· ≤ ·) fun i ↦ LinearMap.ker ((f - μ • 1) ^ (i : ℕ)) := + Monotone.directed_le fun m n h ↦ by simpa using (f - μ • 1).iterateKer.monotone h + simp_rw [unifEigenspace, OrderHom.coe_mk, LinearMap.mem_ker, iSup_subtype', + Submodule.mem_iSup_of_directed _ this, LinearMap.mem_ker, Subtype.exists, exists_prop] + +lemma unifEigenspace_directed {f : End R M} {μ : R} {k : ℕ∞} : + Directed (· ≤ ·) (fun l : {l : ℕ // l ≤ k} ↦ f.unifEigenspace μ l) := by + have aux : Monotone ((↑) : {l : ℕ // l ≤ k} → ℕ∞) := fun x y h ↦ by simpa using h + exact ((unifEigenspace f μ).monotone.comp aux).directed_le + +lemma mem_unifEigenspace_nat {f : End R M} {μ : R} {k : ℕ} {x : M} : + x ∈ f.unifEigenspace μ k ↔ x ∈ LinearMap.ker ((f - μ • 1) ^ k) := by + rw [mem_unifEigenspace] + constructor + · rintro ⟨l, hl, hx⟩ + simp only [Nat.cast_le] at hl + exact (f - μ • 1).iterateKer.monotone hl hx + · intro hx + exact ⟨k, le_rfl, hx⟩ + +lemma mem_unifEigenspace_top {f : End R M} {μ : R} {x : M} : + x ∈ f.unifEigenspace μ ⊤ ↔ ∃ k : ℕ, x ∈ LinearMap.ker ((f - μ • 1) ^ k) := by + simp [mem_unifEigenspace] + +lemma unifEigenspace_nat {f : End R M} {μ : R} {k : ℕ} : + f.unifEigenspace μ k = LinearMap.ker ((f - μ • 1) ^ k) := by + ext; simp [mem_unifEigenspace_nat] + +lemma unifEigenspace_eq_iSup_unifEigenspace_nat (f : End R M) (μ : R) (k : ℕ∞) : + f.unifEigenspace μ k = ⨆ l : {l : ℕ // l ≤ k}, f.unifEigenspace μ l := by + simp_rw [unifEigenspace_nat, unifEigenspace, OrderHom.coe_mk, iSup_subtype] + +lemma unifEigenspace_top (f : End R M) (μ : R) : + f.unifEigenspace μ ⊤ = ⨆ k : ℕ, f.unifEigenspace μ k := by + rw [unifEigenspace_eq_iSup_unifEigenspace_nat, iSup_subtype] + simp only [le_top, iSup_pos, OrderHom.coe_mk] + +lemma unifEigenspace_one {f : End R M} {μ : R} : + f.unifEigenspace μ 1 = LinearMap.ker (f - μ • 1) := by + rw [← Nat.cast_one, unifEigenspace_nat, pow_one] + +@[simp] +lemma mem_unifEigenspace_one {f : End R M} {μ : R} {x : M} : + x ∈ f.unifEigenspace μ 1 ↔ f x = μ • x := by + rw [unifEigenspace_one, LinearMap.mem_ker, LinearMap.sub_apply, + sub_eq_zero, LinearMap.smul_apply, LinearMap.one_apply] + +-- `simp` can prove this using `unifEigenspace_zero` +lemma mem_unifEigenspace_zero {f : End R M} {μ : R} {x : M} : + x ∈ f.unifEigenspace μ 0 ↔ x = 0 := by + rw [← Nat.cast_zero, mem_unifEigenspace_nat, pow_zero, LinearMap.mem_ker, LinearMap.one_apply] + +@[simp] +lemma unifEigenspace_zero {f : End R M} {μ : R} : + f.unifEigenspace μ 0 = ⊥ := by + ext; apply mem_unifEigenspace_zero + +@[simp] +lemma unifEigenspace_zero_nat (f : End R M) (k : ℕ) : + f.unifEigenspace 0 k = LinearMap.ker (f ^ k) := by + ext; simp [mem_unifEigenspace_nat] + +/-- Let `M` be an `R`-module, and `f` an `R`-linear endomorphism of `M`, +and let `μ : R` and `k : ℕ∞` be given. +Then `x : M` satisfies `HasUnifEigenvector f μ k x` if +`x ∈ f.unifEigenspace μ k` and `x ≠ 0`. + +For `k = 1`, this means that `x` is an eigenvector of `f` with eigenvalue `μ`. -/ +def HasUnifEigenvector (f : End R M) (μ : R) (k : ℕ∞) (x : M) : Prop := + x ∈ f.unifEigenspace μ k ∧ x ≠ 0 + +/-- Let `M` be an `R`-module, and `f` an `R`-linear endomorphism of `M`. +Then `μ : R` and `k : ℕ∞` satisfy `HasUnifEigenvalue f μ k` if +`f.unifEigenspace μ k ≠ ⊥`. + +For `k = 1`, this means that `μ` is an eigenvalue of `f`. -/ +def HasUnifEigenvalue (f : End R M) (μ : R) (k : ℕ∞) : Prop := + f.unifEigenspace μ k ≠ ⊥ + +/-- Let `M` be an `R`-module, and `f` an `R`-linear endomorphism of `M`. +For `k : ℕ∞`, we define `UnifEigenvalues f k` to be the type of all +`μ : R` that satisfy `f.HasUnifEigenvalue μ k`. + +For `k = 1` this is the type of all eigenvalues of `f`. -/ +def UnifEigenvalues (f : End R M) (k : ℕ∞) : Type _ := + { μ : R // f.HasUnifEigenvalue μ k } + +/-- The underlying value of a bundled eigenvalue. -/ +@[coe] +def UnifEigenvalues.val (f : Module.End R M) (k : ℕ∞) : UnifEigenvalues f k → R := Subtype.val + +instance UnifEigenvalues.instCoeOut {f : Module.End R M} (k : ℕ∞) : + CoeOut (UnifEigenvalues f k) R where + coe := UnifEigenvalues.val f k + +instance UnivEigenvalues.instDecidableEq [DecidableEq R] (f : Module.End R M) (k : ℕ∞) : + DecidableEq (UnifEigenvalues f k) := + inferInstanceAs (DecidableEq (Subtype (fun x : R ↦ f.HasUnifEigenvalue x k))) + +lemma HasUnifEigenvector.hasUnifEigenvalue {f : End R M} {μ : R} {k : ℕ∞} {x : M} + (h : f.HasUnifEigenvector μ k x) : f.HasUnifEigenvalue μ k := by + rw [HasUnifEigenvalue, Submodule.ne_bot_iff] + use x; exact h + +lemma HasUnifEigenvector.apply_eq_smul {f : End R M} {μ : R} {x : M} + (hx : f.HasUnifEigenvector μ 1 x) : f x = μ • x := + mem_unifEigenspace_one.mp hx.1 + +lemma HasUnifEigenvector.pow_apply {f : End R M} {μ : R} {v : M} (hv : f.HasUnifEigenvector μ 1 v) + (n : ℕ) : (f ^ n) v = μ ^ n • v := by + induction n <;> simp [*, pow_succ f, hv.apply_eq_smul, smul_smul, pow_succ' μ] + +theorem HasUnifEigenvalue.exists_hasUnifEigenvector + {f : End R M} {μ : R} {k : ℕ∞} (hμ : f.HasUnifEigenvalue μ k) : + ∃ v, f.HasUnifEigenvector μ k v := + Submodule.exists_mem_ne_zero_of_ne_bot hμ + +lemma HasUnifEigenvalue.pow {f : End R M} {μ : R} (h : f.HasUnifEigenvalue μ 1) (n : ℕ) : + (f ^ n).HasUnifEigenvalue (μ ^ n) 1 := by + rw [HasUnifEigenvalue, Submodule.ne_bot_iff] + obtain ⟨m : M, hm⟩ := h.exists_hasUnifEigenvector + exact ⟨m, by simpa [mem_unifEigenspace_one] using hm.pow_apply n, hm.2⟩ + +/-- A nilpotent endomorphism has nilpotent eigenvalues. + +See also `LinearMap.isNilpotent_trace_of_isNilpotent`. -/ +lemma HasUnifEigenvalue.isNilpotent_of_isNilpotent [NoZeroSMulDivisors R M] {f : End R M} + (hfn : IsNilpotent f) {μ : R} (hf : f.HasUnifEigenvalue μ 1) : + IsNilpotent μ := by + obtain ⟨m : M, hm⟩ := hf.exists_hasUnifEigenvector + obtain ⟨n : ℕ, hn : f ^ n = 0⟩ := hfn + exact ⟨n, by simpa [hn, hm.2, eq_comm (a := (0 : M))] using hm.pow_apply n⟩ + +lemma HasUnifEigenvalue.mem_spectrum {f : End R M} {μ : R} (hμ : HasUnifEigenvalue f μ 1) : + μ ∈ spectrum R f := by + refine spectrum.mem_iff.mpr fun h_unit ↦ ?_ + set f' := LinearMap.GeneralLinearGroup.toLinearEquiv h_unit.unit + rcases hμ.exists_hasUnifEigenvector with ⟨v, hv⟩ + refine hv.2 ((LinearMap.ker_eq_bot'.mp f'.ker) v (?_ : μ • v - f v = 0)) + rw [hv.apply_eq_smul, sub_self] + +lemma hasUnifEigenvalue_iff_mem_spectrum [FiniteDimensional K V] {f : End K V} {μ : K} : + f.HasUnifEigenvalue μ 1 ↔ μ ∈ spectrum K f := by + rw [spectrum.mem_iff, IsUnit.sub_iff, LinearMap.isUnit_iff_ker_eq_bot, + HasUnifEigenvalue, unifEigenspace_one, ne_eq, not_iff_not] + simp [Submodule.ext_iff, LinearMap.mem_ker] + +alias ⟨_, HasUnifEigenvalue.of_mem_spectrum⟩ := hasUnifEigenvalue_iff_mem_spectrum + +lemma unifEigenspace_div (f : End K V) (a b : K) (hb : b ≠ 0) : + unifEigenspace f (a / b) 1 = LinearMap.ker (b • f - a • 1) := + calc + unifEigenspace f (a / b) 1 = unifEigenspace f (b⁻¹ * a) 1 := by rw [div_eq_mul_inv, mul_comm] + _ = LinearMap.ker (f - (b⁻¹ * a) • 1) := by rw [unifEigenspace_one] + _ = LinearMap.ker (f - b⁻¹ • a • 1) := by rw [smul_smul] + _ = LinearMap.ker (b • (f - b⁻¹ • a • 1)) := by rw [LinearMap.ker_smul _ b hb] + _ = LinearMap.ker (b • f - a • 1) := by rw [smul_sub, smul_inv_smul₀ hb] + +/-- The generalized eigenrange for a linear map `f`, a scalar `μ`, and an exponent `k ∈ ℕ∞` +is the range of `(f - μ • id) ^ k` if `k` is a natural number, +or the infimum of these ranges if `k = ∞`. -/ +def unifEigenrange (f : End R M) (μ : R) (k : ℕ∞) : Submodule R M := + ⨅ l : ℕ, ⨅ (_ : l ≤ k), LinearMap.range ((f - μ • 1) ^ l) + +lemma unifEigenrange_nat {f : End R M} {μ : R} {k : ℕ} : + f.unifEigenrange μ k = LinearMap.range ((f - μ • 1) ^ k) := by + ext x + simp only [unifEigenrange, Nat.cast_le, Submodule.mem_iInf, LinearMap.mem_range] + constructor + · intro h + exact h _ le_rfl + · rintro ⟨x, rfl⟩ i hi + have : k = i + (k - i) := by omega + rw [this, pow_add] + exact ⟨_, rfl⟩ + +/-- The exponent of a generalized eigenvalue is never 0. -/ +lemma HasUnifEigenvalue.exp_ne_zero {f : End R M} {μ : R} {k : ℕ} + (h : f.HasUnifEigenvalue μ k) : k ≠ 0 := by + rintro rfl + simp [HasUnifEigenvalue, Nat.cast_zero, unifEigenspace_zero] at h + +/-- If there exists a natural number `k` such that the kernel of `(f - μ • id) ^ k` is the +maximal generalized eigenspace, then this value is the least such `k`. If not, this value is not +meaningful. -/ +noncomputable def maxUnifEigenspaceIndex (f : End R M) (μ : R) := + monotonicSequenceLimitIndex <| (f.unifEigenspace μ).comp <| WithTop.coeOrderHom.toOrderHom + +/-- For an endomorphism of a Noetherian module, the maximal eigenspace is always of the form kernel +`(f - μ • id) ^ k` for some `k`. -/ +lemma unifEigenspace_top_eq_maxUnifEigenspaceIndex [h : IsNoetherian R M] (f : End R M) (μ : R) : + unifEigenspace f μ ⊤ = f.unifEigenspace μ (maxUnifEigenspaceIndex f μ) := by + rw [isNoetherian_iff] at h + have := WellFounded.iSup_eq_monotonicSequenceLimit h <| + (f.unifEigenspace μ).comp <| WithTop.coeOrderHom.toOrderHom + convert this using 1 + simp only [unifEigenspace, OrderHom.coe_mk, le_top, iSup_pos, OrderHom.comp_coe, + Function.comp_def] + rw [iSup_prod', iSup_subtype', ← sSup_range, ← sSup_range] + congr + aesop + +lemma unifEigenspace_le_unifEigenspace_maxUnifEigenspaceIndex [IsNoetherian R M] (f : End R M) + (μ : R) (k : ℕ∞) : + f.unifEigenspace μ k ≤ f.unifEigenspace μ (maxUnifEigenspaceIndex f μ) := by + rw [← unifEigenspace_top_eq_maxUnifEigenspaceIndex] + exact (f.unifEigenspace μ).monotone le_top + +/-- Generalized eigenspaces for exponents at least `finrank K V` are equal to each other. -/ +theorem unifEigenspace_eq_unifEigenspace_maxUnifEigenspaceIndex_of_le [IsNoetherian R M] + (f : End R M) (μ : R) {k : ℕ} (hk : maxUnifEigenspaceIndex f μ ≤ k) : + f.unifEigenspace μ k = f.unifEigenspace μ (maxUnifEigenspaceIndex f μ) := + le_antisymm + (unifEigenspace_le_unifEigenspace_maxUnifEigenspaceIndex _ _ _) + ((f.unifEigenspace μ).monotone <| by simpa using hk) + +/-- A generalized eigenvalue for some exponent `k` is also + a generalized eigenvalue for exponents larger than `k`. -/ +lemma HasUnifEigenvalue.le {f : End R M} {μ : R} {k m : ℕ∞} + (hm : k ≤ m) (hk : f.HasUnifEigenvalue μ k) : + f.HasUnifEigenvalue μ m := by + unfold HasUnifEigenvalue at * + contrapose! hk + rw [← le_bot_iff, ← hk] + exact (f.unifEigenspace _).monotone hm + +/-- A generalized eigenvalue for some exponent `k` is also + a generalized eigenvalue for positive exponents. -/ +lemma HasUnifEigenvalue.lt {f : End R M} {μ : R} {k m : ℕ∞} + (hm : 0 < m) (hk : f.HasUnifEigenvalue μ k) : + f.HasUnifEigenvalue μ m := by + apply HasUnifEigenvalue.le (k := 1) (Order.one_le_iff_pos.mpr hm) + intro contra; apply hk + rw [unifEigenspace_one, LinearMap.ker_eq_bot] at contra + rw [eq_bot_iff] + intro x hx + rw [mem_unifEigenspace] at hx + rcases hx with ⟨l, -, hx⟩ + rwa [LinearMap.ker_eq_bot.mpr] at hx + rw [LinearMap.coe_pow (f - μ • 1) l] + exact Function.Injective.iterate contra l + +/-- Generalized eigenvalues are actually just eigenvalues. -/ +@[simp] +lemma hasUnifEigenvalue_iff_hasUnifEigenvalue_one {f : End R M} {μ : R} {k : ℕ∞} (hk : 0 < k) : + f.HasUnifEigenvalue μ k ↔ f.HasUnifEigenvalue μ 1 := + ⟨HasUnifEigenvalue.lt zero_lt_one, HasUnifEigenvalue.lt hk⟩ + +lemma maxUnifEigenspaceIndex_le_finrank [FiniteDimensional K V] (f : End K V) (μ : K) : + maxUnifEigenspaceIndex f μ ≤ finrank K V := by + apply Nat.sInf_le + intro n hn + apply le_antisymm + · exact (f.unifEigenspace μ).monotone <| WithTop.coeOrderHom.monotone hn + · show (f.unifEigenspace μ) n ≤ (f.unifEigenspace μ) (finrank K V) + rw [unifEigenspace_nat, unifEigenspace_nat] + apply ker_pow_le_ker_pow_finrank + +/-- Every generalized eigenvector is a generalized eigenvector for exponent `finrank K V`. + (Lemma 8.11 of [axler2015]) -/ +lemma unifEigenspace_le_unifEigenspace_finrank [FiniteDimensional K V] (f : End K V) + (μ : K) (k : ℕ∞) : f.unifEigenspace μ k ≤ f.unifEigenspace μ (finrank K V) := by + calc f.unifEigenspace μ k + ≤ f.unifEigenspace μ ⊤ := (f.unifEigenspace _).monotone le_top + _ ≤ f.unifEigenspace μ (finrank K V) := by + rw [unifEigenspace_top_eq_maxUnifEigenspaceIndex] + exact (f.unifEigenspace _).monotone <| by simpa using maxUnifEigenspaceIndex_le_finrank f μ + +/-- Generalized eigenspaces for exponents at least `finrank K V` are equal to each other. -/ +theorem unifEigenspace_eq_unifEigenspace_finrank_of_le [FiniteDimensional K V] + (f : End K V) (μ : K) {k : ℕ} (hk : finrank K V ≤ k) : + f.unifEigenspace μ k = f.unifEigenspace μ (finrank K V) := + le_antisymm + (unifEigenspace_le_unifEigenspace_finrank _ _ _) + ((f.unifEigenspace μ).monotone <| by simpa using hk) + +lemma mapsTo_unifEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) (k : ℕ∞) : + MapsTo g (f.unifEigenspace μ k) (f.unifEigenspace μ k) := by + intro x hx + simp only [SetLike.mem_coe, mem_unifEigenspace, LinearMap.mem_ker] at hx ⊢ + rcases hx with ⟨l, hl, hx⟩ + replace h : Commute ((f - μ • (1 : End R M)) ^ l) g := + (h.sub_left <| Algebra.commute_algebraMap_left μ g).pow_left l + use l, hl + rw [← LinearMap.comp_apply, ← LinearMap.mul_eq_comp, h.eq, LinearMap.mul_eq_comp, + LinearMap.comp_apply, hx, map_zero] + +/-- The restriction of `f - μ • 1` to the `k`-fold generalized `μ`-eigenspace is nilpotent. -/ +lemma isNilpotent_restrict_unifEigenspace_nat (f : End R M) (μ : R) (k : ℕ) + (h : MapsTo (f - μ • (1 : End R M)) + (f.unifEigenspace μ k) (f.unifEigenspace μ k) := + mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ) μ k) : + IsNilpotent ((f - μ • 1).restrict h) := by + use k + ext ⟨x, hx⟩ + rw [mem_unifEigenspace_nat] at hx + rw [LinearMap.zero_apply, ZeroMemClass.coe_zero, ZeroMemClass.coe_eq_zero, + LinearMap.pow_restrict, LinearMap.restrict_apply] + ext + simpa + +/-- The restriction of `f - μ • 1` to the generalized `μ`-eigenspace is nilpotent. -/ +lemma isNilpotent_restrict_unifEigenspace_top [IsNoetherian R M] (f : End R M) (μ : R) + (h : MapsTo (f - μ • (1 : End R M)) + (f.unifEigenspace μ ⊤) (f.unifEigenspace μ ⊤) := + mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ) μ _) : + IsNilpotent ((f - μ • 1).restrict h) := by + apply isNilpotent_restrict_of_le + swap; apply isNilpotent_restrict_unifEigenspace_nat f μ (maxUnifEigenspaceIndex f μ) + rw [unifEigenspace_top_eq_maxUnifEigenspaceIndex] + /-- The submodule `eigenspace f μ` for a linear map `f` and a scalar `μ` consists of all vectors `x` such that `f x = μ • x`. (Def 5.36 of [axler2015])-/ -def eigenspace (f : End R M) (μ : R) : Submodule R M := - LinearMap.ker (f - algebraMap R (End R M) μ) +abbrev eigenspace (f : End R M) (μ : R) : Submodule R M := + f.unifEigenspace μ 1 -lemma eigenspace_def (f : End R M) (μ : R) : - f.eigenspace μ = LinearMap.ker (f - algebraMap R (End R M) μ) := rfl +lemma eigenspace_def {f : End R M} {μ : R} : + f.eigenspace μ = LinearMap.ker (f - μ • 1) := by + rw [eigenspace, unifEigenspace_one] @[simp] -theorem eigenspace_zero (f : End R M) : f.eigenspace 0 = LinearMap.ker f := by simp [eigenspace] +theorem eigenspace_zero (f : End R M) : f.eigenspace 0 = LinearMap.ker f := by + simp only [eigenspace, ← Nat.cast_one (R := ℕ∞), unifEigenspace_zero_nat, pow_one] /-- A nonzero element of an eigenspace is an eigenvector. (Def 5.7 of [axler2015]) -/ -def HasEigenvector (f : End R M) (μ : R) (x : M) : Prop := - x ∈ eigenspace f μ ∧ x ≠ 0 +abbrev HasEigenvector (f : End R M) (μ : R) (x : M) : Prop := + HasUnifEigenvector f μ 1 x lemma hasEigenvector_iff {f : End R M} {μ : R} {x : M} : - f.HasEigenvector μ x ↔ x ∈ eigenspace f μ ∧ x ≠ 0 := Iff.rfl + f.HasEigenvector μ x ↔ x ∈ f.eigenspace μ ∧ x ≠ 0 := Iff.rfl /-- A scalar `μ` is an eigenvalue for a linear map `f` if there are nonzero vectors `x` such that `f x = μ • x`. (Def 5.5 of [axler2015]) -/ -def HasEigenvalue (f : End R M) (a : R) : Prop := - eigenspace f a ≠ ⊥ +abbrev HasEigenvalue (f : End R M) (a : R) : Prop := + HasUnifEigenvalue f a 1 -lemma hasEigenvalue_iff (f : End R M) (μ : R) : f.HasEigenvalue μ ↔ eigenspace f μ ≠ ⊥ := Iff.rfl +lemma hasEigenvalue_iff {f : End R M} {μ : R} : + f.HasEigenvalue μ ↔ f.eigenspace μ ≠ ⊥ := Iff.rfl /-- The eigenvalues of the endomorphism `f`, as a subtype of `R`. -/ -def Eigenvalues (f : End R M) : Type _ := - { μ : R // f.HasEigenvalue μ } +abbrev Eigenvalues (f : End R M) : Type _ := + UnifEigenvalues f 1 @[coe] -def Eigenvalues.val (f : Module.End R M) : Eigenvalues f → R := Subtype.val - -instance Eigenvalues.instCoeOut {f : Module.End R M} : CoeOut (Eigenvalues f) R where - coe := Eigenvalues.val f - -instance Eigenvalues.instDecidableEq [DecidableEq R] (f : Module.End R M) : - DecidableEq (Eigenvalues f) := - inferInstanceAs (DecidableEq (Subtype (fun x : R => HasEigenvalue f x))) +abbrev Eigenvalues.val (f : Module.End R M) : Eigenvalues f → R := UnifEigenvalues.val f 1 theorem hasEigenvalue_of_hasEigenvector {f : End R M} {μ : R} {x : M} (h : HasEigenvector f μ x) : - HasEigenvalue f μ := by - rw [HasEigenvalue, Submodule.ne_bot_iff] - use x; exact h + HasEigenvalue f μ := + h.hasUnifEigenvalue -theorem mem_eigenspace_iff {f : End R M} {μ : R} {x : M} : x ∈ eigenspace f μ ↔ f x = μ • x := by - rw [eigenspace, LinearMap.mem_ker, LinearMap.sub_apply, algebraMap_end_apply, sub_eq_zero] +theorem mem_eigenspace_iff {f : End R M} {μ : R} {x : M} : x ∈ eigenspace f μ ↔ f x = μ • x := + mem_unifEigenspace_one +nonrec theorem HasEigenvector.apply_eq_smul {f : End R M} {μ : R} {x : M} (hx : f.HasEigenvector μ x) : f x = μ • x := - mem_eigenspace_iff.mp hx.1 + hx.apply_eq_smul +nonrec 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' μ] + (f ^ n) v = μ ^ n • v := + hv.pow_apply n 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μ +nonrec lemma HasEigenvalue.pow {f : End R M} {μ : R} (h : f.HasEigenvalue μ) (n : ℕ) : - (f ^ n).HasEigenvalue (μ ^ n) := by - rw [HasEigenvalue, Submodule.ne_bot_iff] - obtain ⟨m : M, hm⟩ := h.exists_hasEigenvector - exact ⟨m, by simpa [mem_eigenspace_iff] using hm.pow_apply n, hm.2⟩ + (f ^ n).HasEigenvalue (μ ^ n) := + h.pow n /-- A nilpotent endomorphism has nilpotent eigenvalues. See also `LinearMap.isNilpotent_trace_of_isNilpotent`. -/ +nonrec lemma HasEigenvalue.isNilpotent_of_isNilpotent [NoZeroSMulDivisors R M] {f : End R M} (hfn : IsNilpotent f) {μ : R} (hf : f.HasEigenvalue μ) : - IsNilpotent μ := by - obtain ⟨m : M, hm⟩ := hf.exists_hasEigenvector - obtain ⟨n : ℕ, hn : f ^ n = 0⟩ := hfn - exact ⟨n, by simpa [hn, hm.2, eq_comm (a := (0 : M))] using hm.pow_apply n⟩ + IsNilpotent μ := + hf.isNilpotent_of_isNilpotent hfn +nonrec theorem HasEigenvalue.mem_spectrum {f : End R M} {μ : R} (hμ : HasEigenvalue f μ) : - μ ∈ spectrum R f := by - refine spectrum.mem_iff.mpr fun h_unit => ?_ - set f' := LinearMap.GeneralLinearGroup.toLinearEquiv h_unit.unit - rcases hμ.exists_hasEigenvector with ⟨v, hv⟩ - refine hv.2 ((LinearMap.ker_eq_bot'.mp f'.ker) v (?_ : μ • v - f v = 0)) - rw [hv.apply_eq_smul, sub_self] + μ ∈ spectrum R f := + hμ.mem_spectrum theorem hasEigenvalue_iff_mem_spectrum [FiniteDimensional K V] {f : End K V} {μ : K} : - f.HasEigenvalue μ ↔ μ ∈ spectrum K f := by - rw [spectrum.mem_iff, IsUnit.sub_iff, LinearMap.isUnit_iff_ker_eq_bot, HasEigenvalue, eigenspace] + f.HasEigenvalue μ ↔ μ ∈ spectrum K f := + hasUnifEigenvalue_iff_mem_spectrum alias ⟨_, HasEigenvalue.of_mem_spectrum⟩ := hasEigenvalue_iff_mem_spectrum theorem eigenspace_div (f : End K V) (a b : K) (hb : b ≠ 0) : eigenspace f (a / b) = LinearMap.ker (b • f - algebraMap K (End K V) a) := - calc - eigenspace f (a / b) = eigenspace f (b⁻¹ * a) := by rw [div_eq_mul_inv, mul_comm] - _ = LinearMap.ker (f - (b⁻¹ * a) • LinearMap.id) := by rw [eigenspace]; rfl - _ = LinearMap.ker (f - b⁻¹ • a • LinearMap.id) := by rw [smul_smul] - _ = LinearMap.ker (f - b⁻¹ • algebraMap K (End K V) a) := rfl - _ = LinearMap.ker (b • (f - b⁻¹ • algebraMap K (End K V) a)) := by - rw [LinearMap.ker_smul _ b hb] - _ = LinearMap.ker (b • f - algebraMap K (End K V) a) := by rw [smul_sub, smul_inv_smul₀ hb] + unifEigenspace_div f a b hb /-- The generalized eigenspace for a linear map `f`, a scalar `μ`, and an exponent `k ∈ ℕ` is the kernel of `(f - μ • id) ^ k`. (Def 8.10 of [axler2015]). Furthermore, a generalized eigenspace for some exponent `k` is contained in the generalized eigenspace for exponents larger than `k`. -/ def genEigenspace (f : End R M) (μ : R) : ℕ →o Submodule R M where - toFun k := LinearMap.ker ((f - algebraMap R (End R M) μ) ^ k) - monotone' k m hm := by - simp only [← pow_sub_mul_pow _ hm] - exact - LinearMap.ker_le_ker_comp ((f - algebraMap R (End R M) μ) ^ k) - ((f - algebraMap R (End R M) μ) ^ (m - k)) + toFun k := f.unifEigenspace μ k + monotone' k l hkl := (f.unifEigenspace μ).monotone <| by simpa lemma genEigenspace_def (f : End R M) (μ : R) (k : ℕ) : - f.genEigenspace μ k = LinearMap.ker ((f - algebraMap R (End R M) μ) ^ k) := rfl + f.genEigenspace μ k = LinearMap.ker ((f - μ • 1) ^ k) := by + rw [genEigenspace, OrderHom.coe_mk, unifEigenspace_nat] @[simp] theorem mem_genEigenspace (f : End R M) (μ : R) (k : ℕ) (m : M) : - m ∈ f.genEigenspace μ k ↔ ((f - μ • (1 : End R M)) ^ k) m = 0 := Iff.rfl + m ∈ f.genEigenspace μ k ↔ ((f - μ • (1 : End R M)) ^ k) m = 0 := + mem_unifEigenspace_nat @[simp] theorem genEigenspace_zero (f : End R M) (k : ℕ) : - f.genEigenspace 0 k = LinearMap.ker (f ^ k) := by - simp [Module.End.genEigenspace] + f.genEigenspace 0 k = LinearMap.ker (f ^ k) := + unifEigenspace_zero_nat _ _ /-- A nonzero element of a generalized eigenspace is a generalized eigenvector. (Def 8.9 of [axler2015])-/ -def HasGenEigenvector (f : End R M) (μ : R) (k : ℕ) (x : M) : Prop := - x ≠ 0 ∧ x ∈ genEigenspace f μ k +abbrev HasGenEigenvector (f : End R M) (μ : R) (k : ℕ) (x : M) : Prop := + HasUnifEigenvector f μ k x lemma hasGenEigenvector_iff {f : End R M} {μ : R} {k : ℕ} {x : M} : - f.HasGenEigenvector μ k x ↔ x ≠ 0 ∧ x ∈ f.genEigenspace μ k := Iff.rfl + f.HasGenEigenvector μ k x ↔ x ∈ f.genEigenspace μ k ∧ x ≠ 0 := Iff.rfl /-- A scalar `μ` is a generalized eigenvalue for a linear map `f` and an exponent `k ∈ ℕ` if there are generalized eigenvectors for `f`, `k`, and `μ`. -/ -def HasGenEigenvalue (f : End R M) (μ : R) (k : ℕ) : Prop := - genEigenspace f μ k ≠ ⊥ +abbrev HasGenEigenvalue (f : End R M) (μ : R) (k : ℕ) : Prop := + HasUnifEigenvalue f μ k -lemma hasGenEigenvalue_iff (f : End R M) (μ : R) (k : ℕ) : - f.HasGenEigenvalue μ k ↔ genEigenspace f μ k ≠ ⊥ := Iff.rfl +lemma hasGenEigenvalue_iff {f : End R M} {μ : R} {k : ℕ} : + f.HasGenEigenvalue μ k ↔ f.genEigenspace μ k ≠ ⊥ := Iff.rfl /-- The generalized eigenrange for a linear map `f`, a scalar `μ`, and an exponent `k ∈ ℕ` is the range of `(f - μ • id) ^ k`. -/ -def genEigenrange (f : End R M) (μ : R) (k : ℕ) : Submodule R M := - LinearMap.range ((f - algebraMap R (End R M) μ) ^ k) +abbrev genEigenrange (f : End R M) (μ : R) (k : ℕ) : Submodule R M := + unifEigenrange f μ k -lemma genEigenrange_def (f : End R M) (μ : R) (k : ℕ) : - f.genEigenrange μ k = LinearMap.range ((f - algebraMap R (End R M) μ) ^ k) := rfl +lemma genEigenrange_def {f : End R M} {μ : R} {k : ℕ} : + f.genEigenrange μ k = LinearMap.range ((f - μ • 1) ^ k) := by + rw [genEigenrange, unifEigenrange_nat] /-- The exponent of a generalized eigenvalue is never 0. -/ theorem exp_ne_zero_of_hasGenEigenvalue {f : End R M} {μ : R} {k : ℕ} - (h : f.HasGenEigenvalue μ k) : k ≠ 0 := by - rintro rfl - exact h LinearMap.ker_id + (h : f.HasGenEigenvalue μ k) : k ≠ 0 := + HasUnifEigenvalue.exp_ne_zero h /-- The union of the kernels of `(f - μ • id) ^ k` over all `k`. -/ -def maxGenEigenspace (f : End R M) (μ : R) : Submodule R M := - ⨆ k, f.genEigenspace μ k +abbrev maxGenEigenspace (f : End R M) (μ : R) : Submodule R M := + unifEigenspace f μ ⊤ lemma maxGenEigenspace_def (f : End R M) (μ : R) : - f.maxGenEigenspace μ = ⨆ k, f.genEigenspace μ k := rfl + f.maxGenEigenspace μ = ⨆ k, f.genEigenspace μ k := by + simp_rw [maxGenEigenspace, unifEigenspace_top, genEigenspace, OrderHom.coe_mk] theorem genEigenspace_le_maximal (f : End R M) (μ : R) (k : ℕ) : f.genEigenspace μ k ≤ f.maxGenEigenspace μ := - le_iSup _ _ + (f.unifEigenspace μ).monotone le_top @[simp] theorem mem_maxGenEigenspace (f : End R M) (μ : R) (m : M) : - m ∈ f.maxGenEigenspace μ ↔ ∃ k : ℕ, ((f - μ • (1 : End R M)) ^ k) m = 0 := by - simp only [maxGenEigenspace, ← mem_genEigenspace, Submodule.mem_iSup_of_chain] + m ∈ f.maxGenEigenspace μ ↔ ∃ k : ℕ, ((f - μ • (1 : End R M)) ^ k) m = 0 := + mem_unifEigenspace_top /-- If there exists a natural number `k` such that the kernel of `(f - μ • id) ^ k` is the maximal generalized eigenspace, then this value is the least such `k`. If not, this value is not meaningful. -/ -noncomputable def maxGenEigenspaceIndex (f : End R M) (μ : R) := - monotonicSequenceLimitIndex (f.genEigenspace μ) +noncomputable abbrev maxGenEigenspaceIndex (f : End R M) (μ : R) := + maxUnifEigenspaceIndex f μ /-- For an endomorphism of a Noetherian module, the maximal eigenspace is always of the form kernel `(f - μ • id) ^ k` for some `k`. -/ -theorem maxGenEigenspace_eq [h : IsNoetherian R M] (f : End R M) (μ : R) : +theorem maxGenEigenspace_eq [IsNoetherian R M] (f : End R M) (μ : R) : maxGenEigenspace f μ = f.genEigenspace μ (maxGenEigenspaceIndex f μ) := - h.wf.iSup_eq_monotonicSequenceLimit (f.genEigenspace μ) + unifEigenspace_top_eq_maxUnifEigenspaceIndex _ _ /-- A generalized eigenvalue for some exponent `k` is also a generalized eigenvalue for exponents larger than `k`. -/ theorem hasGenEigenvalue_of_hasGenEigenvalue_of_le {f : End R M} {μ : R} {k : ℕ} {m : ℕ} (hm : k ≤ m) (hk : f.HasGenEigenvalue μ k) : - f.HasGenEigenvalue μ m := by - unfold HasGenEigenvalue at * - contrapose! hk - rw [← le_bot_iff, ← hk] - exact (f.genEigenspace μ).monotone hm + f.HasGenEigenvalue μ m := + hk.le <| by simpa using hm /-- The eigenspace is a subspace of the generalized eigenspace. -/ theorem eigenspace_le_genEigenspace {f : End R M} {μ : R} {k : ℕ} (hk : 0 < k) : f.eigenspace μ ≤ f.genEigenspace μ k := - (f.genEigenspace μ).monotone (Nat.succ_le_of_lt hk) + (f.unifEigenspace _).monotone <| by simpa using Nat.succ_le_of_lt hk /-- All eigenvalues are generalized eigenvalues. -/ theorem hasGenEigenvalue_of_hasEigenvalue {f : End R M} {μ : R} {k : ℕ} (hk : 0 < k) - (hμ : f.HasEigenvalue μ) : f.HasGenEigenvalue μ k := by - apply hasGenEigenvalue_of_hasGenEigenvalue_of_le hk - rw [HasGenEigenvalue, genEigenspace, OrderHom.coe_mk, pow_one] - exact hμ + (hμ : f.HasEigenvalue μ) : f.HasGenEigenvalue μ k := + hμ.lt <| by simpa using hk /-- All generalized eigenvalues are eigenvalues. -/ theorem hasEigenvalue_of_hasGenEigenvalue {f : End R M} {μ : R} {k : ℕ} - (hμ : f.HasGenEigenvalue μ k) : f.HasEigenvalue μ := by - intro contra; apply hμ - erw [LinearMap.ker_eq_bot] at contra ⊢; rw [LinearMap.coe_pow] - exact Function.Injective.iterate contra k + (hμ : f.HasGenEigenvalue μ k) : f.HasEigenvalue μ := + hμ.lt zero_lt_one /-- Generalized eigenvalues are actually just eigenvalues. -/ @[simp] theorem hasGenEigenvalue_iff_hasEigenvalue {f : End R M} {μ : R} {k : ℕ} (hk : 0 < k) : f.HasGenEigenvalue μ k ↔ f.HasEigenvalue μ := - ⟨hasEigenvalue_of_hasGenEigenvalue, hasGenEigenvalue_of_hasEigenvalue hk⟩ + hasUnifEigenvalue_iff_hasUnifEigenvalue_one <| by simpa using hk /-- Every generalized eigenvector is a generalized eigenvector for exponent `finrank K V`. (Lemma 8.11 of [axler2015]) -/ theorem genEigenspace_le_genEigenspace_finrank [FiniteDimensional K V] (f : End K V) (μ : K) (k : ℕ) : f.genEigenspace μ k ≤ f.genEigenspace μ (finrank K V) := - ker_pow_le_ker_pow_finrank _ _ + unifEigenspace_le_unifEigenspace_finrank _ _ _ @[simp] theorem iSup_genEigenspace_eq_genEigenspace_finrank [FiniteDimensional K V] (f : End K V) (μ : K) : @@ -289,7 +587,7 @@ theorem genEigenspace_le_genEigenspace_finrank [FiniteDimensional K V] (f : End theorem genEigenspace_eq_genEigenspace_finrank_of_le [FiniteDimensional K V] (f : End K V) (μ : K) {k : ℕ} (hk : finrank K V ≤ k) : f.genEigenspace μ k = f.genEigenspace μ (finrank K V) := - ker_pow_eq_ker_pow_finrank_of_le hk + unifEigenspace_eq_unifEigenspace_finrank_of_le f μ hk lemma mapsTo_genEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) (k : ℕ) : MapsTo g (f.genEigenspace μ k) (f.genEigenspace μ k) := by @@ -300,21 +598,43 @@ lemma mapsTo_genEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) (k rw [← LinearMap.comp_apply, ← LinearMap.mul_eq_comp, h.eq, LinearMap.mul_eq_comp, LinearMap.comp_apply, hx, map_zero] -lemma mapsTo_iSup_genEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) : - MapsTo g ↑(⨆ k, f.genEigenspace μ k) ↑(⨆ k, f.genEigenspace μ k) := by +lemma iSup_genEigenspace_eq (f : End R M) (μ : R) : + ⨆ k, (f.genEigenspace μ) k = f.unifEigenspace μ ⊤ := by + rw [unifEigenspace_eq_iSup_unifEigenspace_nat] + ext + simp only [iSup_subtype, le_top, iSup_pos] + rfl + +lemma mapsTo_maxGenEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) : + MapsTo g ↑(f.maxGenEigenspace μ) ↑(f.maxGenEigenspace μ) := by + rw [maxGenEigenspace_def] simp only [MapsTo, Submodule.coe_iSup_of_chain, mem_iUnion, SetLike.mem_coe] rintro x ⟨k, hk⟩ exact ⟨k, f.mapsTo_genEigenspace_of_comm h μ k hk⟩ +lemma mapsTo_iSup_genEigenspace_of_comm {f g : End R M} (h : Commute f g) (μ : R) : + MapsTo g ↑(⨆ k, f.genEigenspace μ k) ↑(⨆ k, f.genEigenspace μ k) := by + rw [← maxGenEigenspace_def] + apply mapsTo_maxGenEigenspace_of_comm h + /-- The restriction of `f - μ • 1` to the `k`-fold generalized `μ`-eigenspace is nilpotent. -/ lemma isNilpotent_restrict_sub_algebraMap (f : End R M) (μ : R) (k : ℕ) (h : MapsTo (f - algebraMap R (End R M) μ) (f.genEigenspace μ k) (f.genEigenspace μ k) := mapsTo_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ) μ k) : + IsNilpotent ((f - algebraMap R (End R M) μ).restrict h) := + isNilpotent_restrict_unifEigenspace_nat _ _ _ + +/-- The restriction of `f - μ • 1` to the generalized `μ`-eigenspace is nilpotent. -/ +lemma isNilpotent_restrict_maxGenEigenspace_sub_algebraMap [IsNoetherian R M] (f : End R M) (μ : R) + (h : MapsTo (f - algebraMap R (End R M) μ) + ↑(f.maxGenEigenspace μ) ↑(f.maxGenEigenspace μ) := + mapsTo_maxGenEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ) μ) : IsNilpotent ((f - algebraMap R (End R M) μ).restrict h) := by - use k - ext - simp [LinearMap.restrict_apply, LinearMap.pow_restrict _] + apply isNilpotent_restrict_of_le (q := f.unifEigenspace μ (maxUnifEigenspaceIndex f μ)) + _ (isNilpotent_restrict_unifEigenspace_nat f μ (maxUnifEigenspaceIndex f μ)) + rw [maxGenEigenspace_eq] + exact le_rfl /-- The restriction of `f - μ • 1` to the generalized `μ`-eigenspace is nilpotent. -/ lemma isNilpotent_restrict_iSup_sub_algebraMap [IsNoetherian R M] (f : End R M) (μ : R) @@ -322,42 +642,53 @@ lemma isNilpotent_restrict_iSup_sub_algebraMap [IsNoetherian R M] (f : End R M) ↑(⨆ k, f.genEigenspace μ k) ↑(⨆ k, f.genEigenspace μ k) := mapsTo_iSup_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ) μ) : IsNilpotent ((f - algebraMap R (End R M) μ).restrict h) := by - obtain ⟨l, hl⟩ : ∃ l, ⨆ k, f.genEigenspace μ k = f.genEigenspace μ l := - ⟨_, maxGenEigenspace_eq f μ⟩ - use l - ext ⟨x, hx⟩ - simpa [hl, LinearMap.restrict_apply, LinearMap.pow_restrict _] using hx - -lemma disjoint_genEigenspace [NoZeroSMulDivisors R M] - (f : End R M) {μ₁ μ₂ : R} (hμ : μ₁ ≠ μ₂) (k l : ℕ) : - Disjoint (f.genEigenspace μ₁ k) (f.genEigenspace μ₂ l) := by + apply isNilpotent_restrict_of_le (q := f.unifEigenspace μ (maxUnifEigenspaceIndex f μ)) + _ (isNilpotent_restrict_unifEigenspace_nat f μ (maxUnifEigenspaceIndex f μ)) + apply iSup_le + intro k + apply unifEigenspace_le_unifEigenspace_maxUnifEigenspaceIndex + +lemma disjoint_unifEigenspace [NoZeroSMulDivisors R M] + (f : End R M) {μ₁ μ₂ : R} (hμ : μ₁ ≠ μ₂) (k l : ℕ∞) : + Disjoint (f.unifEigenspace μ₁ k) (f.unifEigenspace μ₂ l) := by + rw [unifEigenspace_eq_iSup_unifEigenspace_nat, unifEigenspace_eq_iSup_unifEigenspace_nat] + simp_rw [unifEigenspace_directed.disjoint_iSup_left, unifEigenspace_directed.disjoint_iSup_right] + rintro ⟨k, -⟩ ⟨l, -⟩ nontriviality M have := NoZeroSMulDivisors.isReduced R M rw [disjoint_iff] - set p := f.genEigenspace μ₁ k ⊓ f.genEigenspace μ₂ l + set p := f.unifEigenspace μ₁ k ⊓ f.unifEigenspace μ₂ l by_contra hp replace hp : Nontrivial p := Submodule.nontrivial_iff_ne_bot.mpr hp let f₁ : End R p := (f - algebraMap R (End R M) μ₁).restrict <| MapsTo.inter_inter - (mapsTo_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₁) μ₁ k) - (mapsTo_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₁) μ₂ l) + (mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₁) μ₁ k) + (mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₁) μ₂ l) let f₂ : End R p := (f - algebraMap R (End R M) μ₂).restrict <| MapsTo.inter_inter - (mapsTo_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₂) μ₁ k) - (mapsTo_genEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₂) μ₂ l) + (mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₂) μ₁ k) + (mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f μ₂) μ₂ l) have : IsNilpotent (f₂ - f₁) := by - apply Commute.isNilpotent_sub (x := f₂) (y := f₁) _ ⟨l, ?_⟩ ⟨k, ?_⟩ + apply Commute.isNilpotent_sub (x := f₂) (y := f₁) _ + (isNilpotent_restrict_of_le inf_le_right _) + (isNilpotent_restrict_of_le inf_le_left _) · ext; simp [f₁, f₂, smul_sub, sub_sub, smul_comm μ₁, add_sub_left_comm] - all_goals ext ⟨x, _, _⟩; simpa [LinearMap.restrict_apply, LinearMap.pow_restrict _] using ‹_› + apply mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f _) + apply isNilpotent_restrict_unifEigenspace_nat + apply mapsTo_unifEigenspace_of_comm (Algebra.mul_sub_algebraMap_commutes f _) + apply isNilpotent_restrict_unifEigenspace_nat have hf₁₂ : f₂ - f₁ = algebraMap R (End R p) (μ₁ - μ₂) := by ext; simp [f₁, f₂, sub_smul] rw [hf₁₂, IsNilpotent.map_iff (NoZeroSMulDivisors.algebraMap_injective R (End R p)), isNilpotent_iff_eq_zero, sub_eq_zero] at this contradiction +lemma disjoint_genEigenspace [NoZeroSMulDivisors R M] + (f : End R M) {μ₁ μ₂ : R} (hμ : μ₁ ≠ μ₂) (k l : ℕ) : + Disjoint (f.genEigenspace μ₁ k) (f.genEigenspace μ₂ l) := + disjoint_unifEigenspace f hμ k l + lemma disjoint_iSup_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) {μ₁ μ₂ : R} (hμ : μ₁ ≠ μ₂) : Disjoint (⨆ k, f.genEigenspace μ₁ k) (⨆ k, f.genEigenspace μ₂ k) := by - simp_rw [(f.genEigenspace μ₁).mono.directed_le.disjoint_iSup_left, - (f.genEigenspace μ₂).mono.directed_le.disjoint_iSup_right] - exact disjoint_genEigenspace f hμ + simpa only [iSup_genEigenspace_eq] using disjoint_unifEigenspace f hμ ⊤ ⊤ lemma injOn_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : InjOn (⨆ k, f.genEigenspace · k) {μ | ⨆ k, f.genEigenspace μ k ≠ ⊥} := by @@ -366,12 +697,14 @@ lemma injOn_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : apply hμ₂ simpa only [hμ₁₂, disjoint_self] using f.disjoint_iSup_genEigenspace contra -theorem independent_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : - CompleteLattice.Independent (fun μ ↦ ⨆ k, f.genEigenspace μ k) := by +theorem independent_maxGenEigenspace [NoZeroSMulDivisors R M] (f : End R M) : + CompleteLattice.Independent f.maxGenEigenspace := by classical suffices ∀ μ (s : Finset R), μ ∉ s → Disjoint (⨆ k, f.genEigenspace μ k) (s.sup fun μ ↦ ⨆ k, f.genEigenspace μ k) by - simp_rw [CompleteLattice.independent_iff_supIndep_of_injOn f.injOn_genEigenspace, + show CompleteLattice.Independent (f.maxGenEigenspace ·) + simp_rw [maxGenEigenspace_def, + CompleteLattice.independent_iff_supIndep_of_injOn f.injOn_genEigenspace, Finset.supIndep_iff_disjoint_erase] exact fun s μ _ ↦ this _ _ (s.not_mem_erase μ) intro μ₁ s @@ -405,6 +738,11 @@ theorem independent_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : simp_rw [Submodule.mem_iSup_of_chain, mem_genEigenspace] exact ⟨k, hyz⟩ +theorem independent_genEigenspace [NoZeroSMulDivisors R M] (f : End R M) : + CompleteLattice.Independent (fun μ ↦ ⨆ k, f.genEigenspace μ k) := by + simp_rw [← maxGenEigenspace_def] + apply independent_maxGenEigenspace + /-- The eigenspaces of a linear operator form an independent family of subspaces of `M`. That is, any eigenspace has trivial intersection with the span of all the other eigenspaces. -/ theorem eigenspaces_independent [NoZeroSMulDivisors R M] (f : End R M) : @@ -417,7 +755,7 @@ theorem eigenvectors_linearIndependent' {ι : Type*} [NoZeroSMulDivisors R M] (f : End R M) (μ : ι → R) (hμ : Function.Injective μ) (v : ι → M) (h_eigenvec : ∀ i, f.HasEigenvector (μ i) (v i)) : LinearIndependent R v := f.eigenspaces_independent.comp hμ |>.linearIndependent _ - (fun i => h_eigenvec i |>.left) (fun i => h_eigenvec i |>.right) + (fun i ↦ h_eigenvec i |>.left) (fun i ↦ h_eigenvec i |>.right) /-- Eigenvectors corresponding to distinct eigenvalues of a linear operator are linearly independent. (Lemma 5.10 of [axler2015]) @@ -428,7 +766,7 @@ theorem eigenvectors_linearIndependent' {ι : Type*} [NoZeroSMulDivisors R M] theorem eigenvectors_linearIndependent [NoZeroSMulDivisors R M] (f : End R M) (μs : Set R) (xs : μs → M) (h_eigenvec : ∀ μ : μs, f.HasEigenvector μ (xs μ)) : LinearIndependent R xs := - f.eigenvectors_linearIndependent' (fun μ : μs => μ) Subtype.coe_injective _ h_eigenvec + f.eigenvectors_linearIndependent' (fun μ : μs ↦ μ) Subtype.coe_injective _ h_eigenvec /-- If `f` maps a subspace `p` into itself, then the generalized eigenspace of the restriction of `f` to `p` is the part of the generalized eigenspace of `f` that lies in `p`. -/ @@ -436,7 +774,7 @@ theorem genEigenspace_restrict (f : End R M) (p : Submodule R M) (k : ℕ) (μ : (hfp : ∀ x : M, x ∈ p → f x ∈ p) : genEigenspace (LinearMap.restrict f hfp) μ k = Submodule.comap p.subtype (f.genEigenspace μ k) := by - simp only [genEigenspace, OrderHom.coe_mk, ← LinearMap.ker_comp] + simp only [genEigenspace_def, OrderHom.coe_mk, ← LinearMap.ker_comp] induction' k with k ih · rw [pow_zero, pow_zero, LinearMap.one_eq_id] apply (Submodule.ker_subtype _).symm @@ -449,6 +787,50 @@ lemma _root_.Submodule.inf_genEigenspace (f : End R M) (p : Submodule R M) {k : (genEigenspace (LinearMap.restrict f hfp) μ k).map p.subtype := by rw [f.genEigenspace_restrict _ _ _ hfp, Submodule.map_comap_eq, Submodule.range_subtype] +/-- Given a family of endomorphisms `i ↦ f i`, a family of candidate eigenvalues `i ↦ μ i`, and a +submodule `p` which is invariant wrt every `f i`, the intersection of `p` with the simultaneous +maximal generalised eigenspace (taken over all `i`), is the same as the simultaneous maximal +generalised eigenspace of the `f i` restricted to `p`. -/ +lemma _root_.Submodule.inf_iInf_maxGenEigenspace_of_forall_mapsTo {ι : Type*} {μ : ι → R} + (f : ι → End R M) (p : Submodule R M) (hfp : ∀ i, MapsTo (f i) p p) : + p ⊓ ⨅ i, (f i).maxGenEigenspace (μ i) = + (⨅ i, maxGenEigenspace ((f i).restrict (hfp i)) (μ i)).map p.subtype := by + cases isEmpty_or_nonempty ι + · simp [iInf_of_isEmpty] + · simp_rw [inf_iInf, maxGenEigenspace_def, ((f _).genEigenspace _).mono.directed_le.inf_iSup_eq, + p.inf_genEigenspace _ (hfp _), ← Submodule.map_iSup, Submodule.map_iInf _ p.injective_subtype] + +/-- Given a family of endomorphisms `i ↦ f i`, a family of candidate eigenvalues `i ↦ μ i`, and a +distinguished index `i` whose maximal generalised `μ i`-eigenspace is invariant wrt every `f j`, +taking simultaneous maximal generalised eigenspaces is unaffected by first restricting to the +distinguished generalised `μ i`-eigenspace. -/ +lemma iInf_maxGenEigenspace_restrict_map_subtype_eq + {ι : Type*} {μ : ι → R} (i : ι) (f : ι → End R M) + (h : ∀ j, MapsTo (f j) ((f i).maxGenEigenspace (μ i)) ((f i).maxGenEigenspace (μ i))) : + letI p := (f i).maxGenEigenspace (μ i) + letI q (j : ι) := maxGenEigenspace ((f j).restrict (h j)) (μ j) + (⨅ j, q j).map p.subtype = ⨅ j, (f j).maxGenEigenspace (μ j) := by + have : Nonempty ι := ⟨i⟩ + set p := (f i).maxGenEigenspace (μ i) + have : ⨅ j, (f j).maxGenEigenspace (μ j) = p ⊓ ⨅ j, (f j).maxGenEigenspace (μ j) := by + refine le_antisymm ?_ inf_le_right + simpa only [le_inf_iff, le_refl, and_true] using iInf_le _ _ + rw [Submodule.map_iInf _ p.injective_subtype, this, Submodule.inf_iInf] + simp_rw [maxGenEigenspace_def, Submodule.map_iSup, + ((f _).genEigenspace _).mono.directed_le.inf_iSup_eq, p.inf_genEigenspace (f _) (h _)] + +lemma mapsTo_restrict_maxGenEigenspace_restrict_of_mapsTo + {p : Submodule R M} (f g : End R M) (hf : MapsTo f p p) (hg : MapsTo g p p) {μ₁ μ₂ : R} + (h : MapsTo f (g.maxGenEigenspace μ₁) (g.maxGenEigenspace μ₂)) : + MapsTo (f.restrict hf) + (maxGenEigenspace (g.restrict hg) μ₁) + (maxGenEigenspace (g.restrict hg) μ₂) := by + intro x hx + simp_rw [SetLike.mem_coe, mem_maxGenEigenspace, ← LinearMap.restrict_smul_one _, + LinearMap.restrict_sub _, LinearMap.pow_restrict _, LinearMap.restrict_apply, + Submodule.mk_eq_zero, ← mem_maxGenEigenspace] at hx ⊢ + exact h hx + /-- If `p` is an invariant submodule of an endomorphism `f`, then the `μ`-eigenspace of the restriction of `f` to `p` is a submodule of the `μ`-eigenspace of `f`. -/ theorem eigenspace_restrict_le_eigenspace (f : End R M) {p : Submodule R M} (hfp : ∀ x ∈ p, f x ∈ p) @@ -463,16 +845,18 @@ theorem generalized_eigenvec_disjoint_range_ker [FiniteDimensional K V] (f : End (f.genEigenspace μ (finrank K V)) := by have h := calc - Submodule.comap ((f - algebraMap _ _ μ) ^ finrank K V) + Submodule.comap ((f - μ • 1) ^ finrank K V) (f.genEigenspace μ (finrank K V)) = LinearMap.ker ((f - algebraMap _ _ μ) ^ finrank K V * (f - algebraMap K (End K V) μ) ^ finrank K V) := by - rw [genEigenspace, OrderHom.coe_mk, ← LinearMap.ker_comp]; rfl - _ = f.genEigenspace μ (finrank K V + finrank K V) := by rw [← pow_add]; rfl + rw [genEigenspace, OrderHom.coe_mk, unifEigenspace_nat, ← LinearMap.ker_comp]; rfl + _ = f.genEigenspace μ (finrank K V + finrank K V) := by + rw [← pow_add, genEigenspace, OrderHom.coe_mk, unifEigenspace_nat]; rfl _ = f.genEigenspace μ (finrank K V) := by - rw [genEigenspace_eq_genEigenspace_finrank_of_le]; omega - rw [disjoint_iff_inf_le, genEigenrange, LinearMap.range_eq_map, - Submodule.map_inf_eq_map_inf_comap, top_inf_eq, h] + rw [genEigenspace_eq_genEigenspace_finrank_of_le]; omega + rw [disjoint_iff_inf_le, genEigenrange, unifEigenrange_nat, LinearMap.range_eq_map, + Submodule.map_inf_eq_map_inf_comap, top_inf_eq, h, + genEigenspace, OrderHom.coe_mk, unifEigenspace_nat] apply Submodule.map_comap_le /-- If an invariant subspace `p` of an endomorphism `f` is disjoint from the `μ`-eigenspace of `f`, @@ -499,11 +883,13 @@ theorem map_genEigenrange_le {f : End K V} {μ : K} {n : ℕ} : calc Submodule.map f (f.genEigenrange μ n) = LinearMap.range (f * (f - algebraMap _ _ μ) ^ n) := by - rw [genEigenrange]; exact (LinearMap.range_comp _ _).symm + rw [genEigenrange, unifEigenrange_nat]; exact (LinearMap.range_comp _ _).symm _ = LinearMap.range ((f - algebraMap _ _ μ) ^ n * f) := by rw [Algebra.mul_sub_algebraMap_pow_commutes] _ = Submodule.map ((f - algebraMap _ _ μ) ^ n) (LinearMap.range f) := LinearMap.range_comp _ _ - _ ≤ f.genEigenrange μ n := LinearMap.map_le_range + _ ≤ f.genEigenrange μ n := by + rw [genEigenrange, unifEigenrange_nat] + apply LinearMap.map_le_range lemma iSup_genEigenspace_le_smul (f : Module.End R M) (μ t : R) : (⨆ k, f.genEigenspace μ k) ≤ ⨆ k, (t • f).genEigenspace (t * μ) k := by diff --git a/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean b/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean index 561d462974d51..70c17ee7b2097 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Minpoly.lean @@ -21,7 +21,7 @@ namespace Module namespace End -open Polynomial FiniteDimensional +open Polynomial Module open scoped Polynomial @@ -78,7 +78,7 @@ theorem hasEigenvalue_of_isRoot (h : (minpoly K f).IsRoot μ) : f.HasEigenvalue have : (aeval f) p = 0 := by have h_aeval := minpoly.aeval K f revert h_aeval - simp [hp, ← hu] + simp [hp, ← hu, Algebra.algebraMap_eq_smul_one] have h_deg := minpoly.degree_le_of_ne_zero K f p_ne_0 this rw [hp, degree_mul, degree_X_sub_C, Polynomial.degree_eq_natDegree p_ne_0] at h_deg norm_cast at h_deg diff --git a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean index e2cd61a713f7f..03e4ac0132b66 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Triangularizable.lean @@ -38,7 +38,7 @@ generalized eigenspaces span the whole space. eigenspace, eigenvector, eigenvalue, eigen -/ -open Set Function Module FiniteDimensional +open Set Function Module Module variable {K V : Type*} [Field K] [AddCommGroup V] [Module K V] {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] @@ -222,3 +222,54 @@ theorem Module.End.iSup_genEigenspace_restrict_eq_top simp_rw [Submodule.inf_genEigenspace f p h, Submodule.comap_subtype_self, ← Submodule.map_iSup, Submodule.comap_map_eq_of_injective h_inj] at this exact this.symm + +/-- Given a family of endomorphisms `i ↦ f i` which are compatible in the sense that every maximal +generalised eigenspace of `f i` is invariant wrt `f j`, if each `f i` is triangularizable, the +family is simultaneously triangularizable. -/ +lemma Module.End.iSup_iInf_maxGenEigenspace_eq_top_of_forall_mapsTo + {ι : Type*} [FiniteDimensional K V] + (f : ι → End K V) + (h : ∀ i j φ, MapsTo (f i) ((f j).maxGenEigenspace φ) ((f j).maxGenEigenspace φ)) + (h' : ∀ i, ⨆ μ, (f i).maxGenEigenspace μ = ⊤) : + ⨆ χ : ι → K, ⨅ i, (f i).maxGenEigenspace (χ i) = ⊤ := by + generalize h_dim : finrank K V = n + induction n using Nat.strongRecOn generalizing V with | ind n ih => ?_ + obtain this | ⟨i : ι, hy : ¬ ∃ φ, (f i).maxGenEigenspace φ = ⊤⟩ := + forall_or_exists_not (fun j : ι ↦ ∃ φ : K, (f j).maxGenEigenspace φ = ⊤) + · choose χ hχ using this + replace hχ : ⨅ i, (f i).maxGenEigenspace (χ i) = ⊤ := by simpa + simp_rw [eq_top_iff] at hχ ⊢ + exact le_trans hχ <| le_iSup (fun χ : ι → K ↦ ⨅ i, (f i).maxGenEigenspace (χ i)) χ + · replace hy : ∀ φ, finrank K ((f i).maxGenEigenspace φ) < n := fun φ ↦ by + simp_rw [not_exists, ← lt_top_iff_ne_top] at hy; exact h_dim ▸ Submodule.finrank_lt (hy φ) + have hi (j : ι) (φ : K) : + MapsTo (f j) ((f i).maxGenEigenspace φ) ((f i).maxGenEigenspace φ) := by + exact h j i φ + replace ih (φ : K) : + ⨆ χ : ι → K, ⨅ j, maxGenEigenspace ((f j).restrict (hi j φ)) (χ j) = ⊤ := by + apply ih _ (hy φ) + · intro j k μ + exact mapsTo_restrict_maxGenEigenspace_restrict_of_mapsTo (f j) (f k) _ _ (h j k μ) + · simp_rw [maxGenEigenspace_def] at h' ⊢ + exact fun j ↦ Module.End.iSup_genEigenspace_restrict_eq_top _ (h' j) + · rfl + replace ih (φ : K) : + ⨆ (χ : ι → K) (_ : χ i = φ), ⨅ j, maxGenEigenspace ((f j).restrict (hi j φ)) (χ j) = ⊤ := by + suffices ∀ χ : ι → K, χ i ≠ φ → ⨅ j, maxGenEigenspace ((f j).restrict (hi j φ)) (χ j) = ⊥ by + specialize ih φ; rw [iSup_split, biSup_congr this] at ih; simpa using ih + intro χ hχ + rw [eq_bot_iff, ← ((f i).maxGenEigenspace φ).ker_subtype, LinearMap.ker, + ← Submodule.map_le_iff_le_comap, ← Submodule.inf_iInf_maxGenEigenspace_of_forall_mapsTo, + ← disjoint_iff_inf_le] + simp_rw [maxGenEigenspace_def] + exact ((f i).disjoint_iSup_genEigenspace hχ.symm).mono_right (iInf_le _ i) + replace ih (φ : K) : + ⨆ (χ : ι → K) (_ : χ i = φ), ⨅ j, maxGenEigenspace (f j) (χ j) = + maxGenEigenspace (f i) φ := by + have (χ : ι → K) (hχ : χ i = φ) : ⨅ j, maxGenEigenspace (f j) (χ j) = + (⨅ j, maxGenEigenspace ((f j).restrict (hi j φ)) (χ j)).map + ((f i).maxGenEigenspace φ).subtype := by + rw [← hχ, iInf_maxGenEigenspace_restrict_map_subtype_eq] + simp_rw [biSup_congr this, ← Submodule.map_iSup, ih, Submodule.map_top, + Submodule.range_subtype] + simpa only [← ih, iSup_comm (ι := K), iSup_iSup_eq_right] using h' i diff --git a/Mathlib/LinearAlgebra/Eigenspace/Zero.lean b/Mathlib/LinearAlgebra/Eigenspace/Zero.lean index 7830bfb5e4d7f..30837353e1b0a 100644 --- a/Mathlib/LinearAlgebra/Eigenspace/Zero.lean +++ b/Mathlib/LinearAlgebra/Eigenspace/Zero.lean @@ -33,7 +33,7 @@ variable {R K M : Type*} [CommRing R] [IsDomain R] [Field K] [AddCommGroup M] variable [Module R M] [Module.Finite R M] [Module.Free R M] variable [Module K M] [Module.Finite K M] -open FiniteDimensional Module.Free Polynomial +open Module Module.Free Polynomial lemma IsNilpotent.charpoly_eq_X_pow_finrank (φ : Module.End R M) (h : IsNilpotent φ) : φ.charpoly = X ^ finrank R M := by @@ -160,7 +160,7 @@ lemma finrank_maxGenEigenspace (φ : Module.End K M) : apply b.ext simp only [Basis.prod_apply, coe_inl, coe_inr, prodMap_apply, LinearEquiv.conj_apply, LinearEquiv.symm_symm, Submodule.coe_prodEquivOfIsCompl, coe_comp, LinearEquiv.coe_coe, - Function.comp_apply, coprod_apply, Submodule.coeSubtype, map_add, Sum.forall, Sum.elim_inl, + Function.comp_apply, coprod_apply, Submodule.coe_subtype, map_add, Sum.forall, Sum.elim_inl, map_zero, ZeroMemClass.coe_zero, add_zero, LinearEquiv.eq_symm_apply, and_self, Submodule.coe_prodEquivOfIsCompl', restrict_coe_apply, implies_true, Sum.elim_inr, zero_add, e, V, W, ψ, F, G, b] diff --git a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean index 3b3ed5d5dab30..cd48d0d7611d4 100644 --- a/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean +++ b/Mathlib/LinearAlgebra/ExteriorAlgebra/Basic.lean @@ -164,6 +164,9 @@ theorem algebraMap_eq_zero_iff (x : R) : algebraMap R (ExteriorAlgebra R M) x = theorem algebraMap_eq_one_iff (x : R) : algebraMap R (ExteriorAlgebra R M) x = 1 ↔ x = 1 := map_eq_one_iff (algebraMap _ _) (algebraMap_leftInverse _).injective +instance isLocalRingHom_algebraMap : IsLocalRingHom (algebraMap R (ExteriorAlgebra R M)) := + isLocalRingHom_of_leftInverse _ (algebraMap_leftInverse M) + theorem isUnit_algebraMap (r : R) : IsUnit (algebraMap R (ExteriorAlgebra R M) r) ↔ IsUnit r := isUnit_map_of_leftInverse _ (algebraMap_leftInverse M) @@ -299,8 +302,8 @@ theorem ιMulti_apply {n : ℕ} (v : Fin n → M) : ιMulti R n v = (List.ofFn f rfl @[simp] -theorem ιMulti_zero_apply (v : Fin 0 → M) : ιMulti R 0 v = 1 := - rfl +theorem ιMulti_zero_apply (v : Fin 0 → M) : ιMulti R 0 v = 1 := by + simp [ιMulti] @[simp] theorem ιMulti_succ_apply {n : ℕ} (v : Fin n.succ → M) : diff --git a/Mathlib/LinearAlgebra/FiniteDimensional.lean b/Mathlib/LinearAlgebra/FiniteDimensional.lean index 8aec07c6ff9dd..7b2f68f6cdcdd 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional.lean @@ -27,7 +27,7 @@ variable {K : Type u} {V : Type v} namespace Submodule -open IsNoetherian FiniteDimensional +open IsNoetherian Module section DivisionRing @@ -116,7 +116,7 @@ end FiniteDimensional namespace LinearMap -open FiniteDimensional +open Module section DivisionRing @@ -142,7 +142,7 @@ end DivisionRing end LinearMap -open FiniteDimensional +open Module namespace LinearMap diff --git a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean index 7209c69493247..f7ab907b35f9c 100644 --- a/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean +++ b/Mathlib/LinearAlgebra/FiniteDimensional/Defs.lean @@ -27,7 +27,7 @@ that all these points of view are equivalent, with the following lemmas - `fintypeBasisIndex` states that a finite-dimensional vector space has a finite basis -- `FiniteDimensional.finBasis` and `FiniteDimensional.finBasisOfFinrankEq` +- `Module.finBasis` and `Module.finBasisOfFinrankEq` are bases for finite dimensional vector spaces, where the index type is `Fin` (in `Mathlib.LinearAlgebra.Dimension.Free`) - `of_fintype_basis` states that the existence of a basis indexed by a @@ -70,7 +70,7 @@ Plenty of the results hold for general fg modules or notherian modules, and they universe u v v' w -open Cardinal Submodule Module Function +open Cardinal Function IsNoetherian Module Submodule /-- `FiniteDimensional` vector spaces are defined to be finite modules. Use `FiniteDimensional.of_fintype_basis` to prove finite dimension from another definition. -/ @@ -80,11 +80,6 @@ abbrev FiniteDimensional (K V : Type*) [DivisionRing K] [AddCommGroup V] [Module variable {K : Type u} {V : Type v} namespace FiniteDimensional - -open IsNoetherian - -section DivisionRing - variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] [Module K V₂] @@ -145,10 +140,8 @@ theorem of_finite_basis {ι : Type w} {s : Set ι} (h : Basis s K V) (hs : Set.F instance finiteDimensional_submodule [FiniteDimensional K V] (S : Submodule K V) : FiniteDimensional K S := by letI : IsNoetherian K V := iff_fg.2 ?_ - · exact - iff_fg.1 - (IsNoetherian.iff_rank_lt_aleph0.2 - (lt_of_le_of_lt (rank_submodule_le _) (_root_.rank_lt_aleph0 K V))) + · exact iff_fg.1 <| IsNoetherian.iff_rank_lt_aleph0.2 <| + (Submodule.rank_le _).trans_lt (rank_lt_aleph0 K V) · infer_instance /-- A quotient of a finite-dimensional space is also finite-dimensional. -/ @@ -156,18 +149,6 @@ instance finiteDimensional_quotient [FiniteDimensional K V] (S : Submodule K V) FiniteDimensional K (V ⧸ S) := Module.Finite.quotient K S -variable (K V) - -/-- In a finite-dimensional space, its dimension (seen as a cardinal) coincides with its -`finrank`. This is a copy of `finrank_eq_rank _ _` which creates easier typeclass searches. -/ -theorem finrank_eq_rank' [FiniteDimensional K V] : (finrank K V : Cardinal.{v}) = Module.rank K V := - finrank_eq_rank _ _ - -variable {K V} - -theorem finrank_of_infinite_dimensional (h : ¬FiniteDimensional K V) : finrank K V = 0 := - FiniteDimensional.finrank_of_not_finite h - theorem of_finrank_pos (h : 0 < finrank K V) : FiniteDimensional K V := Module.finite_of_finrank_pos h @@ -181,6 +162,24 @@ theorem of_fact_finrank_eq_succ (n : ℕ) [hn : Fact (finrank K V = n + 1)] : FiniteDimensional K V := of_finrank_eq_succ hn.out +end FiniteDimensional + +namespace Module + +variable (K V) +variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] + [Module K V₂] + +/-- In a finite-dimensional space, its dimension (seen as a cardinal) coincides with its +`finrank`. This is a copy of `finrank_eq_rank _ _` which creates easier typeclass searches. -/ +theorem finrank_eq_rank' [FiniteDimensional K V] : (finrank K V : Cardinal.{v}) = Module.rank K V := + finrank_eq_rank _ _ + +variable {K V} + +theorem finrank_of_infinite_dimensional (h : ¬FiniteDimensional K V) : finrank K V = 0 := + Module.finrank_of_not_finite h + theorem finiteDimensional_iff_of_rank_eq_nsmul {W} [AddCommGroup W] [Module K W] {n : ℕ} (hn : n ≠ 0) (hVW : Module.rank K V = n • Module.rank K W) : FiniteDimensional K V ↔ FiniteDimensional K W := @@ -192,11 +191,16 @@ theorem finrank_eq_card_basis' [FiniteDimensional K V] {ι : Type w} (h : Basis (finrank K V : Cardinal.{w}) = #ι := Module.mk_finrank_eq_card_basis h +end Module + +namespace FiniteDimensional +section DivisionRing +variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] + [Module K V₂] + theorem _root_.LinearIndependent.lt_aleph0_of_finiteDimensional {ι : Type w} [FiniteDimensional K V] {v : ι → V} (h : LinearIndependent K v) : #ι < ℵ₀ := h.lt_aleph0_of_finite -@[deprecated (since := "2023-12-27")] -alias lt_aleph0_of_linearIndependent := LinearIndependent.lt_aleph0_of_finiteDimensional /-- If a submodule has maximal dimension in a finite dimensional space, then it is equal to the whole space. -/ @@ -221,7 +225,7 @@ theorem _root_.Submodule.eq_top_of_finrank_eq [FiniteDimensional K V] {S : Submo (by rw [Set.card_image_of_injective _ Subtype.coe_injective, ← finrank_eq_card_basis bS, ← finrank_eq_card_basis b, h]) - rw [← b.span_eq, b_eq, Basis.coe_extend, Subtype.range_coe, ← this, ← Submodule.coeSubtype, + rw [← b.span_eq, b_eq, Basis.coe_extend, Subtype.range_coe, ← this, ← Submodule.coe_subtype, span_image] have := bS.span_eq rw [bS_eq, Basis.coe_ofVectorSpace, Subtype.range_coe] at this @@ -254,8 +258,6 @@ section open Finset -section - variable {L : Type*} [LinearOrderedField L] variable {W : Type v} [AddCommGroup W] [Module L W] @@ -271,16 +273,14 @@ theorem exists_relation_sum_zero_pos_coefficient_of_finrank_succ_lt_card [Finite exact ⟨f, sum, total, exists_pos_of_sum_zero_of_exists_nonzero f total nonzero⟩ -end - end /-- In a vector space with dimension 1, each set {v} is a basis for `v ≠ 0`. -/ @[simps repr_apply] noncomputable def basisSingleton (ι : Type*) [Unique ι] (h : finrank K V = 1) (v : V) (hv : v ≠ 0) : Basis ι K V := - let b := FiniteDimensional.basisUnique ι h - let h : b.repr v default ≠ 0 := mt FiniteDimensional.basisUnique_repr_eq_zero_iff.mp hv + let b := Module.basisUnique ι h + let h : b.repr v default ≠ 0 := mt Module.basisUnique_repr_eq_zero_iff.mp hv Basis.ofRepr { toFun := fun w => Finsupp.single default (b.repr w default / b.repr v default) invFun := fun f => f default • v @@ -326,8 +326,6 @@ section ZeroRank variable [DivisionRing K] [AddCommGroup V] [Module K V] -open FiniteDimensional - theorem FiniteDimensional.of_rank_eq_nat {n : ℕ} (h : Module.rank K V = n) : FiniteDimensional K V := Module.finite_of_rank_eq_nat h @@ -350,7 +348,7 @@ alias finiteDimensional_of_rank_eq_one := FiniteDimensional.of_rank_eq_one variable (K V) instance finiteDimensional_bot : FiniteDimensional K (⊥ : Submodule K V) := - of_rank_eq_zero <| by simp + .of_rank_eq_zero <| by simp variable {K V} @@ -358,7 +356,7 @@ end ZeroRank namespace Submodule -open IsNoetherian FiniteDimensional +open IsNoetherian Module section DivisionRing @@ -374,8 +372,7 @@ theorem finiteDimensional_of_le {S₁ S₂ : Submodule K V} [FiniteDimensional K FiniteDimensional K S₁ := haveI : IsNoetherian K S₂ := iff_fg.2 inferInstance iff_fg.1 - (IsNoetherian.iff_rank_lt_aleph0.2 - (lt_of_le_of_lt (rank_le_of_submodule _ _ h) (rank_lt_aleph0 K S₂))) + (IsNoetherian.iff_rank_lt_aleph0.2 ((Submodule.rank_mono h).trans_lt (rank_lt_aleph0 K S₂))) /-- The inf of two submodules, the first finite-dimensional, is finite-dimensional. -/ @@ -424,7 +421,7 @@ end Submodule namespace LinearEquiv -open FiniteDimensional +open Module variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] [Module K V₂] @@ -449,10 +446,7 @@ instance finiteDimensional_finsupp {ι : Type*} [Finite ι] [FiniteDimensional K end -namespace FiniteDimensional - -section DivisionRing - +namespace Submodule variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] [Module K V₂] @@ -470,33 +464,29 @@ theorem eq_of_le_of_finrank_eq {S₁ S₂ : Submodule K V} [FiniteDimensional K (hd : finrank K S₁ = finrank K S₂) : S₁ = S₂ := eq_of_le_of_finrank_le hle hd.ge -section Subalgebra +end Submodule + +namespace Subalgebra variable {K L : Type*} [Field K] [Ring L] [Algebra K L] {F E : Subalgebra K L} [hfin : FiniteDimensional K E] /-- If a subalgebra is contained in a finite-dimensional subalgebra with the same or smaller dimension, they are equal. -/ -theorem _root_.Subalgebra.eq_of_le_of_finrank_le (h_le : F ≤ E) - (h_finrank : finrank K E ≤ finrank K F) : F = E := +theorem eq_of_le_of_finrank_le (h_le : F ≤ E) (h_finrank : finrank K E ≤ finrank K F) : F = E := haveI : Module.Finite K (Subalgebra.toSubmodule E) := hfin - Subalgebra.toSubmodule_injective <| FiniteDimensional.eq_of_le_of_finrank_le h_le h_finrank + toSubmodule_injective <| Submodule.eq_of_le_of_finrank_le h_le h_finrank /-- If a subalgebra is contained in a finite-dimensional subalgebra with the same dimension, they are equal. -/ -theorem _root_.Subalgebra.eq_of_le_of_finrank_eq (h_le : F ≤ E) - (h_finrank : finrank K F = finrank K E) : F = E := - Subalgebra.eq_of_le_of_finrank_le h_le h_finrank.ge +theorem eq_of_le_of_finrank_eq (h_le : F ≤ E) (h_finrank : finrank K F = finrank K E) : F = E := + eq_of_le_of_finrank_le h_le h_finrank.ge end Subalgebra -end DivisionRing - -end FiniteDimensional - namespace LinearMap -open FiniteDimensional +open Module section DivisionRing @@ -600,7 +590,7 @@ end LinearMap namespace LinearEquiv -open FiniteDimensional +open Module variable [DivisionRing K] [AddCommGroup V] [Module K V] variable [FiniteDimensional K V] @@ -647,14 +637,14 @@ theorem isUnit_iff_range_eq_top [FiniteDimensional K V] (f : V →ₗ[K] V) : end LinearMap -open Module FiniteDimensional +open FiniteDimensional Module section variable [DivisionRing K] [AddCommGroup V] [Module K V] theorem finrank_zero_iff_forall_zero [FiniteDimensional K V] : finrank K V = 0 ↔ ∀ x : V, x = 0 := - FiniteDimensional.finrank_zero_iff.trans (subsingleton_iff_forall_eq 0) + Module.finrank_zero_iff.trans (subsingleton_iff_forall_eq 0) /-- If `ι` is an empty type and `V` is zero-dimensional, there is a unique `ι`-indexed basis. -/ noncomputable def basisOfFinrankZero [FiniteDimensional K V] {ι : Type*} [IsEmpty ι] @@ -679,7 +669,7 @@ noncomputable def divisionRingOfFiniteDimensional (F K : Type*) [Field F] [Ring inv x := letI := Classical.decEq K if H : x = 0 then 0 else Classical.choose <| FiniteDimensional.exists_mul_eq_one F H - mul_inv_cancel x hx := show x * dite _ (h := _) _ = _ by + mul_inv_cancel x hx := show x * dite _ (h := _) _ _ = _ by rw [dif_neg hx] exact (Classical.choose_spec (FiniteDimensional.exists_mul_eq_one F hx):) inv_zero := dif_pos rfl @@ -694,21 +684,6 @@ noncomputable def fieldOfFiniteDimensional (F K : Type*) [Field F] [h : CommRing { divisionRingOfFiniteDimensional F K with toCommRing := h } end - -namespace Submodule - -section DivisionRing - -variable [DivisionRing K] [AddCommGroup V] [Module K V] {V₂ : Type v'} [AddCommGroup V₂] - [Module K V₂] - -theorem finrank_mono [FiniteDimensional K V] : Monotone fun s : Submodule K V => finrank K s := - fun _ _ => finrank_le_finrank_of_le - -end DivisionRing - -end Submodule - section DivisionRing variable [DivisionRing K] [AddCommGroup V] [Module K V] diff --git a/Mathlib/LinearAlgebra/Finsupp.lean b/Mathlib/LinearAlgebra/Finsupp.lean index fe713da58c68c..810b8a01afebd 100644 --- a/Mathlib/LinearAlgebra/Finsupp.lean +++ b/Mathlib/LinearAlgebra/Finsupp.lean @@ -365,7 +365,7 @@ theorem supported_iUnion {δ : Type*} (s : δ → Set α) : · exact zero_mem _ · refine fun x a l _ _ => add_mem ?_ by_cases h : ∃ i, x ∈ s i - · simp only [mem_comap, coe_comp, coeSubtype, Function.comp_apply, restrictDom_apply, + · simp only [mem_comap, coe_comp, coe_subtype, Function.comp_apply, restrictDom_apply, mem_iUnion, h, filter_single_of_pos] cases' h with i hi exact le_iSup (fun i => supported M R (s i)) i (single_mem_supported R _ hi) diff --git a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean index d0b35b5f4be62..27e40eb067043 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Finite/Matrix.lean @@ -26,7 +26,7 @@ variable (R : Type u) (S : Type u') (M : Type v) (N : Type w) open Module.Free (chooseBasis ChooseBasisIndex) -open FiniteDimensional (finrank) +open Module (finrank) section Ring @@ -46,27 +46,27 @@ instance Module.Finite.linearMap [Module.Finite S N] : Module.Finite S (M →ₗ variable [StrongRankCondition R] [StrongRankCondition S] [Module.Free S N] open Cardinal -theorem FiniteDimensional.rank_linearMap : +theorem Module.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] /-- The finrank of `M →ₗ[R] N` as an `S`-module is `(finrank R M) * (finrank S N)`. -/ -theorem FiniteDimensional.finrank_linearMap : +theorem Module.finrank_linearMap : finrank S (M →ₗ[R] N) = finrank R M * finrank S N := by simp_rw [finrank, rank_linearMap, toNat_mul, toNat_lift] variable [Module R S] [SMulCommClass R S S] -theorem FiniteDimensional.rank_linearMap_self : +theorem Module.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] -theorem FiniteDimensional.finrank_linearMap_self : finrank S (M →ₗ[R] S) = finrank R M := by +theorem Module.finrank_linearMap_self : finrank S (M →ₗ[R] S) = finrank R M := by rw [finrank_linearMap, finrank_self, mul_one] @[deprecated (since := "2024-01-12")] -alias FiniteDimensional.finrank_linear_map' := FiniteDimensional.finrank_linearMap_self +alias Module.finrank_linear_map' := Module.finrank_linearMap_self end Ring @@ -84,12 +84,12 @@ theorem cardinal_mk_algHom_le_rank : #(M →ₐ[K] L) ≤ lift.{v} (Module.rank 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] + rw [lift_id, Module.rank_linearMap_self] theorem card_algHom_le_finrank : Nat.card (M →ₐ[K] L) ≤ finrank K M := by convert toNat_le_toNat (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 + · rw [lift_lt_aleph0]; have := Module.nontrivial K L; apply Module.rank_lt_aleph0 end AlgHom diff --git a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean index 44870709f726a..054d145f3347d 100644 --- a/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean +++ b/Mathlib/LinearAlgebra/FreeModule/IdealQuotient.lean @@ -114,9 +114,9 @@ noncomputable def quotientEquivDirectSum : theorem finrank_quotient_eq_sum {ι} [Fintype ι] (b : Basis ι R S) [Nontrivial F] [∀ i, Module.Free F (R ⧸ span ({I.smithCoeffs b hI i} : Set R))] [∀ i, Module.Finite F (R ⧸ span ({I.smithCoeffs b hI i} : Set R))] : - FiniteDimensional.finrank F (S ⧸ I) = - ∑ i, FiniteDimensional.finrank F (R ⧸ span ({I.smithCoeffs b hI i} : Set R)) := by + Module.finrank F (S ⧸ I) = + ∑ i, Module.finrank F (R ⧸ span ({I.smithCoeffs b hI i} : Set R)) := by -- slow, and dot notation doesn't work - rw [LinearEquiv.finrank_eq <| quotientEquivDirectSum F b hI, FiniteDimensional.finrank_directSum] + rw [LinearEquiv.finrank_eq <| quotientEquivDirectSum F b hI, Module.finrank_directSum] end Ideal diff --git a/Mathlib/LinearAlgebra/FreeModule/Norm.lean b/Mathlib/LinearAlgebra/FreeModule/Norm.lean index 39bb414d9ce5c..5332fcc328e26 100644 --- a/Mathlib/LinearAlgebra/FreeModule/Norm.lean +++ b/Mathlib/LinearAlgebra/FreeModule/Norm.lean @@ -71,7 +71,7 @@ instance (b : Basis ι F[X] S) {I : Ideal S} (hI : I ≠ ⊥) (i : ι) : `F`-vector space is the degree of the norm of `f` relative to `F[X]`. -/ theorem finrank_quotient_span_eq_natDegree_norm [Algebra F S] [IsScalarTower F F[X] S] (b : Basis ι F[X] S) {f : S} (hf : f ≠ 0) : - FiniteDimensional.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by + Module.finrank F (S ⧸ span ({f} : Set S)) = (Algebra.norm F[X] f).natDegree := by haveI := Fintype.ofFinite ι have h := span_singleton_eq_bot.not.2 hf rw [natDegree_eq_of_degree_eq diff --git a/Mathlib/LinearAlgebra/FreeModule/PID.lean b/Mathlib/LinearAlgebra/FreeModule/PID.lean index c5c0346f9a5de..3e5251f600539 100644 --- a/Mathlib/LinearAlgebra/FreeModule/PID.lean +++ b/Mathlib/LinearAlgebra/FreeModule/PID.lean @@ -251,7 +251,7 @@ theorem Submodule.basis_of_pid_aux [Finite ι] {O : Type*} [AddCommGroup O] [Mod refine ⟨-b, Submodule.mem_map.mpr ⟨⟨_, N.sub_mem zN (N.smul_mem b yN)⟩, ?_, ?_⟩⟩ · refine LinearMap.mem_ker.mpr (show ϕ (⟨z, N_le_M zN⟩ - b • ⟨y, N_le_M yN⟩) = 0 from ?_) rw [LinearMap.map_sub, LinearMap.map_smul, hb, ϕy_eq, smul_eq_mul, mul_comm, sub_self] - · simp only [sub_eq_add_neg, neg_smul, coeSubtype] + · simp only [sub_eq_add_neg, neg_smul, coe_subtype] -- And extend a basis for `M'` with `y'` intro m' hn'm' bM' refine ⟨Nat.succ_le_succ hn'm', ?_, ?_⟩ @@ -270,7 +270,7 @@ theorem Submodule.basis_of_pid_aux [Finite ι] {O : Type*} [AddCommGroup O] [Mod · simp only [Fin.cons_zero, Fin.castLE_zero] exact a_smul_y'.symm · rw [Fin.castLE_succ] - simp only [Fin.cons_succ, Function.comp_apply, coe_inclusion, map_coe, coeSubtype, h i] + simp only [Fin.cons_succ, Function.comp_apply, coe_inclusion, map_coe, coe_subtype, h i] /-- A submodule of a free `R`-module of finite rank is also a free `R`-module of finite rank, if `R` is a principal ideal domain. diff --git a/Mathlib/LinearAlgebra/GeneralLinearGroup.lean b/Mathlib/LinearAlgebra/GeneralLinearGroup.lean index c85e27df2b8bf..289bcb15903b7 100644 --- a/Mathlib/LinearAlgebra/GeneralLinearGroup.lean +++ b/Mathlib/LinearAlgebra/GeneralLinearGroup.lean @@ -37,8 +37,8 @@ variable {R M} def toLinearEquiv (f : GeneralLinearGroup R M) : M ≃ₗ[R] M := { f.val with invFun := f.inv.toFun - left_inv := fun m ↦ show (f.inv * f.val) m = m by erw [f.inv_val]; simp - right_inv := fun m ↦ show (f.val * f.inv) m = m by erw [f.val_inv]; simp } + left_inv := fun m ↦ show (f.inv * f.val) m = m by rw [f.inv_val]; simp + right_inv := fun m ↦ show (f.val * f.inv) m = m by rw [f.val_inv]; simp } /-- An equivalence from `M` to itself determines an invertible linear map. -/ def ofLinearEquiv (f : M ≃ₗ[R] M) : GeneralLinearGroup R M where diff --git a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean index fb28e11886df5..1a9f732fb0a95 100644 --- a/Mathlib/LinearAlgebra/InvariantBasisNumber.lean +++ b/Mathlib/LinearAlgebra/InvariantBasisNumber.lean @@ -282,7 +282,7 @@ private def induced_map (I : Ideal R) (e : (ι → R) →ₗ[R] ι' → R) : Quotient.liftOn' x (fun y => Ideal.Quotient.mk (I.pi ι') (e y)) (by refine fun a b hab => Ideal.Quotient.eq.2 fun h => ?_ - rw [Submodule.quotientRel_r_def] at hab + rw [Submodule.quotientRel_def] at hab rw [← LinearMap.map_sub] exact Ideal.map_pi _ _ hab e h) diff --git a/Mathlib/LinearAlgebra/Isomorphisms.lean b/Mathlib/LinearAlgebra/Isomorphisms.lean index 7a9bb31cd43fa..54a39b6372052 100644 --- a/Mathlib/LinearAlgebra/Isomorphisms.lean +++ b/Mathlib/LinearAlgebra/Isomorphisms.lean @@ -83,7 +83,7 @@ theorem quotientInfEquivSupQuotient_surjective (p p' : Submodule R M) : rw [← range_eq_top, quotientInfToSupQuotient, range_liftQ, eq_top_iff'] rintro ⟨x, hx⟩; rcases mem_sup.1 hx with ⟨y, hy, z, hz, rfl⟩ use ⟨y, hy⟩; apply (Submodule.Quotient.eq _).2 - simp only [mem_comap, map_sub, coeSubtype, coe_inclusion, sub_add_cancel_left, neg_mem_iff, hz] + simp only [mem_comap, map_sub, coe_subtype, coe_inclusion, sub_add_cancel_left, neg_mem_iff, hz] /-- Second Isomorphism Law : the canonical map from `p/(p ∩ p')` to `(p+p')/p'` as a linear isomorphism. @@ -122,7 +122,7 @@ theorem quotientInfEquivSupQuotient_symm_apply_eq_zero_iff {p p' : Submodule R M (quotientInfEquivSupQuotient p p').symm (Submodule.Quotient.mk x) = 0 ↔ (x : M) ∈ p' := (LinearEquiv.symm_apply_eq _).trans <| by -- porting note (#10745): was `simp`. - rw [_root_.map_zero, Quotient.mk_eq_zero, mem_comap, Submodule.coeSubtype] + rw [_root_.map_zero, Quotient.mk_eq_zero, mem_comap, Submodule.coe_subtype] theorem quotientInfEquivSupQuotient_symm_apply_right (p p' : Submodule R M) {x : ↥(p ⊔ p')} (hx : (x : M) ∈ p') : (quotientInfEquivSupQuotient p p').symm (Submodule.Quotient.mk x) diff --git a/Mathlib/LinearAlgebra/LinearDisjoint.lean b/Mathlib/LinearAlgebra/LinearDisjoint.lean index 3eb097c1e65c0..f290e4e777d86 100644 --- a/Mathlib/LinearAlgebra/LinearDisjoint.lean +++ b/Mathlib/LinearAlgebra/LinearDisjoint.lean @@ -512,7 +512,7 @@ if any two elements of `↥(M ⊓ N)` are commutative, then the rank of `↥(M theorem rank_inf_le_one_of_commute_of_flat (hf : Module.Flat R M ∨ Module.Flat R N) (hc : ∀ (m n : ↥(M ⊓ N)), Commute m.1 n.1) : Module.rank R ↥(M ⊓ N) ≤ 1 := by nontriviality R - refine rank_le fun s h ↦ ?_ + refine _root_.rank_le fun s h ↦ ?_ by_contra hs rw [not_le, ← Fintype.card_coe, Fintype.one_lt_card_iff_nontrivial] at hs obtain ⟨a, b, hab⟩ := hs.exists_pair_ne diff --git a/Mathlib/LinearAlgebra/LinearIndependent.lean b/Mathlib/LinearAlgebra/LinearIndependent.lean index bba76de12bd95..9ce4ca2f473b7 100644 --- a/Mathlib/LinearAlgebra/LinearIndependent.lean +++ b/Mathlib/LinearAlgebra/LinearIndependent.lean @@ -11,7 +11,8 @@ import Mathlib.Tactic.FinCases import Mathlib.Tactic.LinearCombination import Mathlib.Lean.Expr.ExtraRecognizers import Mathlib.Data.Set.Subsingleton -import Mathlib.Tactic.Abel +import Mathlib.Tactic.Module +import Mathlib.Tactic.NoncommRing /-! @@ -591,15 +592,13 @@ theorem LinearIndependent.units_smul {v : ι → M} (hv : LinearIndependent R v) exact (hgs i hi).symm ▸ zero_smul _ _ · rw [← hsum, Finset.sum_congr rfl _] intros - erw [Pi.smul_apply, smul_assoc] - rfl + rw [Pi.smul_apply', smul_assoc, Units.smul_def] lemma LinearIndependent.eq_of_pair {x y : M} (h : LinearIndependent R ![x, y]) {s t s' t' : R} (h' : s • x + t • y = s' • x + t' • y) : s = s' ∧ t = t' := by have : (s - s') • x + (t - t') • y = 0 := by - rw [← sub_eq_zero_of_eq h', ← sub_eq_zero] - simp only [sub_smul] - abel + rw [← sub_eq_zero_of_eq h'] + match_scalars <;> noncomm_ring simpa [sub_eq_zero] using h.eq_zero_of_pair this lemma LinearIndependent.eq_zero_of_pair' {x y : M} (h : LinearIndependent R ![x, y]) @@ -617,8 +616,7 @@ lemma LinearIndependent.linear_combination_pair_of_det_ne_zero {R M : Type*} [Co apply LinearIndependent.pair_iff.2 (fun s t hst ↦ ?_) have H : (s * a + t * c) • x + (s * b + t * d) • y = 0 := by convert hst using 1 - simp only [_root_.add_smul, smul_add, smul_smul] - abel + module have I1 : s * a + t * c = 0 := (h.eq_zero_of_pair H).1 have I2 : s * b + t * d = 0 := (h.eq_zero_of_pair H).2 have J1 : (a * d - b * c) * s = 0 := by linear_combination d * I1 - c * I2 @@ -1112,11 +1110,10 @@ theorem linearIndependent_monoidHom (G : Type*) [Monoid G] (L : Type*) [CommRing rw [Finset.sum_insert has, Finset.sum_insert has] _ = (∑ i ∈ insert a s, g i * i (x * y)) - - ∑ i ∈ insert a s, a x * (g i * i y) := - congr - (congr_arg Sub.sub - (Finset.sum_congr rfl fun i _ => by rw [i.map_mul, mul_assoc])) - (Finset.sum_congr rfl fun _ _ => by rw [mul_assoc, mul_left_comm]) + ∑ i ∈ insert a s, a x * (g i * i y) := by + congrm ∑ i ∈ insert a s, ?_ - ∑ i ∈ insert a s, ?_ + · rw [map_mul, mul_assoc] + · rw [mul_assoc, mul_left_comm] _ = (∑ i ∈ insert a s, (g i • (i : G → L))) (x * y) - a x * (∑ i ∈ insert a s, (g i • (i : G → L))) y := by @@ -1232,7 +1229,7 @@ theorem mem_span_insert_exchange : have a0 : a ≠ 0 := by rintro rfl simp_all - simp [a0, smul_add, smul_smul] + match_scalars <;> simp [a0] theorem linearIndependent_iff_not_mem_span : LinearIndependent K v ↔ ∀ i, v i ∉ span K (v '' (univ \ {i})) := by @@ -1255,7 +1252,7 @@ theorem linearIndependent_option' : LinearIndependent K (fun o => Option.casesOn' o x v : Option ι → V) ↔ LinearIndependent K v ∧ x ∉ Submodule.span K (range v) := by -- Porting note: Explicit universe level is required in `Equiv.optionEquivSumPUnit`. - rw [← linearIndependent_equiv (Equiv.optionEquivSumPUnit.{_, u'} ι).symm, linearIndependent_sum, + rw [← linearIndependent_equiv (Equiv.optionEquivSumPUnit.{u', _} ι).symm, linearIndependent_sum, @range_unique _ PUnit, @linearIndependent_unique_iff PUnit, disjoint_span_singleton] dsimp [(· ∘ ·)] refine ⟨fun h => ⟨h.1, fun hx => h.2.1 <| h.2.2 hx⟩, fun h => ⟨h.1, ?_, fun hx => (h.2 hx).elim⟩⟩ @@ -1306,8 +1303,8 @@ theorem LinearIndependent.pair_iff' {x y : V} (hx : x ≠ 0) : by_cases ht : t = 0 · exact ⟨by simpa [ht, hx] using hst, ht⟩ apply_fun (t⁻¹ • ·) at hst - simp only [smul_add, smul_smul, inv_mul_cancel₀ ht, one_smul, smul_zero] at hst - cases H (-(t⁻¹ * s)) (by rwa [neg_smul, neg_eq_iff_eq_neg, eq_neg_iff_add_eq_zero]) + simp only [smul_add, smul_smul, inv_mul_cancel₀ ht] at hst + cases H (-(t⁻¹ * s)) <| by linear_combination (norm := match_scalars <;> noncomm_ring) -hst theorem linearIndependent_fin_cons {n} {v : Fin n → V} : LinearIndependent K (Fin.cons x v : Fin (n + 1) → V) ↔ @@ -1404,6 +1401,10 @@ theorem LinearIndependent.subset_span_extend (hs : LinearIndependent K (fun x => let ⟨_hbt, _hsb, htb, _hli⟩ := Classical.choose_spec (exists_linearIndependent_extension hs hst) htb +theorem LinearIndependent.span_extend_eq_span (hs : LinearIndependent K (fun x => x : s → V)) + (hst : s ⊆ t) : span K (hs.extend hst) = span K t := + le_antisymm (span_mono (hs.extend_subset hst)) (span_le.2 (hs.subset_span_extend hst)) + theorem LinearIndependent.linearIndependent_extend (hs : LinearIndependent K (fun x => x : s → V)) (hst : s ⊆ t) : LinearIndependent K ((↑) : hs.extend hst → V) := let ⟨_hbt, _hsb, _htb, hli⟩ := Classical.choose_spec (exists_linearIndependent_extension hs hst) diff --git a/Mathlib/LinearAlgebra/Matrix/Adjugate.lean b/Mathlib/LinearAlgebra/Matrix/Adjugate.lean index b814a9748abac..ef3a1b2ec6823 100644 --- a/Mathlib/LinearAlgebra/Matrix/Adjugate.lean +++ b/Mathlib/LinearAlgebra/Matrix/Adjugate.lean @@ -256,7 +256,7 @@ theorem cramer_eq_adjugate_mulVec (A : Matrix n n α) (b : n → α) : theorem mul_adjugate_apply (A : Matrix n n α) (i j k) : A i k * adjugate A k j = cramer Aᵀ (Pi.single k (A i k)) j := by - erw [← smul_eq_mul, adjugate, of_apply, ← Pi.smul_apply, ← LinearMap.map_smul, ← Pi.single_smul', + rw [← smul_eq_mul, adjugate, of_apply, ← Pi.smul_apply, ← LinearMap.map_smul, ← Pi.single_smul', smul_eq_mul, mul_one] theorem mul_adjugate (A : Matrix n n α) : A * adjugate A = A.det • (1 : Matrix n n α) := by @@ -495,8 +495,8 @@ theorem adjugate_adjugate (A : Matrix n n α) (h : Fintype.card n ≠ 1) : let A' := mvPolynomialX n n ℤ suffices adjugate (adjugate A') = det A' ^ (Fintype.card n - 2) • A' by rw [← mvPolynomialX_mapMatrix_aeval ℤ A, ← AlgHom.map_adjugate, ← AlgHom.map_adjugate, this, - ← AlgHom.map_det, ← map_pow (MvPolynomial.aeval _), AlgHom.mapMatrix_apply, - AlgHom.mapMatrix_apply, Matrix.map_smul' _ _ _ (_root_.map_mul _)] + ← AlgHom.map_det, ← map_pow (MvPolynomial.aeval fun p : n × n ↦ A p.1 p.2), + AlgHom.mapMatrix_apply, AlgHom.mapMatrix_apply, Matrix.map_smul' _ _ _ (_root_.map_mul _)] have h_card' : Fintype.card n - 2 + 1 = Fintype.card n - 1 := by simp [h_card] have is_reg : IsSMulRegular (MvPolynomial (n × n) ℤ) (det A') := fun x y => mul_left_cancel₀ (det_mvPolynomialX_ne_zero n ℤ) diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean index cc04b3b64ac37..4a0d9f53997f4 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Coeff.lean @@ -204,7 +204,7 @@ lemma derivative_det_one_add_X_smul_aux {n} (M : Matrix (Fin n) (Fin n) R) : rw [det_eq_zero_of_column_eq_zero 0, eval_zero, mul_zero] intro j rw [submatrix_apply, Fin.succAbove_of_castSucc_lt, one_apply_ne] - · exact (bne_iff_ne (Fin.succ j) (Fin.castSucc 0)).mp rfl + · exact (bne_iff_ne (a := Fin.succ j) (b := Fin.castSucc 0)).mp rfl · rw [Fin.castSucc_zero]; exact lt_of_le_of_ne (Fin.zero_le _) hi.symm · exact fun H ↦ (H <| Finset.mem_univ _).elim diff --git a/Mathlib/LinearAlgebra/Matrix/Charpoly/Eigs.lean b/Mathlib/LinearAlgebra/Matrix/Charpoly/Eigs.lean index ccd5c26310966..4eb330442505f 100644 --- a/Mathlib/LinearAlgebra/Matrix/Charpoly/Eigs.lean +++ b/Mathlib/LinearAlgebra/Matrix/Charpoly/Eigs.lean @@ -58,7 +58,7 @@ namespace Matrix theorem det_eq_prod_roots_charpoly_of_splits (hAps : A.charpoly.Splits (RingHom.id R)) : A.det = (Matrix.charpoly A).roots.prod := by rw [det_eq_sign_charpoly_coeff, ← charpoly_natDegree_eq_dim A, - Polynomial.prod_roots_eq_coeff_zero_of_monic_of_split A.charpoly_monic hAps, ← mul_assoc, + Polynomial.prod_roots_eq_coeff_zero_of_monic_of_splits A.charpoly_monic hAps, ← mul_assoc, ← pow_two, pow_right_comm, neg_one_sq, one_pow, one_mul] theorem trace_eq_sum_roots_charpoly_of_splits (hAps : A.charpoly.Splits (RingHom.id R)) : diff --git a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean index f29c7888f644b..c33327a8858ae 100644 --- a/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean +++ b/Mathlib/LinearAlgebra/Matrix/Determinant/Basic.lean @@ -183,14 +183,14 @@ theorem det_mul_left_comm (M N P : Matrix m m R) : det (M * (N * P)) = det (N * theorem det_mul_right_comm (M N P : Matrix m m R) : det (M * N * P) = det (M * P * N) := by rw [Matrix.mul_assoc, Matrix.mul_assoc, det_mul, det_mul_comm N P, ← det_mul] --- TODO(mathlib4#6607): fix elaboration so that the ascription isn't needed +-- TODO(mathlib4#6607): fix elaboration so `val` isn't needed theorem det_units_conj (M : (Matrix m m R)ˣ) (N : Matrix m m R) : - det ((M : Matrix _ _ _) * N * (↑M⁻¹ : Matrix _ _ _)) = det N := by + det (M.val * N * M⁻¹.val) = det N := by rw [det_mul_right_comm, Units.mul_inv, one_mul] --- TODO(mathlib4#6607): fix elaboration so that the ascription isn't needed +-- TODO(mathlib4#6607): fix elaboration so `val` isn't needed theorem det_units_conj' (M : (Matrix m m R)ˣ) (N : Matrix m m R) : - det ((↑M⁻¹ : Matrix _ _ _) * N * (↑M : Matrix _ _ _)) = det N := + det (M⁻¹.val * N * ↑M.val) = det N := det_units_conj M⁻¹ N /-- Transposing a matrix preserves the determinant. -/ @@ -747,7 +747,7 @@ theorem det_fin_one_of (a : R) : det !![a] = a := theorem det_fin_two (A : Matrix (Fin 2) (Fin 2) R) : det A = A 0 0 * A 1 1 - A 0 1 * A 1 0 := by simp only [det_succ_row_zero, det_unique, Fin.default_eq_zero, submatrix_apply, Fin.succ_zero_eq_one, Fin.sum_univ_succ, Fin.val_zero, Fin.zero_succAbove, univ_unique, - Fin.val_succ, Fin.coe_fin_one, Fin.succ_succAbove_zero, sum_singleton] + Fin.val_succ, Fin.val_eq_zero, Fin.succ_succAbove_zero, sum_singleton] ring @[simp] @@ -763,7 +763,7 @@ theorem det_fin_three (A : Matrix (Fin 3) (Fin 3) R) : simp only [det_succ_row_zero, ← Nat.not_even_iff_odd, submatrix_apply, Fin.succ_zero_eq_one, submatrix_submatrix, det_unique, Fin.default_eq_zero, comp_apply, Fin.succ_one_eq_two, Fin.sum_univ_succ, Fin.val_zero, Fin.zero_succAbove, univ_unique, Fin.val_succ, - Fin.coe_fin_one, Fin.succ_succAbove_zero, sum_singleton, Fin.succ_succAbove_one, even_add_self] + Fin.val_eq_zero, Fin.succ_succAbove_zero, sum_singleton, Fin.succ_succAbove_one, even_add_self] ring end Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean index 8d2b791e900da..d7867798bc310 100644 --- a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean +++ b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Card.lean @@ -27,7 +27,7 @@ variable {K V : Type*} [DivisionRing K] [AddCommGroup V] [Module K V] variable [Fintype K] [Finite V] local notation "q" => Fintype.card K -local notation "n" => FiniteDimensional.finrank K V +local notation "n" => Module.finrank K V attribute [local instance] Fintype.ofFinite in open Fintype in @@ -86,8 +86,8 @@ theorem card_GL_field : rcases Nat.eq_zero_or_pos n with rfl | hn · simp [Nat.card_eq_fintype_card] · rw [Nat.card_congr (equiv_GL_linearindependent n hn), card_linearIndependent, - FiniteDimensional.finrank_fintype_fun_eq_card, Fintype.card_fin] - simp only [FiniteDimensional.finrank_fintype_fun_eq_card, Fintype.card_fin, le_refl] + Module.finrank_fintype_fun_eq_card, Fintype.card_fin] + simp only [Module.finrank_fintype_fun_eq_card, Fintype.card_fin, le_refl] end field diff --git a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean index 50c1c2dfc8bb0..5ae49bf1b77c9 100644 --- a/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean +++ b/Mathlib/LinearAlgebra/Matrix/GeneralLinearGroup/Defs.lean @@ -137,6 +137,10 @@ def map (f : R →+* S) : GL n R →* GL n S := Units.map <| (RingHom.mapMatrix theorem map_id : map (RingHom.id R) = MonoidHom.id (GL n R) := rfl +@[simp] +protected lemma map_apply (f : R →+* S) (i j : n) (g : GL n R) : map f g i j = f (g i j) := by + rfl + @[simp] theorem map_comp (f : T →+* R) (g : R →+* S) : map (g.comp f) = (map g).comp (map (n := n) f) := @@ -147,6 +151,44 @@ theorem map_comp_apply (f : T →+* R) (g : R →+* S) (x : GL n T) : (map g).comp (map f) x = map g (map f x) := rfl +variable (f : R →+* S) + +@[simp] +protected lemma map_one : map f (1 : GL n R) = 1 := by + ext + simp only [_root_.map_one, Units.val_one] + +protected lemma map_mul (g h : GL n R) : map f (g * h) = map f g * map f h := by + ext + simp only [_root_.map_mul, Units.val_mul] + +protected lemma map_inv (g : GL n R) : map f g⁻¹ = (map f g)⁻¹ := by + ext + simp only [_root_.map_inv, coe_units_inv] + +protected lemma map_det (g : GL n R) : Matrix.GeneralLinearGroup.det (map f g) = + Units.map f (Matrix.GeneralLinearGroup.det g) := by + ext + simp only [map, RingHom.mapMatrix_apply, Units.inv_eq_val_inv, Matrix.coe_units_inv, + Matrix.GeneralLinearGroup.val_det_apply, Units.coe_map, MonoidHom.coe_coe] + exact Eq.symm (RingHom.map_det f g.1) + +lemma map_mul_map_inv (g : GL n R) : map f g * map f g⁻¹ = 1 := by + simp only [map_inv, mul_inv_cancel] + +lemma map_inv_mul_map (g : GL n R) : map f g⁻¹ * map f g = 1 := by + simp only [map_inv, inv_mul_cancel] + +@[simp] +lemma coe_map_mul_map_inv (g : GL n R) : g.val.map f * g.val⁻¹.map f = 1 := by + rw [← Matrix.map_mul] + simp only [isUnits_det_units, mul_nonsing_inv, map_zero, _root_.map_one, Matrix.map_one] + +@[simp] +lemma coe_map_inv_mul_map (g : GL n R) : g.val⁻¹.map f * g.val.map f = 1 := by + rw [← Matrix.map_mul] + simp only [isUnits_det_units, nonsing_inv_mul, map_zero, _root_.map_one, Matrix.map_one] + end GeneralLinearGroup namespace SpecialLinearGroup diff --git a/Mathlib/LinearAlgebra/Matrix/Gershgorin.lean b/Mathlib/LinearAlgebra/Matrix/Gershgorin.lean index e6dd7b5af91ea..06f6a65c35c43 100644 --- a/Mathlib/LinearAlgebra/Matrix/Gershgorin.lean +++ b/Mathlib/LinearAlgebra/Matrix/Gershgorin.lean @@ -37,7 +37,7 @@ theorem eigenvalue_mem_ball {μ : K} (hμ : Module.End.HasEigenvalue (Matrix.toL refine (h_i ▸ Finset.le_sup' (fun i => ‖v i‖) (Finset.mem_univ j)).trans ?_ exact norm_le_zero_iff.mpr h_nz have h_le : ∀ j, ‖v j * (v i)⁻¹‖ ≤ 1 := fun j => by - rw [norm_mul, norm_inv, mul_inv_le_iff' (norm_pos_iff.mpr h_nz), one_mul] + rw [norm_mul, norm_inv, mul_inv_le_iff₀ (norm_pos_iff.mpr h_nz), one_mul] exact h_i ▸ Finset.le_sup' (fun i => ‖v i‖) (Finset.mem_univ j) simp_rw [mem_closedBall_iff_norm'] refine ⟨i, ?_⟩ diff --git a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean index 336209008ab7e..ff884d2e289ad 100644 --- a/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean +++ b/Mathlib/LinearAlgebra/Matrix/HermitianFunctionalCalculus.lean @@ -7,7 +7,7 @@ Authors: Jon Bannon, Jireh Loreaux import Mathlib.LinearAlgebra.Matrix.Spectrum import Mathlib.LinearAlgebra.Eigenspace.Matrix import Mathlib.Analysis.CStarAlgebra.ContinuousFunctionalCalculus.Unique -import Mathlib.Topology.ContinuousFunction.Units +import Mathlib.Topology.ContinuousMap.Units /-! # Continuous Functional Calculus for Hermitian Matrices diff --git a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean index e91010d1bc343..41e80c3f6b369 100644 --- a/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean +++ b/Mathlib/LinearAlgebra/Matrix/NonsingularInverse.lean @@ -175,6 +175,20 @@ theorem det_ne_zero_of_right_inverse [Nontrivial α] (h : A * B = 1) : A.det ≠ end Invertible + +section + +variable [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n] [CommRing α] + +/-- A version of `mul_eq_one_comm` that works for square matrices with rectangular types. -/ +theorem mul_eq_one_comm_of_equiv {A : Matrix m n α} {B : Matrix n m α} (e : m ≃ n) : + A * B = 1 ↔ B * A = 1 := by + refine (reindex e e).injective.eq_iff.symm.trans ?_ + rw [reindex_apply, reindex_apply, submatrix_one_equiv, ← submatrix_mul_equiv _ _ _ (.refl _), + mul_eq_one_comm, submatrix_mul_equiv, coe_refl, submatrix_id_id] + +end + section Inv variable [Fintype n] [DecidableEq n] [CommRing α] @@ -456,6 +470,10 @@ theorem nonsing_inv_nonsing_inv (h : IsUnit A.det) : A⁻¹⁻¹ = A := theorem isUnit_nonsing_inv_det_iff {A : Matrix n n α} : IsUnit A⁻¹.det ↔ IsUnit A.det := by rw [Matrix.det_nonsing_inv, isUnit_ring_inverse] +@[simp] +theorem isUnit_nonsing_inv_iff {A : Matrix n n α} : IsUnit A⁻¹ ↔ IsUnit A := by + simp_rw [isUnit_iff_isUnit_det, isUnit_nonsing_inv_det_iff] + -- `IsUnit.invertible` lifts the proposition `IsUnit A` to a constructive inverse of `A`. /-- A version of `Matrix.invertibleOfDetInvertible` with the inverse defeq to `A⁻¹` that is therefore noncomputable. -/ @@ -593,6 +611,42 @@ theorem inv_diagonal (v : n → α) : (diagonal v)⁻¹ = diagonal (Ring.inverse end Diagonal +/-- The inverse of a 1×1 or 0×0 matrix is always diagonal. + +While we could write this as `of fun _ _ => Ring.inverse (A default default)` on the RHS, this is +less useful because: + +* It wouldn't work for 0×0 matrices. +* More things are true about diagonal matrices than constant matrices, and so more lemmas exist. + +`Matrix.diagonal_unique` can be used to reach this form, while `Ring.inverse_eq_inv` can be used +to replace `Ring.inverse` with `⁻¹`. +-/ +@[simp] +theorem inv_subsingleton [Subsingleton m] [Fintype m] [DecidableEq m] (A : Matrix m m α) : + A⁻¹ = diagonal fun i => Ring.inverse (A i i) := by + rw [inv_def, adjugate_subsingleton, smul_one_eq_diagonal] + congr! with i + exact det_eq_elem_of_subsingleton _ _ + +section Woodbury + +variable [Fintype m] [DecidableEq m] +variable (A : Matrix n n α) (U : Matrix n m α) (C : Matrix m m α) (V : Matrix m n α) + +/-- The **Woodbury Identity** (`⁻¹` version). -/ +theorem add_mul_mul_inv_eq_sub (hA : IsUnit A) (hC : IsUnit C) (hAC : IsUnit (C⁻¹ + V * A⁻¹ * U)) : + (A + U * C * V)⁻¹ = A⁻¹ - A⁻¹ * U * (C⁻¹ + V * A⁻¹ * U)⁻¹ * V * A⁻¹ := by + obtain ⟨_⟩ := hA.nonempty_invertible + obtain ⟨_⟩ := hC.nonempty_invertible + obtain ⟨iAC⟩ := hAC.nonempty_invertible + simp only [← invOf_eq_nonsing_inv] at iAC + letI := invertibleAddMulMul A U C V + simp only [← invOf_eq_nonsing_inv] + apply invOf_add_mul_mul + +end Woodbury + @[simp] theorem inv_inv_inv (A : Matrix n n α) : A⁻¹⁻¹⁻¹ = A⁻¹ := by by_cases h : IsUnit A.det @@ -722,4 +776,21 @@ theorem det_conj' {M : Matrix m m α} (h : IsUnit M) (N : Matrix m m α) : end Det +/-! ### More results about traces -/ + + +section trace + +variable [Fintype m] [DecidableEq m] + +/-- A variant of `Matrix.trace_units_conj`. -/ +theorem trace_conj {M : Matrix m m α} (h : IsUnit M) (N : Matrix m m α) : + trace (M * N * M⁻¹) = trace N := by rw [← h.unit_spec, ← coe_units_inv, trace_units_conj] + +/-- A variant of `Matrix.trace_units_conj'`. -/ +theorem trace_conj' {M : Matrix m m α} (h : IsUnit M) (N : Matrix m m α) : + trace (M⁻¹ * N * M) = trace N := by rw [← h.unit_spec, ← coe_units_inv, trace_units_conj'] + +end trace + end Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/PosDef.lean b/Mathlib/LinearAlgebra/Matrix/PosDef.lean index 941af97a89e99..9343bc8070623 100644 --- a/Mathlib/LinearAlgebra/Matrix/PosDef.lean +++ b/Mathlib/LinearAlgebra/Matrix/PosDef.lean @@ -450,6 +450,25 @@ theorem det_pos [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) : 0 < det intro i _ simpa using hM.eigenvalues_pos i +theorem isUnit [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) : IsUnit M := + isUnit_iff_isUnit_det _ |>.2 <| hM.det_pos.ne'.isUnit + +protected theorem inv [DecidableEq n] {M : Matrix n n 𝕜} (hM : M.PosDef) : M⁻¹.PosDef := by + refine ⟨hM.isHermitian.inv, fun x hx => ?_⟩ + have := hM.2 (M⁻¹ *ᵥ x) ((Matrix.mulVec_injective_iff_isUnit.mpr ?_ |>.ne_iff' ?_).2 hx) + · let _inst := hM.isUnit.invertible + rwa [star_mulVec, mulVec_mulVec, Matrix.mul_inv_of_invertible, one_mulVec, + ← star_pos_iff, ← star_mulVec, ← star_dotProduct] at this + · simpa using hM.isUnit + · simp + +@[simp] +theorem _root_.Matrix.posDef_inv_iff [DecidableEq n] {M : Matrix n n 𝕜} : + M⁻¹.PosDef ↔ M.PosDef := + ⟨fun h => + letI := (Matrix.isUnit_nonsing_inv_iff.1 <| h.isUnit).invertible + Matrix.inv_inv_of_invertible M ▸ h.inv, (·.inv)⟩ + end PosDef end Matrix diff --git a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean index 13e2bba24b39b..8e620f838f3f0 100644 --- a/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean +++ b/Mathlib/LinearAlgebra/Matrix/SesquilinearForm.lean @@ -559,8 +559,7 @@ theorem Matrix.isAdjointPair_equiv (P : Matrix n n R) (h : IsUnit P) : let v := Pᵀ.nonsingInvUnit (P.isUnit_det_transpose h') let x := A₁ᵀ * Pᵀ * J 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 + suffices x * u = v * y ↔ v⁻¹ * x = y * u⁻¹ by dsimp only [Matrix.IsAdjointPair] simp only [Matrix.transpose_mul] simp only [← mul_assoc, P.transpose_nonsing_inv] diff --git a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean index abb3fa721cfad..261b976d62a38 100644 --- a/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean +++ b/Mathlib/LinearAlgebra/Matrix/SpecialLinearGroup.lean @@ -124,6 +124,9 @@ instance : Pow (SpecialLinearGroup n R) ℕ where instance : Inhabited (SpecialLinearGroup n R) := ⟨1⟩ +instance [Fintype R] [DecidableEq R] : Fintype (SpecialLinearGroup n R) := Subtype.fintype _ +instance [Finite R] : Finite (SpecialLinearGroup n R) := Subtype.finite + /-- 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⟩ diff --git a/Mathlib/LinearAlgebra/Matrix/Trace.lean b/Mathlib/LinearAlgebra/Matrix/Trace.lean index fbc571b846cfc..40da0be3f44c0 100644 --- a/Mathlib/LinearAlgebra/Matrix/Trace.lean +++ b/Mathlib/LinearAlgebra/Matrix/Trace.lean @@ -175,6 +175,23 @@ lemma trace_submatrix_succ {n : ℕ} [NonUnitalNonAssocSemiring R] rw [← (finSuccEquiv n).symm.sum_comp] simp +section CommSemiring + +variable [DecidableEq m] [CommSemiring R] + +-- TODO(mathlib4#6607): fix elaboration so that the ascription isn't needed +theorem trace_units_conj (M : (Matrix m m R)ˣ) (N : Matrix m m R) : + trace ((M : Matrix _ _ _) * N * (↑M⁻¹ : Matrix _ _ _)) = trace N := by + rw [trace_mul_cycle, Units.inv_mul, one_mul] + +set_option linter.docPrime false in +-- TODO(mathlib4#6607): fix elaboration so that the ascription isn't needed +theorem trace_units_conj' (M : (Matrix m m R)ˣ) (N : Matrix m m R) : + trace ((↑M⁻¹ : Matrix _ _ _) * N * (↑M : Matrix _ _ _)) = trace N := + trace_units_conj M⁻¹ N + +end CommSemiring + section Fin variable [AddCommMonoid R] diff --git a/Mathlib/LinearAlgebra/Multilinear/Basic.lean b/Mathlib/LinearAlgebra/Multilinear/Basic.lean index dbc2bea4ba67f..25022902c14a5 100644 --- a/Mathlib/LinearAlgebra/Multilinear/Basic.lean +++ b/Mathlib/LinearAlgebra/Multilinear/Basic.lean @@ -109,7 +109,7 @@ variable [Semiring R] [∀ i, AddCommMonoid (M i)] [∀ i, AddCommMonoid (M₁ i -- Porting note: Replaced CoeFun with FunLike instance 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 + coe_injective' f g h := by cases f; cases g; cases h; rfl initialize_simps_projections MultilinearMap (toFun → apply) @@ -453,14 +453,9 @@ theorem map_sum_finset_aux [DecidableEq ι] [Fintype ι] {n : ℕ} (h : (∑ i, induction' n using Nat.strong_induction_on with n IH generalizing A -- If one of the sets is empty, then all the sums are zero by_cases Ai_empty : ∃ i, A i = ∅ - · rcases Ai_empty with ⟨i, hi⟩ - have : ∑ j ∈ A i, g i j = 0 := by rw [hi, Finset.sum_empty] - rw [f.map_coord_zero i this] - have : piFinset A = ∅ := by - refine Finset.eq_empty_of_forall_not_mem fun r hr => ?_ - have : r i ∈ A i := mem_piFinset.mp hr i - simp [hi] at this - rw [this, Finset.sum_empty] + · obtain ⟨i, hi⟩ : ∃ i, ∑ j ∈ A i, g i j = 0 := Ai_empty.imp fun i hi ↦ by simp [hi] + have hpi : piFinset A = ∅ := by simpa + rw [f.map_coord_zero i hi, hpi, Finset.sum_empty] push_neg at Ai_empty -- Otherwise, if all sets are at most singletons, then they are exactly singletons and the result -- is again straightforward diff --git a/Mathlib/LinearAlgebra/Orientation.lean b/Mathlib/LinearAlgebra/Orientation.lean index 68891b346f5df..549ff52629c7b 100644 --- a/Mathlib/LinearAlgebra/Orientation.lean +++ b/Mathlib/LinearAlgebra/Orientation.lean @@ -326,7 +326,7 @@ namespace Orientation variable [Fintype ι] -open FiniteDimensional +open FiniteDimensional Module /-- If the index type has cardinality equal to the finite dimension, any two orientations are equal or negations. -/ diff --git a/Mathlib/LinearAlgebra/PerfectPairing.lean b/Mathlib/LinearAlgebra/PerfectPairing.lean index d5e2dd945411b..dfec7b49779cd 100644 --- a/Mathlib/LinearAlgebra/PerfectPairing.lean +++ b/Mathlib/LinearAlgebra/PerfectPairing.lean @@ -34,7 +34,7 @@ open Function Module variable (R M N : Type*) [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] /-- A perfect pairing of two (left) modules over a commutative ring. -/ -structure PerfectPairing := +structure PerfectPairing where toLin : M →ₗ[R] N →ₗ[R] R bijectiveLeft : Bijective toLin bijectiveRight : Bijective toLin.flip diff --git a/Mathlib/LinearAlgebra/PiTensorProduct.lean b/Mathlib/LinearAlgebra/PiTensorProduct.lean index acdc671ceb60a..79f7de870e7fd 100644 --- a/Mathlib/LinearAlgebra/PiTensorProduct.lean +++ b/Mathlib/LinearAlgebra/PiTensorProduct.lean @@ -411,7 +411,7 @@ theorem liftAux_tprod (φ : MultilinearMap R s E) (f : Π i, s i) : liftAux φ ( -- show _ • _ = _ -- rw [one_smul] erw [AddCon.lift_coe] - erw [FreeAddMonoid.of] + rw [FreeAddMonoid.of] dsimp [FreeAddMonoid.ofList] rw [← one_smul R (φ f)] erw [Equiv.refl_apply] diff --git a/Mathlib/LinearAlgebra/Prod.lean b/Mathlib/LinearAlgebra/Prod.lean index fb36914029e72..5c0e7970a2362 100644 --- a/Mathlib/LinearAlgebra/Prod.lean +++ b/Mathlib/LinearAlgebra/Prod.lean @@ -863,7 +863,7 @@ theorem tailing_disjoint_tunnel_succ (f : M × N →ₗ[R] M) (i : Injective f) Disjoint (tailing f i n) (OrderDual.ofDual (α := Submodule R M) <| tunnel f i (n + 1)) := by rw [disjoint_iff] dsimp [tailing, tunnel, tunnel'] - erw [Submodule.map_inf_eq_map_inf_comap, + rw [Submodule.map_inf_eq_map_inf_comap, Submodule.comap_map_eq_of_injective (tunnelAux_injective _ i _), inf_comm, Submodule.fst_inf_snd, Submodule.map_bot] @@ -872,7 +872,7 @@ theorem tailing_sup_tunnel_succ_le_tunnel (f : M × N →ₗ[R] M) (i : Injectiv tailing f i n ⊔ (OrderDual.ofDual (α := Submodule R M) <| tunnel f i (n + 1)) ≤ (OrderDual.ofDual (α := Submodule R M) <| 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] + rw [← Submodule.map_sup, sup_comm, Submodule.fst_sup_snd, Submodule.map_comp, Submodule.map_comp] apply Submodule.map_subtype_le /-- The supremum of all the copies of `N` found inside the tunnel. -/ diff --git a/Mathlib/LinearAlgebra/Projection.lean b/Mathlib/LinearAlgebra/Projection.lean index e730906ab556c..da597346dcca3 100644 --- a/Mathlib/LinearAlgebra/Projection.lean +++ b/Mathlib/LinearAlgebra/Projection.lean @@ -40,7 +40,7 @@ theorem ker_id_sub_eq_of_proj {f : E →ₗ[R] p} (hf : ∀ x : p, f x = x) : ker (id - p.subtype.comp f) = p := by ext x simp only [comp_apply, mem_ker, subtype_apply, sub_apply, id_apply, sub_eq_zero] - exact ⟨fun h => h.symm ▸ Submodule.coe_mem _, fun hx => by erw [hf ⟨x, hx⟩, Subtype.coe_mk]⟩ + exact ⟨fun h => h.symm ▸ Submodule.coe_mem _, fun hx => by rw [hf ⟨x, hx⟩, Subtype.coe_mk]⟩ theorem range_eq_of_proj {f : E →ₗ[R] p} (hf : ∀ x : p, f x = x) : range f = ⊤ := range_eq_top.2 fun x => ⟨x, hf x⟩ @@ -49,7 +49,7 @@ theorem isCompl_of_proj {f : E →ₗ[R] p} (hf : ∀ x : p, f x = x) : IsCompl constructor · rw [disjoint_iff_inf_le] rintro x ⟨hpx, hfx⟩ - erw [SetLike.mem_coe, mem_ker, hf ⟨x, hpx⟩, mk_eq_zero] at hfx + rw [SetLike.mem_coe, mem_ker, hf ⟨x, hpx⟩, mk_eq_zero] at hfx simp only [hfx, SetLike.mem_coe, zero_mem] · rw [codisjoint_iff_le_sup] intro x _ @@ -393,10 +393,10 @@ theorem eq_conj_prod_map' {f : E →ₗ[R] E} (h : IsProj p f) : prodMap id 0 ∘ₗ (p.prodEquivOfIsCompl (ker f) h.isCompl).symm.toLinearMap := by rw [← LinearMap.comp_assoc, LinearEquiv.eq_comp_toLinearMap_symm] ext x - · simp only [coe_prodEquivOfIsCompl, comp_apply, coe_inl, coprod_apply, coeSubtype, + · simp only [coe_prodEquivOfIsCompl, comp_apply, coe_inl, coprod_apply, coe_subtype, _root_.map_zero, add_zero, h.map_id x x.2, prodMap_apply, id_apply] · simp only [coe_prodEquivOfIsCompl, comp_apply, coe_inr, coprod_apply, _root_.map_zero, - coeSubtype, zero_add, map_coe_ker, prodMap_apply, zero_apply, add_zero] + coe_subtype, zero_add, map_coe_ker, prodMap_apply, zero_apply, add_zero] end IsProj diff --git a/Mathlib/LinearAlgebra/Projectivization/Basic.lean b/Mathlib/LinearAlgebra/Projectivization/Basic.lean index fd5d3d6aa6db7..94d4e7925bb43 100644 --- a/Mathlib/LinearAlgebra/Projectivization/Basic.lean +++ b/Mathlib/LinearAlgebra/Projectivization/Basic.lean @@ -78,7 +78,7 @@ theorem rep_nonzero (v : ℙ K V) : v.rep ≠ 0 := @[simp] theorem mk_rep (v : ℙ K V) : mk K v.rep v.rep_nonzero = v := Quotient.out_eq' _ -open FiniteDimensional +open Module /-- Consider an element of the projectivization as a submodule of `V`. -/ protected def submodule (v : ℙ K V) : Submodule K V := diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean index caedda89e57e7..fe2fe2b66dfe2 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Basic.lean @@ -854,15 +854,15 @@ theorem associated_toQuadraticMap (B : BilinMap R M R) (x y : M) : theorem associated_left_inverse (h : B₁.IsSymm) : associatedHom S B₁.toQuadraticMap = B₁ := LinearMap.ext₂ fun x y => by - rw [associated_toQuadraticMap, ← h.eq x y, RingHom.id_apply, ← two_mul, ← smul_mul_assoc, - smul_eq_mul, invOf_mul_self, one_mul] + rw [associated_toQuadraticMap, ← h.eq x y, RingHom.id_apply] + match_scalars + linear_combination invOf_mul_self' (2:R) -- Porting note: moved from below to golf the next theorem theorem associated_eq_self_apply (x : M) : associatedHom S Q x x = Q x := by - rw [associated_apply, map_add_self, ← three_add_one_eq_four, ← two_add_one_eq_three, add_smul, - add_smul, one_smul, add_sub_cancel_right, add_sub_cancel_right, two_smul, ← two_smul R, - ← smul_assoc] - simp only [smul_eq_mul, invOf_mul_self', one_smul] + rw [associated_apply, map_add_self] + match_scalars + linear_combination invOf_mul_self' (2:R) theorem toQuadraticMap_associated : (associatedHom S Q).toQuadraticMap = Q := QuadraticMap.ext <| associated_eq_self_apply S Q @@ -1180,7 +1180,7 @@ theorem exists_bilinForm_self_ne_zero [htwo : Invertible (2 : R)] {B : BilinForm obtain ⟨x, hx⟩ := QuadraticMap.exists_quadraticForm_ne_zero hB₁ exact ⟨x, fun h => hx (Q.associated_eq_self_apply ℕ x ▸ h)⟩ -open FiniteDimensional +open Module variable {V : Type u} {K : Type v} [Field K] [AddCommGroup V] [Module K V] variable [FiniteDimensional K V] @@ -1194,7 +1194,7 @@ theorem exists_orthogonal_basis [hK : Invertible (2 : K)] {B : LinearMap.BilinFo haveI := finrank_pos_iff.1 (hd.symm ▸ Nat.succ_pos d : 0 < finrank K V) -- either the bilinear form is trivial or we can pick a non-null `x` obtain rfl | hB₁ := eq_or_ne B 0 - · let b := FiniteDimensional.finBasis K V + · let b := Module.finBasis K V rw [hd] at b exact ⟨b, fun i j _ => rfl⟩ obtain ⟨x, hx⟩ := exists_bilinForm_self_ne_zero hB₁ hB₂ @@ -1288,8 +1288,7 @@ theorem basisRepr_eq_of_iIsOrtho {R M} [CommRing R] [AddCommGroup M] [Module R M smul_eq_mul, smul_eq_mul] ring_nf · intro i _ hij - rw [LinearMap.map_smul, LinearMap.map_smul₂, - show associatedHom R Q (v i) (v j) = 0 from hv₂ hij, smul_eq_mul, smul_eq_mul, - mul_zero, mul_zero] + rw [LinearMap.map_smul, LinearMap.map_smul₂, hv₂ hij] + module end QuadraticMap diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Complex.lean b/Mathlib/LinearAlgebra/QuadraticForm/Complex.lean index 3285feacba1f0..a8c98d7d5b6cf 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Complex.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Complex.lean @@ -35,7 +35,7 @@ noncomputable def isometryEquivSumSquares (w' : ι → ℂ) : convert QuadraticMap.isometryEquivBasisRepr (weightedSumSquares ℂ w') ((Pi.basisFun ℂ ι).unitsSMul fun i => (isUnit_iff_ne_zero.2 <| hw' i).unit) ext1 v - erw [basisRepr_apply, weightedSumSquares_apply, weightedSumSquares_apply] + rw [basisRepr_apply, weightedSumSquares_apply, weightedSumSquares_apply] refine sum_congr rfl fun j hj => ?_ have hsum : (∑ i : ι, v i • ((isUnit_iff_ne_zero.2 <| hw' i).unit : ℂ) • (Pi.basisFun ℂ ι) i) j = v j • w j ^ (-(1 / 2 : ℂ)) := by @@ -70,7 +70,7 @@ noncomputable def isometryEquivSumSquaresUnits (w : ι → Units ℂ) : the sum of squares, i.e. `weightedSumSquares` with weight `fun (i : ι) => 1`. -/ theorem equivalent_sum_squares {M : Type*} [AddCommGroup M] [Module ℂ M] [FiniteDimensional ℂ M] (Q : QuadraticForm ℂ M) (hQ : (associated (R := ℂ) Q).SeparatingLeft) : - Equivalent Q (weightedSumSquares ℂ (1 : Fin (FiniteDimensional.finrank ℂ M) → ℂ)) := + Equivalent Q (weightedSumSquares ℂ (1 : Fin (Module.finrank ℂ M) → ℂ)) := let ⟨w, ⟨hw₁⟩⟩ := Q.equivalent_weightedSumSquares_units_of_nondegenerate' hQ ⟨hw₁.trans (isometryEquivSumSquaresUnits w)⟩ diff --git a/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean b/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean index ff5c68946f2d8..567af287573fc 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/IsometryEquiv.lean @@ -141,7 +141,7 @@ variable [Field K] [Invertible (2 : K)] [AddCommGroup V] [Module K V] /-- Given an orthogonal basis, a quadratic form is isometrically equivalent with a weighted sum of squares. -/ noncomputable def isometryEquivWeightedSumSquares (Q : QuadraticForm K V) - (v : Basis (Fin (FiniteDimensional.finrank K V)) K V) + (v : Basis (Fin (Module.finrank K V)) K V) (hv₁ : (associated (R := K) Q).IsOrthoᵢ v) : Q.IsometryEquiv (weightedSumSquares K fun i => Q (v i)) := by let iso := Q.isometryEquivBasisRepr v @@ -154,13 +154,13 @@ variable [FiniteDimensional K V] open LinearMap.BilinForm theorem equivalent_weightedSumSquares (Q : QuadraticForm K V) : - ∃ w : Fin (FiniteDimensional.finrank K V) → K, Equivalent Q (weightedSumSquares K w) := + ∃ w : Fin (Module.finrank K V) → K, Equivalent Q (weightedSumSquares K w) := let ⟨v, hv₁⟩ := exists_orthogonal_basis (associated_isSymm _ Q) ⟨_, ⟨Q.isometryEquivWeightedSumSquares v hv₁⟩⟩ theorem equivalent_weightedSumSquares_units_of_nondegenerate' (Q : QuadraticForm K V) (hQ : (associated (R := K) Q).SeparatingLeft) : - ∃ w : Fin (FiniteDimensional.finrank K V) → Kˣ, Equivalent Q (weightedSumSquares K w) := by + ∃ w : Fin (Module.finrank K V) → Kˣ, Equivalent Q (weightedSumSquares K w) := by obtain ⟨v, hv₁⟩ := exists_orthogonal_basis (associated_isSymm K Q) have hv₂ := hv₁.not_isOrtho_basis_self_of_separatingLeft hQ simp_rw [LinearMap.IsOrtho, associated_eq_self_apply] at hv₂ diff --git a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean index c05f820fefc9c..c0d2eb6ac8a7a 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/QuadraticModuleCat.lean @@ -43,7 +43,7 @@ def of {X : Type v} [AddCommGroup X] [Module R X] (Q : QuadraticForm R X) : /-- A type alias for `QuadraticForm.LinearIsometry` to avoid confusion between the categorical and algebraic spellings of composition. -/ @[ext] -structure Hom (V W : QuadraticModuleCat.{v} R) := +structure Hom (V W : QuadraticModuleCat.{v} R) where /-- The underlying isometry -/ toIsometry : V.form →qᵢ W.form diff --git a/Mathlib/LinearAlgebra/QuadraticForm/Real.lean b/Mathlib/LinearAlgebra/QuadraticForm/Real.lean index 7ec3a6f4947d8..b9fe9bdf90ae3 100644 --- a/Mathlib/LinearAlgebra/QuadraticForm/Real.lean +++ b/Mathlib/LinearAlgebra/QuadraticForm/Real.lean @@ -53,7 +53,7 @@ noncomputable def isometryEquivSignWeightedSumSquares (w : ι → ℝ) : sum of squares with the weights being ±1, `SignType` version. -/ theorem equivalent_sign_ne_zero_weighted_sum_squared {M : Type*} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M] (Q : QuadraticForm ℝ M) (hQ : (associated (R := ℝ) Q).SeparatingLeft) : - ∃ w : Fin (FiniteDimensional.finrank ℝ M) → SignType, + ∃ w : Fin (Module.finrank ℝ M) → SignType, (∀ i, w i ≠ 0) ∧ Equivalent Q (weightedSumSquares ℝ fun i ↦ (w i : ℝ)) := let ⟨w, ⟨hw₁⟩⟩ := Q.equivalent_weightedSumSquares_units_of_nondegenerate' hQ ⟨sign ∘ ((↑) : ℝˣ → ℝ) ∘ w, fun i => sign_ne_zero.2 (w i).ne_zero, @@ -63,7 +63,7 @@ theorem equivalent_sign_ne_zero_weighted_sum_squared {M : Type*} [AddCommGroup M sum of squares with the weights being ±1. -/ theorem equivalent_one_neg_one_weighted_sum_squared {M : Type*} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M] (Q : QuadraticForm ℝ M) (hQ : (associated (R := ℝ) Q).SeparatingLeft) : - ∃ w : Fin (FiniteDimensional.finrank ℝ M) → ℝ, + ∃ w : Fin (Module.finrank ℝ M) → ℝ, (∀ i, w i = -1 ∨ w i = 1) ∧ Equivalent Q (weightedSumSquares ℝ w) := let ⟨w, hw₀, hw⟩ := Q.equivalent_sign_ne_zero_weighted_sum_squared hQ ⟨(w ·), fun i ↦ by cases hi : w i <;> simp_all, hw⟩ @@ -72,7 +72,7 @@ theorem equivalent_one_neg_one_weighted_sum_squared {M : Type*} [AddCommGroup M] sum of squares with the weights being ±1 or 0, `SignType` version. -/ theorem equivalent_signType_weighted_sum_squared {M : Type*} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M] (Q : QuadraticForm ℝ M) : - ∃ w : Fin (FiniteDimensional.finrank ℝ M) → SignType, + ∃ w : Fin (Module.finrank ℝ M) → SignType, Equivalent Q (weightedSumSquares ℝ fun i ↦ (w i : ℝ)) := let ⟨w, ⟨hw₁⟩⟩ := Q.equivalent_weightedSumSquares ⟨sign ∘ w, ⟨hw₁.trans (isometryEquivSignWeightedSumSquares w)⟩⟩ @@ -81,7 +81,7 @@ theorem equivalent_signType_weighted_sum_squared {M : Type*} [AddCommGroup M] [M sum of squares with the weights being ±1 or 0. -/ theorem equivalent_one_zero_neg_one_weighted_sum_squared {M : Type*} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M] (Q : QuadraticForm ℝ M) : - ∃ w : Fin (FiniteDimensional.finrank ℝ M) → ℝ, + ∃ w : Fin (Module.finrank ℝ M) → ℝ, (∀ i, w i = -1 ∨ w i = 0 ∨ w i = 1) ∧ Equivalent Q (weightedSumSquares ℝ w) := let ⟨w, hw⟩ := Q.equivalent_signType_weighted_sum_squared ⟨(w ·), fun i ↦ by cases h : w i <;> simp [h], hw⟩ diff --git a/Mathlib/LinearAlgebra/Quotient.lean b/Mathlib/LinearAlgebra/Quotient.lean index 61d6fd9576a2a..ece10805d5505 100644 --- a/Mathlib/LinearAlgebra/Quotient.lean +++ b/Mathlib/LinearAlgebra/Quotient.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 -/ import Mathlib.LinearAlgebra.Span +import Mathlib.LinearAlgebra.Pi import Mathlib.Algebra.Module.Equiv.Basic import Mathlib.GroupTheory.QuotientGroup.Basic import Mathlib.SetTheory.Cardinal.Finite @@ -33,13 +34,15 @@ version, where commutativity can't be assumed. -/ def quotientRel : Setoid M := QuotientAddGroup.leftRel p.toAddSubgroup -theorem quotientRel_r_def {x y : M} : @Setoid.r _ p.quotientRel x y ↔ x - y ∈ p := +theorem quotientRel_def {x y : M} : p.quotientRel x y ↔ x - y ∈ p := Iff.trans (by rw [leftRel_apply, sub_eq_add_neg, neg_add, neg_neg] rfl) neg_mem_iff +@[deprecated (since := "2024-08-29")] alias quotientRel_r_def := quotientRel_def + /-- The quotient of a module `M` by a submodule `p ⊆ M`. -/ instance hasQuotient : HasQuotient M (Submodule R M) := ⟨fun p => Quotient (quotientRel p)⟩ @@ -68,7 +71,7 @@ protected theorem eq' {x y : M} : (mk x : M ⧸ p) = (mk : M → M ⧸ p) y ↔ QuotientAddGroup.eq protected theorem eq {x y : M} : (mk x : M ⧸ p) = (mk y : M ⧸ p) ↔ x - y ∈ p := - (Submodule.Quotient.eq' p).trans (leftRel_apply.symm.trans p.quotientRel_r_def) + (Submodule.Quotient.eq' p).trans (leftRel_apply.symm.trans p.quotientRel_def) instance : Zero (M ⧸ p) where -- Use Quotient.mk'' instead of mk here because mk is not reducible. @@ -282,9 +285,14 @@ def mkQ : M →ₗ[R] M ⧸ p where theorem mkQ_apply (x : M) : p.mkQ x = (Quotient.mk x : M ⧸ p) := rfl -theorem mkQ_surjective (A : Submodule R M) : Function.Surjective A.mkQ := by +theorem mkQ_surjective : Function.Surjective p.mkQ := by rintro ⟨x⟩; exact ⟨x, rfl⟩ +theorem strictMono_comap_prod_map : + StrictMono fun m : Submodule R M ↦ (m.comap p.subtype, m.map p.mkQ) := + fun m₁ m₂ ↦ QuotientAddGroup.strictMono_comap_prod_map + p.toAddSubgroup (a := m₁.toAddSubgroup) (b := m₂.toAddSubgroup) + end variable {R₂ M₂ : Type*} [Ring R₂] [AddCommGroup M₂] [Module R₂ M₂] {τ₁₂ : R →+* R₂} @@ -310,6 +318,14 @@ theorem liftQ_apply (f : M →ₛₗ[τ₁₂] M₂) {h} (x : M) : p.liftQ f h ( @[simp] theorem liftQ_mkQ (f : M →ₛₗ[τ₁₂] M₂) (h) : (p.liftQ f h).comp p.mkQ = f := by ext; rfl +theorem pi_liftQ_eq_liftQ_pi {ι : Type*} {N : ι → Type*} + [∀ i, AddCommGroup (N i)] [∀ i, Module R (N i)] + (f : (i : ι) → M →ₗ[R] (N i)) {p : Submodule R M} (h : ∀ i, p ≤ ker (f i)) : + LinearMap.pi (fun i ↦ p.liftQ (f i) (h i)) = + p.liftQ (LinearMap.pi f) (LinearMap.ker_pi f ▸ le_iInf h) := by + ext x i + simp + /-- Special case of `submodule.liftQ` when `p` is the span of `x`. In this case, the condition on `f` simply becomes vanishing at `x`. -/ def liftQSpanSingleton (x : M) (f : M →ₛₗ[τ₁₂] M₂) (h : f x = 0) : (M ⧸ R ∙ x) →ₛₗ[τ₁₂] M₂ := diff --git a/Mathlib/LinearAlgebra/Ray.lean b/Mathlib/LinearAlgebra/Ray.lean index 87778718498eb..547a7c8540f4b 100644 --- a/Mathlib/LinearAlgebra/Ray.lean +++ b/Mathlib/LinearAlgebra/Ray.lean @@ -6,6 +6,7 @@ Authors: Joseph Myers import Mathlib.Algebra.Order.Module.Algebra import Mathlib.LinearAlgebra.LinearIndependent import Mathlib.Algebra.Ring.Subring.Units +import Mathlib.Tactic.Positivity /-! # Rays in modules @@ -106,7 +107,7 @@ lemma sameRay_nonneg_smul_right (v : M) (h : 0 ≤ a) : SameRay R v (a • v) := · 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] + module /-- A nonnegative multiple of a vector is in the same ray as that vector. -/ lemma sameRay_nonneg_smul_left (v : M) (ha : 0 ≤ a) : SameRay R (a • v) v := @@ -170,9 +171,8 @@ theorem add_left (hx : SameRay R x z) (hy : SameRay R y z) : SameRay R (x + y) z rcases hx.exists_pos hx₀ hz₀ with ⟨rx, rz₁, hrx, hrz₁, Hx⟩ rcases hy.exists_pos hy₀ hz₀ with ⟨ry, rz₂, hry, hrz₂, Hy⟩ refine Or.inr (Or.inr ⟨rx * ry, ry * rz₁ + rx * rz₂, mul_pos hrx hry, ?_, ?_⟩) - · apply_rules [add_pos, mul_pos] - · simp only [mul_smul, smul_add, add_smul, ← Hx, ← Hy] - rw [smul_comm] + · positivity + · convert congr(ry • $Hx + rx • $Hy) using 1 <;> module /-- If `y` and `z` are on the same ray as `x`, then so is `y + z`. -/ theorem add_right (hy : SameRay R x y) (hz : SameRay R x z) : SameRay R x (y + z) := @@ -531,11 +531,11 @@ theorem sameRay_or_sameRay_neg_iff_not_linearIndependent {x y : M} : rcases lt_trichotomy (m 1) 0 with (hm1 | hm1 | hm1) · refine Or.inr (Or.inr (Or.inr ⟨-m 0, -m 1, Left.neg_pos_iff.2 hm0, Left.neg_pos_iff.2 hm1, ?_⟩)) - rw [neg_smul_neg, neg_smul, hm, neg_neg] + linear_combination (norm := module) -hm · exfalso simp [hm1, hx, hm0.ne] at hm · refine Or.inl (Or.inr (Or.inr ⟨-m 0, m 1, Left.neg_pos_iff.2 hm0, hm1, ?_⟩)) - rw [neg_smul, hm, neg_neg] + linear_combination (norm := module) -hm · exfalso simp [hm0, hy, hm1.ne] at hm · rw [Fin.exists_fin_two] at hmne diff --git a/Mathlib/LinearAlgebra/RootSystem/Basic.lean b/Mathlib/LinearAlgebra/RootSystem/Basic.lean index fd07952c7174a..4aba11c944d5e 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Basic.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Basic.lean @@ -120,8 +120,8 @@ protected lemma ext [CharZero R] [NoZeroSMulDivisors R M] ext i j refine P₁.root.injective ?_ conv_rhs => rw [hr] - rw [root_reflection_perm, root_reflection_perm] - simp only [hr, he, hc', reflection_apply] + simp only [root_reflection_perm, reflection_apply, coroot'] + simp only [hr, he, hc'] suffices P₁.coroot = P₂.coroot by cases' P₁ with p₁; cases' P₂ with p₂; cases p₁; cases p₂; congr; exact hp this have := NoZeroSMulDivisors.int_of_charZero R M diff --git a/Mathlib/LinearAlgebra/RootSystem/Defs.lean b/Mathlib/LinearAlgebra/RootSystem/Defs.lean index 55112f1e275ed..eac40333d52fc 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Defs.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Defs.lean @@ -32,7 +32,6 @@ This file contains basic definitions for root systems and root data. ## TODO * Base change of root pairings (may need flatness; perhaps should go in a different file). - * Isomorphism of root pairings. * Crystallographic root systems are isomorphic to base changes of root systems over `ℤ`: Take `M₀` and `N₀` to be the `ℤ`-span of roots and coroots. @@ -51,7 +50,6 @@ between roots and coroots is (implicitly) included and the coroots are included Empirically this seems to be by far the most convenient design and by providing extensionality lemmas expressing the uniqueness we expect to get the best of both worlds. - Furthermore, we require roots and coroots to be injections from a base indexing type `ι` rather than subsets of their codomains. This design was chosen to avoid the bijection between roots and coroots being a dependently-typed object. A third option would be to have the roots and coroots be subsets @@ -88,7 +86,7 @@ evaluates to `2`, and the permutation attached to each element of `ι` is compat reflections on the corresponding roots and coroots. It exists to allow for a convenient unification of the theories of root systems and root data. -/ -structure RootPairing extends PerfectPairing R M N := +structure RootPairing extends PerfectPairing R M N where /-- A parametrized family of vectors, called roots. -/ root : ι ↪ M /-- A parametrized family of dual vectors, called coroots. -/ @@ -112,7 +110,7 @@ abbrev RootDatum (X₁ X₂ : Type*) [AddCommGroup X₁] [AddCommGroup X₂] := Note that this is slightly more general than the usual definition in the sense that `N` is not required to be the dual of `M`. -/ -structure RootSystem extends RootPairing ι R M N := +structure RootSystem extends RootPairing ι R M N where span_eq_top : span R (range root) = ⊤ attribute [simp] RootSystem.span_eq_top @@ -146,13 +144,27 @@ protected def flip : RootPairing ι R N M := lemma flip_flip : P.flip.flip = P := rfl +/-- Roots written as functionals on the coweight space. -/ +abbrev root' (i : ι) : Dual R N := P.toPerfectPairing (P.root i) + +/-- Coroots written as functionals on the weight space. -/ +abbrev coroot' (i : ι) : Dual R M := P.toPerfectPairing.flip (P.coroot i) + /-- This is the pairing between roots and coroots. -/ -def pairing : R := P.toPerfectPairing (P.root i) (P.coroot j) +def pairing : R := P.root' i (P.coroot j) @[simp] lemma root_coroot_eq_pairing : P.toPerfectPairing (P.root i) (P.coroot j) = P.pairing i j := rfl +@[simp] +lemma root'_coroot_eq_pairing : P.root' i (P.coroot j) = P.pairing i j := + rfl + +@[simp] +lemma root_coroot'_eq_pairing : P.coroot' i (P.root j) = P.pairing j i := + rfl + lemma coroot_root_eq_pairing : P.toLin.flip (P.coroot i) (P.root j) = P.pairing j i := by simp @@ -178,7 +190,7 @@ theorem mapsTo_reflection_root : exact P.root_reflection_perm i j ▸ mem_range_self (P.reflection_perm i j) lemma reflection_apply (x : M) : - P.reflection i x = x - (P.toPerfectPairing x (P.coroot i)) • P.root i := + P.reflection i x = x - (P.coroot' i x) • P.root i := rfl lemma reflection_apply_root : @@ -253,7 +265,7 @@ theorem mapsTo_coreflection_coroot : exact P.coroot_reflection_perm i j ▸ mem_range_self (P.reflection_perm i j) lemma coreflection_apply (f : N) : - P.coreflection i f = f - (P.toPerfectPairing (P.root i) f) • P.coroot i := + P.coreflection i f = f - (P.root' i) f • P.coroot i := rfl lemma coreflection_apply_coroot : @@ -303,10 +315,42 @@ lemma coroot_eq_coreflection_of_root_eq rw [← P.root_reflection_perm, EmbeddingLike.apply_eq_iff_eq] at hk rw [← P.coroot_reflection_perm, hk] +lemma coroot'_reflection_perm {i j : ι} : + P.coroot' (P.reflection_perm i j) = P.coroot' j ∘ₗ P.reflection i := by + ext y + simp [coreflection_apply_coroot, reflection_apply, map_sub, mul_comm] + +lemma coroot'_reflection {i j : ι} (y : M) : + P.coroot' j (P.reflection i y) = P.coroot' (P.reflection_perm i j) y := + (LinearMap.congr_fun P.coroot'_reflection_perm y).symm + +lemma pairing_reflection_perm (i j k : ι) : + P.pairing j (P.reflection_perm i k) = P.pairing (P.reflection_perm i j) k := by + simp only [pairing, root', coroot_reflection_perm, root_reflection_perm] + simp only [coreflection_apply_coroot, map_sub, map_smul, smul_eq_mul, + reflection_apply_root] + simp only [← toLin_toPerfectPairing, map_smul, LinearMap.smul_apply, map_sub, map_smul, + LinearMap.sub_apply, smul_eq_mul] + simp only [PerfectPairing.toLin_apply, root'_coroot_eq_pairing, sub_right_inj, mul_comm] + +@[simp] +lemma pairing_reflection_perm_self_left (P : RootPairing ι R M N) (i j : ι) : + P.pairing (P.reflection_perm i i) j = - P.pairing i j := by + rw [pairing, root', ← reflection_perm_root, root'_coroot_eq_pairing, pairing_same, two_smul, + sub_add_cancel_left, ← toLin_toPerfectPairing, LinearMap.map_neg₂, toLin_toPerfectPairing, + root'_coroot_eq_pairing] + +@[simp] +lemma pairing_reflection_perm_self_right (i j : ι) : + P.pairing i (P.reflection_perm j j) = - P.pairing i j := by + rw [pairing, ← reflection_perm_coroot, root_coroot_eq_pairing, pairing_same, two_smul, + sub_add_cancel_left, ← toLin_toPerfectPairing, map_neg, toLin_toPerfectPairing, + root_coroot_eq_pairing] + /-- A root pairing is said to be crystallographic if the pairing between a root and coroot is always an integer. -/ def IsCrystallographic : Prop := - ∀ i, MapsTo (P.toPerfectPairing (P.root i)) (range P.coroot) (zmultiples (1 : R)) + ∀ i, MapsTo (P.root' i) (range P.coroot) (zmultiples (1 : R)) lemma isCrystallographic_iff : P.IsCrystallographic ↔ ∀ i j, ∃ z : ℤ, z = P.pairing i j := by @@ -488,12 +532,12 @@ lemma IsOrthogonal.symm : IsOrthogonal P i j ↔ IsOrthogonal P j i := by simp only [IsOrthogonal, and_comm] lemma isOrthogonal_comm (h : IsOrthogonal P i j) : Commute (P.reflection i) (P.reflection j) := by - rw [Commute, SemiconjBy] + rw [commute_iff_eq] ext v replace h : P.pairing i j = 0 ∧ P.pairing j i = 0 := by simpa [IsOrthogonal] using h erw [LinearMap.mul_apply, LinearMap.mul_apply] - simp only [LinearEquiv.coe_coe, reflection_apply, map_sub, map_smul, root_coroot_eq_pairing, - zero_smul, sub_zero, toLin_toPerfectPairing, h] + simp only [LinearEquiv.coe_coe, reflection_apply, PerfectPairing.flip_apply_apply, map_sub, + map_smul, root_coroot_eq_pairing, h, zero_smul, sub_zero] abel end RootPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean b/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean new file mode 100644 index 0000000000000..d495f1b08bbcc --- /dev/null +++ b/Mathlib/LinearAlgebra/RootSystem/Finite/CanonicalBilinear.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2024 Scott Carnahan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Scott Carnahan +-/ +import Mathlib.LinearAlgebra.RootSystem.Defs +import Mathlib.Algebra.Ring.SumsOfSquares + +/-! +# The canonical bilinear form on a finite root pairing +Given a finite root pairing, we define a canonical map from weight space to coweight space, and the +corresponding bilinear form. This form is symmetric and Weyl-invariant, and if the base ring is +linearly ordered, then the form is root-positive, positive-semidefinite on the weight space, and +positive-definite on the span of roots. +From these facts, it is easy to show that Coxeter weights in a finite root pairing are bounded +above by 4. Thus, the pairings of roots and coroots in a crystallographic root pairing are +restricted to a small finite set of possibilities. +Another application is to the faithfulness of the Weyl group action on roots, and finiteness of the +Weyl group. + +## Main definitions: + * `Polarization`: A distinguished linear map from the weight space to the coweight space. + * `RootForm` : The bilinear form on weight space corresponding to `Polarization`. + +## References: + * SGAIII Exp. XXI + * Bourbaki, Lie groups and Lie algebras + +## Main results: + * `polarization_self_sum_of_squares` : The inner product of any weight vector is a sum of squares. + * `rootForm_reflection_reflection_apply` : `RootForm` is invariant with respect + to reflections. + * `rootForm_self_smul_coroot`: The inner product of a root with itself times the + corresponding coroot is equal to two times Polarization applied to the root. + +## TODO (possibly in other files) + * Positivity and nondegeneracy + * Weyl-invariance + * Faithfulness of Weyl group action, and finiteness of Weyl group, for finite root systems. + * Relation to Coxeter weight. In particular, positivity constraints for finite root pairings mean + we restrict to weights between 0 and 4. +-/ + +open Function +open Module hiding reflection + +noncomputable section + +variable {ι R M N : Type*} + +namespace RootPairing + +section CommRing + +variable [Fintype ι] [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] +(P : RootPairing ι R M N) + +/-- An invariant linear map from weight space to coweight space. -/ +def Polarization : M →ₗ[R] N := + ∑ i, LinearMap.toSpanSingleton R N (P.coroot i) ∘ₗ P.coroot' i + +@[simp] +lemma Polarization_apply (x : M) : + P.Polarization x = ∑ i, P.coroot' i x • P.coroot i := by + simp [Polarization] + +/-- An invariant linear map from coweight space to weight space. -/ +def CoPolarization : N →ₗ[R] M := + ∑ i, LinearMap.toSpanSingleton R M (P.root i) ∘ₗ P.root' i + +@[simp] +lemma CoPolarization_apply (x : N) : + P.CoPolarization x = ∑ i, P.root' i x • P.root i := by + simp [CoPolarization] + +lemma CoPolarization_eq : P.CoPolarization = P.flip.Polarization := + rfl + +/-- An invariant inner product on the weight space. -/ +def RootForm : LinearMap.BilinForm R M := + ∑ i, (P.coroot' i).smulRight (P.coroot' i) + +/-- An invariant inner product on the coweight space. -/ +def CorootForm : LinearMap.BilinForm R N := + ∑ i, (P.root' i).smulRight (P.root' i) + +lemma rootForm_apply_apply (x y : M) : P.RootForm x y = + ∑ (i : ι), P.coroot' i x * P.coroot' i y := by + simp [RootForm] + +lemma rootForm_symmetric : + LinearMap.IsSymm P.RootForm := by + simp [LinearMap.IsSymm, mul_comm, rootForm_apply_apply] + +@[simp] +lemma rootForm_reflection_reflection_apply (i : ι) (x y : M) : + P.RootForm (P.reflection i x) (P.reflection i y) = P.RootForm x y := by + simp only [rootForm_apply_apply, coroot'_reflection] + exact Fintype.sum_equiv (P.reflection_perm i) + (fun j ↦ (P.coroot' (P.reflection_perm i j) x) * (P.coroot' (P.reflection_perm i j) y)) + (fun j ↦ P.coroot' j x * P.coroot' j y) (congrFun rfl) + +/-- This is SGA3 XXI Lemma 1.2.1 (10), key for proving nondegeneracy and positivity. -/ +lemma rootForm_self_smul_coroot (i : ι) : + (P.RootForm (P.root i) (P.root i)) • P.coroot i = 2 • P.Polarization (P.root i) := by + have hP : P.Polarization (P.root i) = + ∑ j : ι, P.pairing i (P.reflection_perm i j) • P.coroot (P.reflection_perm i j) := by + simp_rw [Polarization_apply, root_coroot'_eq_pairing] + exact (Fintype.sum_equiv (P.reflection_perm i) + (fun j ↦ P.pairing i (P.reflection_perm i j) • P.coroot (P.reflection_perm i j)) + (fun j ↦ P.pairing i j • P.coroot j) (congrFun rfl)).symm + rw [two_nsmul] + nth_rw 2 [hP] + rw [Polarization_apply] + simp only [root_coroot'_eq_pairing, pairing_reflection_perm, pairing_reflection_perm_self_left, + ← reflection_perm_coroot, smul_sub, neg_smul, sub_neg_eq_add] + rw [Finset.sum_add_distrib, ← add_assoc, ← sub_eq_iff_eq_add] + simp only [rootForm_apply_apply, LinearMap.coe_comp, comp_apply, Polarization_apply, + root_coroot_eq_pairing, map_sum, LinearMapClass.map_smul, Finset.sum_neg_distrib, ← smul_assoc] + rw [Finset.sum_smul, add_neg_eq_zero.mpr rfl] + exact sub_eq_zero_of_eq rfl + +lemma corootForm_self_smul_root (i : ι) : + (P.CorootForm (P.coroot i) (P.coroot i)) • P.root i = 2 • P.CoPolarization (P.coroot i) := + rootForm_self_smul_coroot (P.flip) i + +lemma rootForm_self_sum_of_squares (x : M) : + IsSumSq (P.RootForm x x) := + P.rootForm_apply_apply x x ▸ isSumSq_sum_mul_self Finset.univ _ + +lemma rootForm_root_self (j : ι) : + P.RootForm (P.root j) (P.root j) = ∑ (i : ι), (P.pairing j i) * (P.pairing j i) := by + simp [rootForm_apply_apply] + +end CommRing + +end RootPairing diff --git a/Mathlib/LinearAlgebra/RootSystem/Hom.lean b/Mathlib/LinearAlgebra/RootSystem/Hom.lean index f70d0830fdaee..5d58b28dabbf4 100644 --- a/Mathlib/LinearAlgebra/RootSystem/Hom.lean +++ b/Mathlib/LinearAlgebra/RootSystem/Hom.lean @@ -116,7 +116,9 @@ def Hom.reflection (P : RootPairing ι R M N) (i : ι) : Hom P P where PerfectPairing.toDualRight_apply, LinearMap.dualMap_apply, PerfectPairing.flip_apply_apply, LinearEquiv.comp_coe, LinearEquiv.trans_apply] rw [RootPairing.reflection_apply, RootPairing.coreflection_apply] - simp [map_sub, ← PerfectPairing.toLin_apply, mul_comm] + simp only [← PerfectPairing.toLin_apply, map_sub, map_smul, LinearMap.sub_apply, + toLin_toPerfectPairing, LinearMap.smul_apply, smul_eq_mul, sub_right_inj] + simp only [PerfectPairing.toLin_apply, PerfectPairing.flip_apply_apply, mul_comm] root_weightMap := by ext; simp coroot_coweightMap := by ext; simp diff --git a/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean b/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean index 026b7b23f30d7..b339fa3a131cc 100644 --- a/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean +++ b/Mathlib/LinearAlgebra/RootSystem/OfBilinear.lean @@ -33,7 +33,7 @@ namespace LinearMap injective, and for any vector `y`, the norm of `x` divides twice the inner product of `x` and `y`. These conditions are what we need when describing reflection as a map taking `y` to `y - 2 • (B x y) / (B x x) • x`. -/ -structure IsReflective (B : M →ₗ[R] M →ₗ[R] R) (x : M) : Prop := +structure IsReflective (B : M →ₗ[R] M →ₗ[R] R) (x : M) : Prop where regular : IsRegular (B x x) dvd_two_mul : ∀ y, B x x ∣ 2 * B x y diff --git a/Mathlib/LinearAlgebra/RootSystem/RootPositive.lean b/Mathlib/LinearAlgebra/RootSystem/RootPositive.lean index ccf50330e9a81..e9d55f92f8209 100644 --- a/Mathlib/LinearAlgebra/RootSystem/RootPositive.lean +++ b/Mathlib/LinearAlgebra/RootSystem/RootPositive.lean @@ -55,7 +55,7 @@ lemma two_mul_apply_root_root : 2 * B (P.root i) (P.root j) = P.pairing i j * B (P.root j) (P.root j) := by rw [two_mul, ← eq_sub_iff_add_eq] nth_rw 1 [← IsRootPositive.apply_reflection_eq (P := P) (B := B) j (P.root i) (P.root j)] - rw [reflection_apply, reflection_apply_self, root_coroot_eq_pairing, LinearMap.map_sub₂, + rw [reflection_apply, reflection_apply_self, root_coroot'_eq_pairing, LinearMap.map_sub₂, LinearMap.map_smul₂, smul_eq_mul, LinearMap.map_neg, LinearMap.map_neg, mul_neg, neg_sub_neg] @[simp] diff --git a/Mathlib/LinearAlgebra/Semisimple.lean b/Mathlib/LinearAlgebra/Semisimple.lean index ea02d0bd4374e..3aeb94be63ed6 100644 --- a/Mathlib/LinearAlgebra/Semisimple.lean +++ b/Mathlib/LinearAlgebra/Semisimple.lean @@ -80,7 +80,7 @@ lemma eq_zero_of_isNilpotent_isSemisimple (hn : IsNilpotent f) (hs : f.IsSemisim have ⟨n, h0⟩ := hn rw [← aeval_X (R := R) f]; rw [← aeval_X_pow (R := R) f] at h0 rw [← RingHom.mem_ker, ← AEval.annihilator_eq_ker_aeval (M := M)] at h0 ⊢ - exact hs.annihilator_isRadical ⟨n, h0⟩ + exact hs.annihilator_isRadical _ _ ⟨n, h0⟩ @[simp] lemma isSemisimple_sub_algebraMap_iff {μ : R} : @@ -145,7 +145,7 @@ theorem IsSemisimple.minpoly_squarefree : Squarefree (minpoly K f) := protected theorem IsSemisimple.aeval (p : K[X]) : (aeval f p).IsSemisimple := let R := K[X] ⧸ Ideal.span {minpoly K f} - have : Finite K R := + have : Module.Finite K R := (AdjoinRoot.powerBasis' <| minpoly.monic <| Algebra.IsIntegral.isIntegral f).finite have : IsReduced R := (Ideal.isRadical_iff_quotient_reduced _).mp <| span_minpoly_eq_annihilator K f ▸ hf.annihilator_isRadical @@ -174,9 +174,9 @@ theorem IsSemisimple.of_mem_adjoin_pair {a : End K M} (ha : a ∈ Algebra.adjoin a.IsSemisimple := by let R := K[X] ⧸ Ideal.span {minpoly K f} let S := AdjoinRoot ((minpoly K g).map <| algebraMap K R) - have : Finite K R := + have : Module.Finite K R := (AdjoinRoot.powerBasis' <| minpoly.monic <| Algebra.IsIntegral.isIntegral f).finite - have : Finite R S := + have : Module.Finite R S := (AdjoinRoot.powerBasis' <| (minpoly.monic <| Algebra.IsIntegral.isIntegral g).map _).finite #adaptation_note /-- @@ -187,7 +187,7 @@ theorem IsSemisimple.of_mem_adjoin_pair {a : End K M} (ha : a ∈ Algebra.adjoin -/ set_option maxSynthPendingDepth 2 in have : IsScalarTower K R S := .of_algebraMap_eq fun _ ↦ rfl - have : Finite K S := .trans R S + have : Module.Finite K S := .trans R S have : IsArtinianRing R := .of_finite K R have : IsReduced R := (Ideal.isRadical_iff_quotient_reduced _).mp <| span_minpoly_eq_annihilator K f ▸ hf.annihilator_isRadical diff --git a/Mathlib/LinearAlgebra/Span.lean b/Mathlib/LinearAlgebra/Span.lean index 8ff62644c2b01..460f7003ad94b 100644 --- a/Mathlib/LinearAlgebra/Span.lean +++ b/Mathlib/LinearAlgebra/Span.lean @@ -74,7 +74,7 @@ theorem subset_span : s ⊆ span R s := fun _ h => mem_span.2 fun _ hp => hp h theorem span_le {p} : span R s ≤ p ↔ s ⊆ p := ⟨Subset.trans subset_span, fun ss _ h => mem_span.1 h _ ss⟩ -theorem span_mono (h : s ⊆ t) : span R s ≤ span R t := +@[gcongr] theorem span_mono (h : s ⊆ t) : span R s ≤ span R t := span_le.2 <| Subset.trans h subset_span theorem span_monotone : Monotone (span R : Set M → Submodule R M) := fun _ _ => span_mono diff --git a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean index 12adf5ad0f2b0..e37eea1ee4fdd 100644 --- a/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean +++ b/Mathlib/LinearAlgebra/TensorAlgebra/ToTensorPower.lean @@ -32,8 +32,8 @@ theorem toTensorAlgebra_tprod {n} (x : Fin n → M) : @[simp] theorem toTensorAlgebra_gOne : - TensorPower.toTensorAlgebra (@GradedMonoid.GOne.one _ (fun n => ⨂[R]^n M) _ _) = 1 := - TensorPower.toTensorAlgebra_tprod _ + TensorPower.toTensorAlgebra (@GradedMonoid.GOne.one _ (fun n => ⨂[R]^n M) _ _) = 1 := by + simp [GradedMonoid.GOne.one, TensorPower.toTensorAlgebra_tprod] @[simp] theorem toTensorAlgebra_gMul {i j} (a : (⨂[R]^i) M) (b : (⨂[R]^j) M) : diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean index 64465d3ce42e3..e9896dd5d9c21 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/External.lean @@ -225,8 +225,8 @@ theorem gradedMul_algebraMap (x : (⨁ i, 𝒜 i) ⊗[R] (⨁ i, ℬ i)) (r : R) ext dsimp erw [tmul_of_gradedMul_of_tmul] - rw [mul_zero, uzpow_zero, one_smul, smul_tmul'] - erw [mul_one, _root_.Algebra.smul_def, Algebra.commutes] + rw [mul_zero, uzpow_zero, one_smul, smul_tmul', + mul_one, _root_.Algebra.smul_def, Algebra.commutes] rfl theorem gradedMul_one (x : (⨁ i, 𝒜 i) ⊗[R] (⨁ i, ℬ i)) : diff --git a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean index d06c680fb6859..2560f546b9ab3 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Graded/Internal.lean @@ -184,7 +184,7 @@ theorem tmul_coe_mul_coe_tmul {j₁ i₂ : ι} (a₁ : A) (b₁ : ℬ j₁) (a (-1 : ℤˣ)^(j₁ * i₂) • ((a₁ * a₂ : A) ᵍ⊗ₜ (b₁ * b₂ : B)) := by dsimp only [mul_def, mulHom_apply, of_symm_of] dsimp [auxEquiv, tmul] - erw [decompose_coe, decompose_coe] + rw [decompose_coe, decompose_coe] simp_rw [← lof_eq_of R] rw [tmul_of_gradedMul_of_tmul] simp_rw [lof_eq_of R] @@ -220,7 +220,7 @@ theorem tmul_coe_mul_one_tmul {j₁ : ι} (a₁ : A) (b₁ : ℬ j₁) (b₂ : B theorem tmul_one_mul_one_tmul (a₁ : A) (b₂ : B) : (a₁ ᵍ⊗ₜ[R] (1 : B) * (1 : A) ᵍ⊗ₜ[R] b₂ : 𝒜 ᵍ⊗[R] ℬ) = (a₁ : A) ᵍ⊗ₜ (b₂ : B) := by convert tmul_coe_mul_zero_coe_tmul 𝒜 ℬ - a₁ (@GradedMonoid.GOne.one _ (ℬ ·) _ _) (@GradedMonoid.GOne.one _ (𝒜 ·) _ _) b₂ + a₁ (GradedMonoid.GOne.one (A := (ℬ ·))) (GradedMonoid.GOne.one (A := (𝒜 ·))) b₂ · rw [SetLike.coe_gOne, mul_one] · rw [SetLike.coe_gOne, one_mul] diff --git a/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean b/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean index 608cd74b64296..14d7396e79842 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/RightExactness.lean @@ -547,7 +547,7 @@ lemma Ideal.map_includeLeft_eq (I : Ideal A) : simp only [map_zero, smul_eq_mul, mul_zero] | tmul x y => use (a • x) ⊗ₜ[R] (b * y) - simp only [LinearMap.lTensor_tmul, Submodule.coeSubtype, smul_eq_mul, tmul_mul_tmul] + simp only [LinearMap.lTensor_tmul, Submodule.coe_subtype, smul_eq_mul, tmul_mul_tmul] with_unfolding_all rfl | add x y hx hy => obtain ⟨x', hx'⟩ := hx @@ -566,7 +566,7 @@ lemma Ideal.map_includeLeft_eq (I : Ideal A) : rw [map_zero] apply zero_mem | tmul a b => - simp only [LinearMap.rTensor_tmul, Submodule.coeSubtype] + simp only [LinearMap.rTensor_tmul, Submodule.coe_subtype] suffices (a : A) ⊗ₜ[R] b = ((1 : A) ⊗ₜ[R] b) * ((a : A) ⊗ₜ[R] (1 : B)) by simp only [AddSubsemigroup.mem_carrier, AddSubmonoid.mem_toSubsemigroup, Submodule.mem_toAddSubmonoid, Submodule.restrictScalars_mem] @@ -615,7 +615,7 @@ lemma Ideal.map_includeRight_eq (I : Ideal B) : simp only [map_zero, smul_eq_mul, mul_zero] | tmul x y => use (a * x) ⊗ₜ[R] (b •y) - simp only [LinearMap.lTensor_tmul, Submodule.coeSubtype, smul_eq_mul, tmul_mul_tmul] + simp only [LinearMap.lTensor_tmul, Submodule.coe_subtype, smul_eq_mul, tmul_mul_tmul] rfl | add x y hx hy => obtain ⟨x', hx'⟩ := hx @@ -634,7 +634,7 @@ lemma Ideal.map_includeRight_eq (I : Ideal B) : rw [map_zero] apply zero_mem | tmul a b => - simp only [LinearMap.lTensor_tmul, Submodule.coeSubtype] + simp only [LinearMap.lTensor_tmul, Submodule.coe_subtype] suffices a ⊗ₜ[R] (b : B) = (a ⊗ₜ[R] (1 : B)) * ((1 : A) ⊗ₜ[R] (b : B)) by rw [this] simp only [AddSubsemigroup.mem_carrier, AddSubmonoid.mem_toSubsemigroup, diff --git a/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean b/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean index 2ec0b351ea9e9..83b52e58279fd 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Subalgebra.lean @@ -36,7 +36,7 @@ mainly used in the definition of linearly disjointness. open scoped TensorProduct -open FiniteDimensional +open Module noncomputable section @@ -194,7 +194,7 @@ theorem rank_sup_le_of_free [Module.Free R A] [Module.Free R B] : exact rank_range_le (A.mulMap B).toLinearMap /-- If `A` and `B` are subalgebras of a commutative `R`-algebra `S`, both of them are -free `R`-algebras, then the `FiniteDimensional.finrank` of `A ⊔ B` is less than or equal to +free `R`-algebras, then the `Module.finrank` of `A ⊔ B` is less than or equal to the product of that of `A` and `B`. -/ theorem finrank_sup_le_of_free [Module.Free R A] [Module.Free R B] : finrank R ↥(A ⊔ B) ≤ finrank R A * finrank R B := by @@ -206,7 +206,7 @@ theorem finrank_sup_le_of_free [Module.Free R A] [Module.Free R B] : wlog hA : ¬ Module.Finite R A generalizing A B · have := this B A (fun h' ↦ h h'.symm) (not_and.1 h (of_not_not hA)) rwa [sup_comm, mul_comm] at this - rw [← Module.rank_lt_alpeh0_iff, not_lt] at hA + rw [← Module.rank_lt_aleph0_iff, not_lt] at hA have := LinearMap.rank_le_of_injective _ <| Submodule.inclusion_injective <| show toSubmodule A ≤ toSubmodule (A ⊔ B) by simp rw [show finrank R A = 0 from Cardinal.toNat_apply_of_aleph0_le hA, diff --git a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean index dbf016581b5a2..8a6dcf8f11f00 100644 --- a/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean +++ b/Mathlib/LinearAlgebra/TensorProduct/Vanishing.lean @@ -146,7 +146,7 @@ theorem vanishesTrivially_of_sum_tmul_eq_zero (hm : Submodule.span R (Set.range symm at hkn simp only [map_sum, finsuppScalarLeft_apply_tmul, zero_smul, Finsupp.single_zero, Finsupp.sum_single_index, one_smul, Finsupp.finset_sum_apply, Finsupp.single_apply, - Finset.sum_ite_eq', Finset.mem_univ, ↓reduceIte, rTensor_tmul, coeSubtype, Finsupp.sum_apply, + Finset.sum_ite_eq', Finset.mem_univ, ↓reduceIte, rTensor_tmul, coe_subtype, Finsupp.sum_apply, Finsupp.sum_ite_eq', Finsupp.mem_support_iff, ne_eq, ite_not, en] at hkn simp only [Finset.univ_eq_attach, Finset.sum_attach ma (fun x ↦ (x.1 : ι →₀ R) i • x.2)] convert hkn using 2 with x _ @@ -181,11 +181,11 @@ theorem vanishesTrivially_of_sum_tmul_eq_zero_of_rTensor_injective set m' : ι → span R (Set.range m) := Subtype.coind m mem_M' with m'_eq have hm' : span R (Set.range m') = ⊤ := by apply map_injective_of_injective (injective_subtype (span R (Set.range m))) - rw [Submodule.map_span, Submodule.map_top, range_subtype, coeSubtype, ← Set.range_comp] + rw [Submodule.map_span, Submodule.map_top, range_subtype, coe_subtype, ← Set.range_comp] rfl have hm'n : ∑ i, m' i ⊗ₜ n i = (0 : span R (Set.range m) ⊗[R] N) := by apply hm - simp only [m'_eq, map_sum, rTensor_tmul, coeSubtype, Subtype.coind_coe, _root_.map_zero, hmn] + simp only [m'_eq, map_sum, rTensor_tmul, coe_subtype, Subtype.coind_coe, _root_.map_zero, hmn] have : VanishesTrivially R m' n := vanishesTrivially_of_sum_tmul_eq_zero R hm' hm'n unfold VanishesTrivially at this ⊢ convert this with κ _ a y j @@ -218,7 +218,7 @@ theorem rTensor_injective_of_forall_vanishesTrivially obtain ⟨s, rfl⟩ := exists_finset x rw [← Finset.sum_attach] apply sum_tmul_eq_zero_of_vanishesTrivially - simp only [map_sum, rTensor_tmul, coeSubtype] at hx + simp only [map_sum, rTensor_tmul, coe_subtype] at hx have := hMN ((Finset.sum_attach s _).trans hx) unfold VanishesTrivially at this ⊢ convert this with κ _ a y j diff --git a/Mathlib/LinearAlgebra/Trace.lean b/Mathlib/LinearAlgebra/Trace.lean index d8dfa8fb4f30b..81598681a3b50 100644 --- a/Mathlib/LinearAlgebra/Trace.lean +++ b/Mathlib/LinearAlgebra/Trace.lean @@ -25,7 +25,7 @@ universe u v w namespace LinearMap open scoped Matrix -open FiniteDimensional TensorProduct +open Module TensorProduct section diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index b33cfc478250f..b4258e60f795c 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -429,14 +429,20 @@ theorem rec_heq_iff_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : C a} theorem heq_rec_iff_heq {α β : Sort _} {a b : α} {C : α → Sort*} {x : β} {y : C a} {e : a = b} : HEq x (e ▸ y) ↔ HEq x y := by subst e; rfl +universe u +variable {α β : Sort u} {e : β = α} {a : α} {b : β} + +lemma heq_of_eq_cast (e : β = α) : a = cast e b → HEq a b := by rintro rfl; simp + +lemma eq_cast_iff_heq : a = cast e b ↔ HEq a b := ⟨heq_of_eq_cast _, fun h ↦ by cases h; rfl⟩ + end Equality /-! ### Declarations about quantifiers -/ section Quantifiers section Dependent -variable {α : Sort*} {β : α → Sort*} {γ : ∀ a, β a → Sort*} {δ : ∀ a b, γ a b → Sort*} - {ε : ∀ a b c, δ a b c → Sort*} +variable {α : Sort*} {β : α → Sort*} {γ : ∀ a, β a → Sort*} theorem pi_congr {β' : α → Sort _} (h : ∀ a, β a = β' a) : (∀ a, β a) = ∀ a, β' a := (funext h : β = β') ▸ rfl @@ -462,7 +468,7 @@ theorem Exists₃.imp {p q : ∀ a b, γ a b → Prop} (h : ∀ a b c, p a b c end Dependent -variable {α β : Sort*} {p q : α → Prop} +variable {α β : Sort*} {p : α → Prop} theorem forall_swap {p : α → β → Prop} : (∀ x y, p x y) ↔ ∀ y x, p x y := ⟨fun f x y ↦ f y x, fun f x y ↦ f y x⟩ @@ -664,7 +670,7 @@ namespace Classical /-- Any prop `p` is decidable classically. A shorthand for `Classical.propDecidable`. -/ noncomputable def dec (p : Prop) : Decidable p := by infer_instance -variable {α : Sort*} {p : α → Prop} +variable {α : Sort*} /-- Any predicate `p` is decidable classically. -/ noncomputable def decPred (p : α → Prop) : DecidablePred p := by infer_instance @@ -677,7 +683,6 @@ noncomputable def decEq (α : Sort*) : DecidableEq α := by infer_instance /-- Construct a function from a default value `H0`, and a function to use if there exists a value satisfying the predicate. -/ --- @[elab_as_elim] -- FIXME noncomputable def existsCases {α C : Sort*} {p : α → Prop} (H0 : C) (H : ∀ a, p a → C) : C := if h : ∃ a, p a then H (Classical.choose h) (Classical.choose_spec h) else H0 @@ -737,7 +742,6 @@ end Classical /-- This function has the same type as `Exists.recOn`, and can be used to case on an equality, but `Exists.recOn` can only eliminate into Prop, while this version eliminates into any universe using the axiom of choice. -/ --- @[elab_as_elim] -- FIXME noncomputable def Exists.classicalRecOn {α : Sort*} {p : α → Prop} (h : ∃ a, p a) {C : Sort*} (H : ∀ a, p a → C) : C := H (Classical.choose h) (Classical.choose_spec h) @@ -745,7 +749,7 @@ noncomputable def Exists.classicalRecOn {α : Sort*} {p : α → Prop} (h : ∃ /-! ### Declarations about bounded quantifiers -/ section BoundedQuantifiers -variable {α : Sort*} {r p q : α → Prop} {P Q : ∀ x, p x → Prop} {b : Prop} +variable {α : Sort*} {r p q : α → Prop} {P Q : ∀ x, p x → Prop} theorem bex_def : (∃ (x : _) (_ : p x), q x) ↔ ∃ x, p x ∧ q x := ⟨fun ⟨x, px, qx⟩ ↦ ⟨x, px, qx⟩, fun ⟨x, px, qx⟩ ↦ ⟨x, px, qx⟩⟩ @@ -976,7 +980,7 @@ theorem not_beq_of_ne {α : Type*} [BEq α] [LawfulBEq α] {a b : α} (ne : a fun h => ne (eq_of_beq h) theorem beq_eq_decide {α : Type*} [BEq α] [LawfulBEq α] {a b : α} : (a == b) = decide (a = b) := by - rw [← beq_iff_eq a b] + rw [← beq_iff_eq (a := a) (b := b)] cases a == b <;> simp @[simp] lemma beq_eq_beq {α β : Type*} [BEq α] [LawfulBEq α] [BEq β] [LawfulBEq β] {a₁ a₂ : α} diff --git a/Mathlib/Logic/Encodable/Lattice.lean b/Mathlib/Logic/Encodable/Lattice.lean index 61e01cc0053a4..039681749b576 100644 --- a/Mathlib/Logic/Encodable/Lattice.lean +++ b/Mathlib/Logic/Encodable/Lattice.lean @@ -33,8 +33,7 @@ theorem iSup_decode₂ [CompleteLattice α] (f : β → α) : theorem iUnion_decode₂ (f : β → Set α) : ⋃ (i : ℕ) (b ∈ decode₂ β i), f b = ⋃ b, f b := iSup_decode₂ f -/- Porting note: `@[elab_as_elim]` gives `unexpected eliminator resulting type`. -/ ---@[elab_as_elim] +@[elab_as_elim] theorem iUnion_decode₂_cases {f : β → Set α} {C : Set α → Prop} (H0 : C ∅) (H1 : ∀ b, C (f b)) {n} : C (⋃ b ∈ decode₂ β n, f b) := match decode₂ β n with diff --git a/Mathlib/Logic/Equiv/Array.lean b/Mathlib/Logic/Equiv/Array.lean index cd9c6fbef7d1f..eb98b0edd323b 100644 --- a/Mathlib/Logic/Equiv/Array.lean +++ b/Mathlib/Logic/Equiv/Array.lean @@ -42,7 +42,7 @@ namespace Equiv /-- The natural equivalence between arrays and lists. -/ def arrayEquivList (α : Type*) : Array α ≃ List α := - ⟨Array.data, Array.mk, fun _ => rfl, fun _ => rfl⟩ + ⟨Array.toList, Array.mk, fun _ => rfl, fun _ => rfl⟩ end Equiv diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index d68413363ef4b..198c48db494a9 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -52,7 +52,7 @@ universe u v w z open Function -- Unless required to be `Type*`, all variables in this file are `Sort*` -variable {α α₁ α₂ β β₁ β₂ γ γ₁ γ₂ δ : Sort*} +variable {α α₁ α₂ β β₁ β₂ γ δ : Sort*} namespace Equiv @@ -629,7 +629,7 @@ section /-- A family of equivalences `∀ a, β₁ a ≃ β₂ a` generates an equivalence between `∀ a, β₁ a` and `∀ a, β₂ a`. -/ def piCongrRight {β₁ β₂ : α → Sort*} (F : ∀ a, β₁ a ≃ β₂ a) : (∀ a, β₁ a) ≃ (∀ a, β₂ a) := - ⟨fun H a => F a (H a), fun H a => (F a).symm (H a), fun H => funext <| by simp, + ⟨Pi.map fun a ↦ F a, Pi.map fun a ↦ (F a).symm, fun H => funext <| by simp, fun H => funext <| by simp⟩ /-- Given `φ : α → β → Sort*`, we have an equivalence between `∀ a b, φ a b` and `∀ b a, φ a b`. @@ -1372,14 +1372,14 @@ def subtypeQuotientEquivQuotientSubtype (p₁ : α → Prop) {s₁ : Setoid α} @[simp] theorem subtypeQuotientEquivQuotientSubtype_mk (p₁ : α → Prop) [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)] (p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧) - (h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y) + (h : ∀ x y : Subtype p₁, s₂ x y ↔ (x : α) ≈ y) (x hx) : subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h ⟨⟦x⟧, hx⟩ = ⟦⟨x, (hp₂ _).2 hx⟩⟧ := rfl @[simp] theorem subtypeQuotientEquivQuotientSubtype_symm_mk (p₁ : α → Prop) [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)] (p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧) - (h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y) (x) : + (h : ∀ x y : Subtype p₁, s₂ x y ↔ (x : α) ≈ y) (x) : (subtypeQuotientEquivQuotientSubtype p₁ p₂ hp₂ h).symm ⟦x⟧ = ⟨⟦x⟧, (hp₂ _).1 x.property⟩ := rfl @@ -1580,8 +1580,6 @@ namespace Equiv section -variable (P : α → Sort w) (e : α ≃ β) - /-- Transport dependent functions through an equivalence of the base space. -/ @[simps apply, simps (config := .lemmasOnly) symm_apply] @@ -1690,7 +1688,7 @@ theorem piCongr_symm_apply (f : ∀ b, Z b) : @[simp] theorem piCongr_apply_apply (f : ∀ a, W a) (a : α) : h₁.piCongr h₂ f (h₁ a) = h₂ a (f a) := by - simp only [piCongr, piCongrRight, trans_apply, coe_fn_mk, piCongrLeft_apply_apply] + simp only [piCongr, piCongrRight, trans_apply, coe_fn_mk, piCongrLeft_apply_apply, Pi.map_apply] end diff --git a/Mathlib/Logic/Equiv/Defs.lean b/Mathlib/Logic/Equiv/Defs.lean index 78cf1e5f1f2e2..79b92f29b0e1b 100644 --- a/Mathlib/Logic/Equiv/Defs.lean +++ b/Mathlib/Logic/Equiv/Defs.lean @@ -844,17 +844,17 @@ namespace Quotient /-- An equivalence `e : α ≃ β` generates an equivalence between quotient spaces, if `ra a₁ a₂ ↔ rb (e a₁) (e a₂)`. -/ protected def congr {ra : Setoid α} {rb : Setoid β} (e : α ≃ β) - (eq : ∀ a₁ a₂, @Setoid.r α ra a₁ a₂ ↔ @Setoid.r β rb (e a₁) (e a₂)) : + (eq : ∀ a₁ a₂, ra a₁ a₂ ↔ rb (e a₁) (e a₂)) : Quotient ra ≃ Quotient rb := Quot.congr e eq @[simp] theorem congr_mk {ra : Setoid α} {rb : Setoid β} (e : α ≃ β) - (eq : ∀ a₁ a₂ : α, Setoid.r a₁ a₂ ↔ Setoid.r (e a₁) (e a₂)) (a : α) : + (eq : ∀ a₁ a₂ : α, ra a₁ a₂ ↔ rb (e a₁) (e a₂)) (a : α) : Quotient.congr e eq (Quotient.mk ra a) = Quotient.mk rb (e a) := rfl /-- Quotients are congruent on equivalences under equality of their relation. An alternative is just to use rewriting with `eq`, but then computational proofs get stuck. -/ protected def congrRight {r r' : Setoid α} - (eq : ∀ a₁ a₂, @Setoid.r α r a₁ a₂ ↔ @Setoid.r α r' a₁ a₂) : Quotient r ≃ Quotient r' := + (eq : ∀ a₁ a₂, r a₁ a₂ ↔ r' a₁ a₂) : Quotient r ≃ Quotient r' := Quot.congrRight eq end Quotient diff --git a/Mathlib/Logic/Equiv/Fin.lean b/Mathlib/Logic/Equiv/Fin.lean index 1d07d2d1b2b25..3453d19eac020 100644 --- a/Mathlib/Logic/Equiv/Fin.lean +++ b/Mathlib/Logic/Equiv/Fin.lean @@ -470,7 +470,7 @@ def Int.divModEquiv (n : ℕ) [NeZero n] : ℤ ≃ ℤ × Fin n where toFun a := (a / n, ↑(a.natMod n)) invFun p := p.1 * n + ↑p.2 left_inv a := by - simp_rw [Fin.coe_ofNat_eq_mod, natCast_mod, natMod, + simp_rw [Fin.coe_natCast_eq_mod, natCast_mod, natMod, toNat_of_nonneg (emod_nonneg _ <| natCast_eq_zero.not.2 (NeZero.ne n)), emod_emod, ediv_add_emod'] right_inv := fun ⟨q, r, hrn⟩ => by diff --git a/Mathlib/Logic/Equiv/PartialEquiv.lean b/Mathlib/Logic/Equiv/PartialEquiv.lean index 7d93cc552f446..9dd50be972f0c 100644 --- a/Mathlib/Logic/Equiv/PartialEquiv.lean +++ b/Mathlib/Logic/Equiv/PartialEquiv.lean @@ -316,7 +316,7 @@ def IsImage (s : Set α) (t : Set β) : Prop := namespace IsImage -variable {e} {s : Set α} {t : Set β} {x : α} {y : β} +variable {e} {s : Set α} {t : Set β} {x : α} theorem apply_mem_iff (h : e.IsImage s t) (hx : x ∈ e.source) : e x ∈ t ↔ x ∈ s := h hx @@ -843,8 +843,8 @@ variable {ι : Type*} {αi βi γi : ι → Type*} /-- The product of a family of partial equivalences, as a partial equivalence on the pi type. -/ @[simps (config := mfld_cfg) apply source target] protected def pi (ei : ∀ i, PartialEquiv (αi i) (βi i)) : PartialEquiv (∀ i, αi i) (∀ i, βi i) where - toFun f i := ei i (f i) - invFun f i := (ei i).symm (f i) + toFun := Pi.map fun i ↦ ei i + invFun := Pi.map fun i ↦ (ei i).symm source := pi univ fun i => (ei i).source target := pi univ fun i => (ei i).target map_source' _ hf i hi := (ei i).map_source (hf i hi) diff --git a/Mathlib/Logic/Function/Basic.lean b/Mathlib/Logic/Function/Basic.lean index 21435518020b1..1af46bf00e7fa 100644 --- a/Mathlib/Logic/Function/Basic.lean +++ b/Mathlib/Logic/Function/Basic.lean @@ -118,10 +118,15 @@ theorem Injective.of_comp_iff' (f : α → β) {g : γ → α} (hg : Bijective g Injective (f ∘ g) ↔ Injective f := ⟨fun I ↦ I.of_comp_right hg.2, fun h ↦ h.comp hg.injective⟩ +theorem Injective.piMap {ι : Sort*} {α β : ι → Sort*} {f : ∀ i, α i → β i} + (hf : ∀ i, Injective (f i)) : Injective (Pi.map f) := fun _ _ h ↦ + funext fun i ↦ hf i <| congrFun h _ + +@[deprecated (since := "2024-10-06")] alias injective_pi_map := Injective.piMap + /-- Composition by an injective function on the left is itself injective. -/ -theorem Injective.comp_left {g : β → γ} (hg : Function.Injective g) : - Function.Injective (g ∘ · : (α → β) → α → γ) := - fun _ _ hgf ↦ funext fun i ↦ hg <| (congr_fun hgf i : _) +theorem Injective.comp_left {g : β → γ} (hg : Injective g) : Injective (g ∘ · : (α → β) → α → γ) := + .piMap fun _ ↦ hg theorem injective_of_subsingleton [Subsingleton α] (f : α → β) : Injective f := fun _ _ _ ↦ Subsingleton.elim _ _ @@ -359,7 +364,7 @@ end section InvFun -variable {α β : Sort*} [Nonempty α] {f : α → β} {a : α} {b : β} +variable {α β : Sort*} [Nonempty α] {f : α → β} {b : β} attribute [local instance] Classical.propDecidable @@ -442,10 +447,22 @@ theorem surjective_to_subsingleton [na : Nonempty α] [Subsingleton β] (f : α Surjective f := fun _ ↦ let ⟨a⟩ := na; ⟨a, Subsingleton.elim _ _⟩ +theorem Surjective.piMap {ι : Sort*} {α β : ι → Sort*} {f : ∀ i, α i → β i} + (hf : ∀ i, Surjective (f i)) : Surjective (Pi.map f) := fun g ↦ + ⟨fun i ↦ surjInv (hf i) (g i), funext fun _ ↦ rightInverse_surjInv _ _⟩ + +@[deprecated (since := "2024-10-06")] alias surjective_pi_map := Surjective.piMap + /-- Composition by a surjective function on the left is itself surjective. -/ theorem Surjective.comp_left {g : β → γ} (hg : Surjective g) : - Surjective (g ∘ · : (α → β) → α → γ) := fun f ↦ - ⟨surjInv hg ∘ f, funext fun _ ↦ rightInverse_surjInv _ _⟩ + Surjective (g ∘ · : (α → β) → α → γ) := + .piMap fun _ ↦ hg + +theorem Bijective.piMap {ι : Sort*} {α β : ι → Sort*} {f : ∀ i, α i → β i} + (hf : ∀ i, Bijective (f i)) : Bijective (Pi.map f) := + ⟨.piMap fun i ↦ (hf i).1, .piMap fun i ↦ (hf i).2⟩ + +@[deprecated (since := "2024-10-06")] alias bijective_pi_map := Bijective.piMap /-- Composition by a bijective function on the left is itself bijective. -/ theorem Bijective.comp_left {g : β → γ} (hg : Bijective g) : @@ -457,7 +474,7 @@ end SurjInv section Update variable {α : Sort u} {β : α → Sort v} {α' : Sort w} [DecidableEq α] - {f g : (a : α) → β a} {a : α} {b : β a} + {f : (a : α) → β a} {a : α} {b : β a} /-- Replacing the value of a function at a given point by a given value. -/ diff --git a/Mathlib/Logic/Function/CompTypeclasses.lean b/Mathlib/Logic/Function/CompTypeclasses.lean index 7fcd8ca32286c..69d8ee1e0294f 100644 --- a/Mathlib/Logic/Function/CompTypeclasses.lean +++ b/Mathlib/Logic/Function/CompTypeclasses.lean @@ -24,7 +24,7 @@ TODO : section CompTriple /-- Class of composing triples -/ -class CompTriple {M N P : Type*} (φ : M → N) (ψ : N → P) (χ : outParam (M → P)) : Prop where +class CompTriple {M N P : Type*} (φ : M → N) (ψ : N → P) (χ : outParam (M → P)) : Prop where /-- The maps form a commuting triangle -/ comp_eq : ψ.comp φ = χ diff --git a/Mathlib/Logic/Function/Conjugate.lean b/Mathlib/Logic/Function/Conjugate.lean index 76dc5be2b2999..69098eb142cbf 100644 --- a/Mathlib/Logic/Function/Conjugate.lean +++ b/Mathlib/Logic/Function/Conjugate.lean @@ -31,7 +31,7 @@ def Semiconj (f : α → β) (ga : α → α) (gb : β → β) : Prop := namespace Semiconj -variable {f fab : α → β} {fbc : β → γ} {ga ga' : α → α} {gb gb' : β → β} {gc gc' : γ → γ} +variable {f fab : α → β} {fbc : β → γ} {ga ga' : α → α} {gb gb' : β → β} {gc : γ → γ} /-- 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 diff --git a/Mathlib/Logic/Function/Defs.lean b/Mathlib/Logic/Function/Defs.lean index 78f83b38c66c0..ab1505baf76fa 100644 --- a/Mathlib/Logic/Function/Defs.lean +++ b/Mathlib/Logic/Function/Defs.lean @@ -203,3 +203,16 @@ protected theorem RightInverse.id {g : β → α} {f : α → β} (h : RightInve def IsFixedPt (f : α → α) (x : α) := f x = x end Function + +namespace Pi + +variable {ι : Sort*} {α β : ι → Sort*} + +/-- Sends a dependent function `a : ∀ i, α i` to a dependent function `Pi.map f a : ∀ i, β i` +by applying `f i` to `i`-th component. -/ +protected def map (f : ∀ i, α i → β i) : (∀ i, α i) → (∀ i, β i) := fun a i ↦ f i (a i) + +@[simp] +lemma map_apply (f : ∀ i, α i → β i) (a : ∀ i, α i) (i : ι) : Pi.map f a i = f i (a i) := rfl + +end Pi diff --git a/Mathlib/Logic/Function/FiberPartition.lean b/Mathlib/Logic/Function/FiberPartition.lean index e82895e5b975f..e1463b5d0e46b 100644 --- a/Mathlib/Logic/Function/FiberPartition.lean +++ b/Mathlib/Logic/Function/FiberPartition.lean @@ -62,7 +62,7 @@ lemma fiber_nonempty (f : Y → Z) (a : Fiber f) : Set.Nonempty a.val := by rw [mem_iff_eq_image, ← map_preimage_eq_image] lemma map_preimage_eq_image_map {W : Type*} (f : Y → Z) (g : Z → W) (a : Fiber (g ∘ f)) : - g (f a.preimage) = a.image := by rw [← map_preimage_eq_image]; rfl + g (f a.preimage) = a.image := by rw [← map_preimage_eq_image, comp_apply] lemma image_eq_image_mk (f : Y → Z) (g : X → Y) (a : Fiber (f ∘ g)) : a.image = (Fiber.mk f (g (a.preimage _))).image := by diff --git a/Mathlib/Logic/Godel/GodelBetaFunction.lean b/Mathlib/Logic/Godel/GodelBetaFunction.lean index 4fe1e162e2c5a..52ef094f4d92b 100644 --- a/Mathlib/Logic/Godel/GodelBetaFunction.lean +++ b/Mathlib/Logic/Godel/GodelBetaFunction.lean @@ -76,8 +76,7 @@ private lemma pairwise_coprime_coprimes (a : Fin m → ℕ) : Pairwise (Coprime have hja : j < supOfSeq a := lt_of_lt_of_le j.prop (le_step (le_max_left _ _)) exact coprime_mul_succ (Nat.succ_le_succ <| le_of_lt ltij) - (Nat.dvd_factorial - (by simp [Nat.succ_sub_succ, ltij]) + (Nat.dvd_factorial (by omega) (by simpa only [Nat.succ_sub_succ] using le_of_lt (lt_of_le_of_lt (sub_le j i) hja))) /-- Gödel's Beta Function. This is similar to `(Encodable.decodeList).get i`, but it is easier to diff --git a/Mathlib/Logic/Lemmas.lean b/Mathlib/Logic/Lemmas.lean index 1056a7ffc156f..3e92a9dc21060 100644 --- a/Mathlib/Logic/Lemmas.lean +++ b/Mathlib/Logic/Lemmas.lean @@ -24,7 +24,7 @@ theorem iff_right_comm {a b c : Prop} : ((a ↔ b) ↔ c) ↔ ((a ↔ c) ↔ b) protected alias ⟨HEq.eq, Eq.heq⟩ := heq_iff_eq -variable {α : Sort*} {p q r : Prop} [Decidable p] [Decidable q] {a b c : α} +variable {α : Sort*} {p q : Prop} [Decidable p] [Decidable q] {a b c : α} theorem dite_dite_distrib_left {a : p → α} {b : ¬p → q → α} {c : ¬p → ¬q → α} : (dite p a fun hp ↦ dite q (b hp) (c hp)) = diff --git a/Mathlib/Logic/Nonempty.lean b/Mathlib/Logic/Nonempty.lean index 1a52ca02ab2d4..1c8198b9475d3 100644 --- a/Mathlib/Logic/Nonempty.lean +++ b/Mathlib/Logic/Nonempty.lean @@ -99,13 +99,6 @@ theorem Nonempty.elim_to_inhabited {α : Sort*} [h : Nonempty α] {p : Prop} (f p := h.elim <| f ∘ Inhabited.mk -protected instance Prod.instNonempty {α β} [h : Nonempty α] [h2 : Nonempty β] : Nonempty (α × β) := - h.elim fun g ↦ h2.elim fun g2 ↦ ⟨⟨g, g2⟩⟩ - -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.instNonempty _ _⟩ diff --git a/Mathlib/Logic/Pairwise.lean b/Mathlib/Logic/Pairwise.lean index 26dd58b7b3c9e..13ae772203bbe 100644 --- a/Mathlib/Logic/Pairwise.lean +++ b/Mathlib/Logic/Pairwise.lean @@ -21,11 +21,11 @@ This file defines pairwise relations. open Set Function -variable {α β γ ι ι' : Type*} {r p q : α → α → Prop} +variable {α β ι : Type*} {r p : α → α → Prop} section Pairwise -variable {f g : ι → α} {s t u : Set α} {a b : α} +variable {f : ι → α} {s : Set α} {a b : α} /-- A relation `r` holds pairwise if `r i j` for all `i ≠ j`. -/ def Pairwise (r : α → α → Prop) := diff --git a/Mathlib/Logic/Relation.lean b/Mathlib/Logic/Relation.lean index bbe9ad200f0ca..2a90c042f467f 100644 --- a/Mathlib/Logic/Relation.lean +++ b/Mathlib/Logic/Relation.lean @@ -213,7 +213,7 @@ instance [Decidable (∃ a b, r a b ∧ f a = c ∧ g b = d)] : Decidable (Relat end Map -variable {r : α → α → Prop} {a b c d : α} +variable {r : α → α → Prop} {a b c : α} /-- `ReflTransGen r`: reflexive transitive closure of `r` -/ @[mk_iff ReflTransGen.cases_tail_iff] diff --git a/Mathlib/Logic/Relator.lean b/Mathlib/Logic/Relator.lean index 7e0f0e054c1ac..17ab1660850b2 100644 --- a/Mathlib/Logic/Relator.lean +++ b/Mathlib/Logic/Relator.lean @@ -96,8 +96,8 @@ lemma rel_not : (Iff ⇒ Iff) Not Not := lemma bi_total_eq {α : Type u₁} : Relator.BiTotal (@Eq α) := { left := fun a => ⟨a, rfl⟩, right := fun a => ⟨a, rfl⟩ } -variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} -variable {r : α → β → Prop} {p : β → γ → Prop} {q : γ → δ → Prop} +variable {α : Type*} {β : Type*} {γ : Type*} +variable {r : α → β → Prop} lemma LeftUnique.flip (h : LeftUnique r) : RightUnique (flip r) := fun _ _ _ h₁ h₂ => h h₁ h₂ @@ -116,7 +116,7 @@ lemma rel_eq {r : α → β → Prop} (hr : BiUnique r) : (r ⇒ r ⇒ (·↔·) open Function -variable {α : Type*} {r₁₁ : α → α → Prop} {r₁₂ : α → β → Prop} {r₂₁ : β → α → Prop} +variable {r₁₁ : α → α → Prop} {r₁₂ : α → β → Prop} {r₂₁ : β → α → Prop} {r₂₃ : β → γ → Prop} {r₁₃ : α → γ → Prop} namespace LeftTotal diff --git a/Mathlib/Logic/Unique.lean b/Mathlib/Logic/Unique.lean index 145bc1d43f421..5aad9af23a014 100644 --- a/Mathlib/Logic/Unique.lean +++ b/Mathlib/Logic/Unique.lean @@ -141,10 +141,14 @@ abbrev mk' (α : Sort u) [h₁ : Inhabited α] [Subsingleton α] : Unique α := end Unique +theorem nonempty_unique (α : Sort u) [Subsingleton α] [Nonempty α] : Nonempty (Unique α) := by + inhabit α + exact ⟨Unique.mk' α⟩ + theorem unique_iff_subsingleton_and_nonempty (α : Sort u) : Nonempty (Unique α) ↔ Subsingleton α ∧ Nonempty α := ⟨fun ⟨u⟩ ↦ by constructor <;> exact inferInstance, - fun ⟨hs, hn⟩ ↦ ⟨by inhabit α; exact Unique.mk' α⟩⟩ + fun ⟨hs, hn⟩ ↦ nonempty_unique α⟩ variable {α : Sort*} @@ -247,7 +251,6 @@ instance {α} [IsEmpty α] : Unique (Option α) := end Option section Subtype -variable {α : Sort u} instance Unique.subtypeEq (y : α) : Unique { x // x = y } where default := ⟨y, rfl⟩ diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean index 4c6af21ff5643..b7ac515ab27d0 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Basic.lean @@ -502,9 +502,8 @@ instance (priority := 100) ContinuousSub.measurableSub [Sub γ] [ContinuousSub measurable_sub_const _ := (continuous_id.sub continuous_const).measurable @[to_additive] -instance (priority := 100) TopologicalGroup.measurableInv [Group γ] [TopologicalGroup γ] : - MeasurableInv γ := - ⟨continuous_inv.measurable⟩ +instance (priority := 100) ContinuousInv.measurableInv [Inv γ] [ContinuousInv γ] : + MeasurableInv γ := ⟨continuous_inv.measurable⟩ @[to_additive] instance (priority := 100) ContinuousSMul.measurableSMul {M α} [TopologicalSpace M] diff --git a/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean b/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean index e0029edb7097f..4bd14a8a98d53 100644 --- a/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean +++ b/Mathlib/MeasureTheory/Constructions/BorelSpace/Order.lean @@ -568,7 +568,8 @@ theorem Measurable.isLUB_of_mem {ι} [Countable ι] {f : ι → δ → α} {g g' · simp [hb, hg' hb] rw [this] exact Measurable.piecewise hs measurable_const g'_meas - · let f' : ι → δ → α := fun i ↦ s.piecewise (f i) g' + · have : Nonempty ι := ⟨i⟩ + let f' : ι → δ → α := fun i ↦ s.piecewise (f i) g' suffices ∀ b, IsLUB { a | ∃ i, f' i b = a } (g b) from Measurable.isLUB (fun i ↦ Measurable.piecewise hs (hf i) g'_meas) this intro b @@ -576,14 +577,7 @@ theorem Measurable.isLUB_of_mem {ι} [Countable ι] {f : ι → δ → α} {g g' · have A : ∀ i, f' i b = f i b := fun i ↦ by simp [f', hb] simpa [A] using hg b hb · have A : ∀ i, f' i b = g' b := fun i ↦ by simp [f', hb] - have : {a | ∃ (_i : ι), g' b = a} = {g' b} := by - apply Subset.antisymm - · rintro - ⟨_j, rfl⟩ - simp only [mem_singleton_iff] - · rintro - rfl - exact ⟨i, rfl⟩ - simp only [exists_prop'] at this - simp [A, this, hg' hb, isLUB_singleton] + simp [A, hg' hb, isLUB_singleton] theorem AEMeasurable.isLUB {ι} {μ : Measure δ} [Countable ι] {f : ι → δ → α} {g : δ → α} (hf : ∀ i, AEMeasurable (f i) μ) (hg : ∀ᵐ b ∂μ, IsLUB { a | ∃ i, f i b = a } (g b)) : diff --git a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean b/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean index 9326504897129..01b32e29b00ee 100644 --- a/Mathlib/MeasureTheory/Constructions/HaarToSphere.lean +++ b/Mathlib/MeasureTheory/Constructions/HaarToSphere.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 Mathlib.Algebra.Order.Pointwise +import Mathlib.Algebra.Order.Field.Pointwise import Mathlib.Analysis.NormedSpace.SphereNormEquiv import Mathlib.Analysis.SpecialFunctions.Integrals import Mathlib.MeasureTheory.Constructions.Prod.Integral @@ -27,7 +27,7 @@ for a general nontrivial normed space. open Set Function Metric MeasurableSpace intervalIntegral open scoped Pointwise ENNReal NNReal -local notation "dim" => FiniteDimensional.finrank ℝ +local notation "dim" => Module.finrank ℝ noncomputable section namespace MeasureTheory @@ -39,7 +39,7 @@ namespace Measure /-- If `μ` is an additive Haar measure on a normed space `E`, then `μ.toSphere` is the measure on the unit sphere in `E` -such that `μ.toSphere s = FiniteDimensional.finrank ℝ E • μ (Set.Ioo (0 : ℝ) 1 • s)`. -/ +such that `μ.toSphere s = Module.finrank ℝ E • μ (Set.Ioo (0 : ℝ) 1 • s)`. -/ def toSphere (μ : Measure E) : Measure (sphere (0 : E) 1) := dim E • ((μ.comap (Subtype.val ∘ (homeomorphUnitSphereProd E).symm)).restrict (univ ×ˢ Iio ⟨1, mem_Ioi.2 one_pos⟩)).fst @@ -106,7 +106,7 @@ instance (n : ℕ) : SigmaFinite (volumeIoiPow n) := /-- The homeomorphism `homeomorphUnitSphereProd E` sends an additive Haar measure `μ` to the product of `μ.toSphere` and `MeasureTheory.Measure.volumeIoiPow (dim E - 1)`, -where `dim E = FiniteDimensional.finrank ℝ E` is the dimension of `E`. -/ +where `dim E = Module.finrank ℝ E` is the dimension of `E`. -/ theorem measurePreserving_homeomorphUnitSphereProd : MeasurePreserving (homeomorphUnitSphereProd E) (μ.comap (↑)) (μ.toSphere.prod (volumeIoiPow (dim E - 1))) := by @@ -119,7 +119,7 @@ theorem measurePreserving_homeomorphUnitSphereProd : fun s hs ↦ forall_mem_range.2 fun r ↦ ?_ have : Ioo (0 : ℝ) r = r.1 • Ioo (0 : ℝ) 1 := by rw [LinearOrderedField.smul_Ioo r.2.out, smul_zero, smul_eq_mul, mul_one] - have hpos : 0 < dim E := FiniteDimensional.finrank_pos + have hpos : 0 < dim E := Module.finrank_pos rw [(Homeomorph.measurableEmbedding _).map_apply, toSphere_apply' _ hs, volumeIoiPow_apply_Iio, comap_subtype_coe_apply (measurableSet_singleton _).compl, toSphere_apply_aux, this, smul_assoc, μ.addHaar_smul_of_nonneg r.2.out.le, Nat.sub_add_cancel hpos, Nat.cast_pred hpos, @@ -147,7 +147,7 @@ lemma integral_fun_norm_addHaar (f : ℝ → F) : rw [integral_withDensity_eq_integral_smul, μ.toSphere_apply_univ, ENNReal.toReal_mul, ENNReal.toReal_nat, ← nsmul_eq_mul, smul_assoc, integral_subtype_comap measurableSet_Ioi fun a ↦ Real.toNNReal (a ^ (dim E - 1)) • f a, - setIntegral_congr measurableSet_Ioi fun x hx ↦ ?_] + setIntegral_congr_fun measurableSet_Ioi fun x hx ↦ ?_] · rw [NNReal.smul_def, Real.coe_toNNReal _ (pow_nonneg hx.out.le _)] · exact (measurable_subtype_coe.pow_const _).real_toNNReal diff --git a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean index f1677d8c92db5..89db09097d3cb 100644 --- a/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean +++ b/Mathlib/MeasureTheory/Constructions/Polish/Basic.lean @@ -343,7 +343,7 @@ protected lemma AnalyticSet.preimage {X Y : Type*} [TopologicalSpace X] [Topolog [PolishSpace X] [T2Space Y] {s : Set Y} (hs : AnalyticSet s) {f : X → Y} (hf : Continuous f) : AnalyticSet (f ⁻¹' s) := by rcases analyticSet_iff_exists_polishSpace_range.1 hs with ⟨Z, _, _, g, hg, rfl⟩ - have : IsClosed {x : X × Z | f x.1 = g x.2} := isClosed_diagonal.preimage (hf.prod_map hg) + have : IsClosed {x : X × Z | f x.1 = g x.2} := isClosed_eq hf.fst' hg.snd' convert this.analyticSet.image_of_continuous continuous_fst ext x simp [eq_comm] diff --git a/Mathlib/MeasureTheory/Constructions/Projective.lean b/Mathlib/MeasureTheory/Constructions/Projective.lean index 1754b6934c461..37ef05c547f45 100644 --- a/Mathlib/MeasureTheory/Constructions/Projective.lean +++ b/Mathlib/MeasureTheory/Constructions/Projective.lean @@ -46,6 +46,16 @@ namespace IsProjectiveMeasureFamily variable {I J : Finset ι} +lemma eq_zero_of_isEmpty [h : IsEmpty (Π i, α i)] + (hP : IsProjectiveMeasureFamily P) (I : Finset ι) : + P I = 0 := by + classical + obtain ⟨i, hi⟩ := isEmpty_pi.mp h + rw [hP (insert i I) I (I.subset_insert i)] + have : IsEmpty (Π j : ↑(insert i I), α j) := by simp [hi] + rw [(P (insert i I)).eq_zero_of_isEmpty] + simp + /-- Auxiliary lemma for `measure_univ_eq`. -/ lemma measure_univ_eq_of_subset (hP : IsProjectiveMeasureFamily P) (hJI : J ⊆ I) : P I univ = P J univ := by diff --git a/Mathlib/MeasureTheory/Covering/Besicovitch.lean b/Mathlib/MeasureTheory/Covering/Besicovitch.lean index 466e9d9155efd..91cc3db5e2be0 100644 --- a/Mathlib/MeasureTheory/Covering/Besicovitch.lean +++ b/Mathlib/MeasureTheory/Covering/Besicovitch.lean @@ -309,7 +309,7 @@ theorem mem_iUnionUpTo_lastStep (x : β) : p.c x ∈ p.iUnionUpTo p.lastStep := apply lt_trans (mul_pos (_root_.zero_lt_one.trans p.one_lt_tau) (p.rpos _)) H 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 + exact mul_lt_mul (inv_lt_one_of_one_lt₀ 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 have := exists_lt_of_lt_csSup ?_ B · simpa only [exists_prop, mem_range, exists_exists_and_eq_and, Subtype.exists, diff --git a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean index 60ca4af5a4851..2c3bc40927bd3 100644 --- a/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean +++ b/Mathlib/MeasureTheory/Covering/BesicovitchVectorSpace.lean @@ -43,7 +43,7 @@ In particular, this number is bounded by `5 ^ dim` by a straightforward measure universe u -open Metric Set FiniteDimensional MeasureTheory Filter Fin +open Metric Set Module MeasureTheory Filter Fin open scoped ENNReal Topology diff --git a/Mathlib/MeasureTheory/Covering/DensityTheorem.lean b/Mathlib/MeasureTheory/Covering/DensityTheorem.lean index 51f94e3d8e12d..62c58768b78a6 100644 --- a/Mathlib/MeasureTheory/Covering/DensityTheorem.lean +++ b/Mathlib/MeasureTheory/Covering/DensityTheorem.lean @@ -123,7 +123,7 @@ theorem tendsto_closedBall_filterAt {K : ℝ} {x : α} {ι : Type*} {l : Filter apply (((Metric.tendsto_nhds.mp δlim _ (div_pos hε hK)).and δpos).and xmem).mono rintro j ⟨⟨hjε, hj₀ : 0 < δ j⟩, hx⟩ y hy replace hjε : (K + 1) * δ j < ε := by - simpa [abs_eq_self.mpr hj₀.le] using (lt_div_iff' hK).mp hjε + simpa [abs_eq_self.mpr hj₀.le] using (lt_div_iff₀' hK).mp hjε simp only [mem_closedBall] at hx hy ⊢ linarith [dist_triangle_right y x (w j)] diff --git a/Mathlib/MeasureTheory/Covering/Differentiation.lean b/Mathlib/MeasureTheory/Covering/Differentiation.lean index 4af0418c40a8e..803d605ca1b7f 100644 --- a/Mathlib/MeasureTheory/Covering/Differentiation.lean +++ b/Mathlib/MeasureTheory/Covering/Differentiation.lean @@ -573,7 +573,7 @@ theorem withDensity_le_mul {s : Set α} (hs : MeasurableSet s) {t : ℝ≥0} (ht conv_rhs => rw [← mul_one (t ^ n)] gcongr rw [zpow_neg_one] - exact inv_lt_one ht + exact inv_lt_one_of_one_lt₀ ht calc ν s = ν (s ∩ f ⁻¹' {0}) + ν (s ∩ f ⁻¹' {∞}) + diff --git a/Mathlib/MeasureTheory/Covering/Vitali.lean b/Mathlib/MeasureTheory/Covering/Vitali.lean index 5928bb689a9c9..364031a842a49 100644 --- a/Mathlib/MeasureTheory/Covering/Vitali.lean +++ b/Mathlib/MeasureTheory/Covering/Vitali.lean @@ -112,7 +112,7 @@ theorem exists_disjoint_subfamily_covering_enlargment (B : ι → Set α) (t : S · refine ⟨a, ⟨hat, a_disj⟩, ?_⟩ simpa only [← mzero, zero_div] using δnonneg a hat · have I : m / τ < m := by - rw [div_lt_iff (zero_lt_one.trans hτ)] + 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 (Anonempty.image _) I with ⟨x, xA, hx⟩ diff --git a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean index 48bb69b5fadb2..83a31d388715d 100644 --- a/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean +++ b/Mathlib/MeasureTheory/Decomposition/RadonNikodym.lean @@ -305,6 +305,9 @@ lemma setLIntegral_rnDeriv_le (s : Set α) : @[deprecated (since := "2024-06-29")] alias set_lintegral_rnDeriv_le := setLIntegral_rnDeriv_le +lemma lintegral_rnDeriv_le : ∫⁻ x, μ.rnDeriv ν x ∂ν ≤ μ Set.univ := + (setLIntegral_univ _).symm ▸ Measure.setLIntegral_rnDeriv_le Set.univ + lemma setLIntegral_rnDeriv' [HaveLebesgueDecomposition μ ν] (hμν : μ ≪ ν) {s : Set α} (hs : MeasurableSet s) : ∫⁻ x in s, μ.rnDeriv ν x ∂ν = μ s := by @@ -388,13 +391,13 @@ alias set_integral_toReal_rnDeriv := setIntegral_toReal_rnDeriv lemma integral_toReal_rnDeriv [SigmaFinite μ] [SigmaFinite ν] (hμν : μ ≪ ν) : ∫ x, (μ.rnDeriv ν x).toReal ∂ν = (μ Set.univ).toReal := by - rw [← integral_univ, setIntegral_toReal_rnDeriv hμν Set.univ] + rw [← setIntegral_univ, setIntegral_toReal_rnDeriv hμν Set.univ] lemma integral_toReal_rnDeriv' [IsFiniteMeasure μ] [SigmaFinite ν] : ∫ x, (μ.rnDeriv ν x).toReal ∂ν = (μ Set.univ).toReal - (μ.singularPart ν Set.univ).toReal := by rw [← ENNReal.toReal_sub_of_le (μ.singularPart_le ν Set.univ) (measure_ne_top _ _), ← Measure.sub_apply .univ (Measure.singularPart_le μ ν), Measure.measure_sub_singularPart, - ← Measure.setIntegral_toReal_rnDeriv_eq_withDensity, integral_univ] + ← Measure.setIntegral_toReal_rnDeriv_eq_withDensity, setIntegral_univ] end integral @@ -563,8 +566,8 @@ theorem integral_rnDeriv_smul [HaveLebesgueDecomposition μ ν] (hμν : μ ≪ [SigmaFinite μ] {f : α → E} : ∫ x, (μ.rnDeriv ν x).toReal • f x ∂ν = ∫ x, f x ∂μ := by by_cases hf : Integrable f μ - · rw [← integral_univ, ← withDensityᵥ_apply ((integrable_rnDeriv_smul_iff hμν).mpr hf) .univ, - ← integral_univ, ← withDensityᵥ_apply hf .univ, withDensityᵥ_rnDeriv_smul hμν hf] + · rw [← setIntegral_univ, ← withDensityᵥ_apply ((integrable_rnDeriv_smul_iff hμν).mpr hf) .univ, + ← setIntegral_univ, ← withDensityᵥ_apply hf .univ, withDensityᵥ_rnDeriv_smul hμν hf] · rw [integral_undef hf, integral_undef] contrapose! hf exact (integrable_rnDeriv_smul_iff hμν).mp hf diff --git a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean index 947cbabbc4212..77cd7b8a79759 100644 --- a/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean +++ b/Mathlib/MeasureTheory/Decomposition/SignedHahn.lean @@ -312,7 +312,7 @@ theorem exists_subset_restrict_nonpos (hi : s i < 0) : · have : 1 / s E < bdd k := by linarith only [le_of_max_le_left (hk k le_rfl)] rw [one_div] at this ⊢ - rwa [inv_lt (lt_trans (inv_pos.2 hE₃) this) hE₃] + exact inv_lt_of_inv_lt₀ hE₃ this obtain ⟨k, hk₁, hk₂⟩ := this have hA' : A ⊆ i \ ⋃ l ≤ k, restrictNonposSeq s i l := by apply Set.diff_subset_diff_right diff --git a/Mathlib/MeasureTheory/Function/AEEqFun.lean b/Mathlib/MeasureTheory/Function/AEEqFun.lean index 77d4374b0ee83..000e0416082a7 100644 --- a/Mathlib/MeasureTheory/Function/AEEqFun.lean +++ b/Mathlib/MeasureTheory/Function/AEEqFun.lean @@ -5,7 +5,7 @@ Authors: Johannes Hölzl, Zhouhang Zhou -/ import Mathlib.MeasureTheory.Integral.Lebesgue import Mathlib.Order.Filter.Germ.Basic -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.MeasureTheory.Function.StronglyMeasurable.Basic /-! diff --git a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean index 37c95e1795cb8..d9303573bf9fd 100644 --- a/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean +++ b/Mathlib/MeasureTheory/Function/AEEqOfIntegral.lean @@ -63,7 +63,7 @@ theorem ae_eq_zero_of_forall_inner [NormedAddCommGroup E] [InnerProductSpace rw [Pi.zero_apply, ← @inner_self_eq_zero 𝕜] have h_closed : IsClosed {c : E | inner c (f x) = (0 : 𝕜)} := isClosed_eq (continuous_id.inner continuous_const) continuous_const - exact @isClosed_property ℕ E _ s (fun c => inner c (f x) = (0 : 𝕜)) hs h_closed (fun n => hx n) _ + exact @isClosed_property ℕ E _ s (fun c => inner c (f x) = (0 : 𝕜)) hs h_closed hx _ local notation "⟪" x ", " y "⟫" => y x @@ -590,7 +590,7 @@ lemma ae_eq_zero_of_forall_setIntegral_isClosed_eq_zero {μ : Measure β} {f : have A : ∀ (t : Set β), MeasurableSet t → ∫ (x : β) in t, f x ∂μ = 0 → ∫ (x : β) in tᶜ, f x ∂μ = 0 := by intro t t_meas ht - have I : ∫ x, f x ∂μ = 0 := by rw [← integral_univ]; exact h'f _ isClosed_univ + have I : ∫ x, f x ∂μ = 0 := by rw [← setIntegral_univ]; exact h'f _ isClosed_univ simpa [ht, I] using integral_add_compl t_meas hf intro s hs refine MeasurableSet.induction_on_open (fun U hU ↦ ?_) A (fun g g_disj g_meas hg ↦ ?_) hs diff --git a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean index daab2ab684f35..8e4660db64bc6 100644 --- a/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean +++ b/Mathlib/MeasureTheory/Function/ConditionalExpectation/Basic.lean @@ -208,7 +208,7 @@ theorem integral_condexp (hm : m ≤ m0) [hμm : SigmaFinite (μ.trim hm)] : ∫ x, (μ[f|m]) x ∂μ = ∫ x, f x ∂μ := by by_cases hf : Integrable f μ · suffices ∫ x in Set.univ, (μ[f|m]) x ∂μ = ∫ x in Set.univ, f x ∂μ by - simp_rw [integral_univ] at this; exact this + simp_rw [setIntegral_univ] at this; exact this exact setIntegral_condexp hm hf (@MeasurableSet.univ _ m) simp only [condexp_undef hf, Pi.zero_apply, integral_zero, integral_undef hf] diff --git a/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean b/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean index 31b0277e42b2f..f9a7daf12fa48 100644 --- a/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean +++ b/Mathlib/MeasureTheory/Function/ConvergenceInMeasure.lean @@ -203,12 +203,13 @@ theorem TendstoInMeasure.exists_seq_tendsto_ae (hfg : TendstoInMeasure μ f atTo refine ⟨max N (k - 1), fun n hn_ge => lt_of_le_of_lt ?_ hk_lt_ε⟩ specialize hNx n ((le_max_left _ _).trans hn_ge) have h_inv_n_le_k : (2 : ℝ)⁻¹ ^ n ≤ 2 * (2 : ℝ)⁻¹ ^ k := by - rw [mul_comm, ← inv_mul_le_iff' (zero_lt_two' ℝ)] + rw [mul_comm, ← inv_mul_le_iff₀' (zero_lt_two' ℝ)] conv_lhs => congr rw [← pow_one (2 : ℝ)⁻¹] rw [← pow_add, add_comm] - exact pow_le_pow_of_le_one (one_div (2 : ℝ) ▸ one_half_pos.le) (inv_le_one one_le_two) + exact pow_le_pow_of_le_one (one_div (2 : ℝ) ▸ one_half_pos.le) + (inv_le_one_of_one_le₀ one_le_two) ((le_tsub_add.trans (add_le_add_right (le_max_right _ _) 1)).trans (add_le_add_right hn_ge 1)) exact le_trans hNx.le h_inv_n_le_k diff --git a/Mathlib/MeasureTheory/Function/EssSup.lean b/Mathlib/MeasureTheory/Function/EssSup.lean index 926d7c0f68080..08d14b549d3b7 100644 --- a/Mathlib/MeasureTheory/Function/EssSup.lean +++ b/Mathlib/MeasureTheory/Function/EssSup.lean @@ -6,6 +6,7 @@ Authors: Rémy Degenne import Mathlib.MeasureTheory.Constructions.BorelSpace.Order import Mathlib.MeasureTheory.Measure.Count import Mathlib.Order.Filter.ENNReal +import Mathlib.Probability.UniformOn /-! # Essential supremum and infimum @@ -28,15 +29,14 @@ sense). We do not define that quantity here, which is simply the supremum of a m -/ -open MeasureTheory Filter Set TopologicalSpace - -open ENNReal MeasureTheory NNReal +open Filter MeasureTheory ProbabilityTheory Set TopologicalSpace +open scoped ENNReal NNReal variable {α β : Type*} {m : MeasurableSpace α} {μ ν : Measure α} section ConditionallyCompleteLattice -variable [ConditionallyCompleteLattice β] +variable [ConditionallyCompleteLattice β] {f : α → β} /-- Essential supremum of `f` with respect to measure `μ`: the smallest `c : β` such that `f x ≤ c` a.e. -/ @@ -68,6 +68,40 @@ theorem essSup_const (c : β) (hμ : μ ≠ 0) : essSup (fun _ : α => c) μ = c theorem essInf_const (c : β) (hμ : μ ≠ 0) : essInf (fun _ : α => c) μ = c := have := NeZero.mk hμ; essInf_const' _ +section SMul +variable {R : Type*} [Zero R] [SMulWithZero R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] + [NoZeroSMulDivisors R ℝ≥0∞] {c : R} + +@[simp] +lemma essSup_smul_measure (hc : c ≠ 0) (f : α → β) : essSup f (c • μ) = essSup f μ := by + simp_rw [essSup, Measure.ae_smul_measure_eq hc] + +end SMul + +variable [Nonempty α] + +lemma essSup_eq_ciSup (hμ : ∀ a, μ {a} ≠ 0) (hf : BddAbove (Set.range f)) : + essSup f μ = ⨆ a, f a := by rw [essSup, ae_eq_top.2 hμ, limsup_top_eq_ciSup hf] + +lemma essInf_eq_ciInf (hμ : ∀ a, μ {a} ≠ 0) (hf : BddBelow (Set.range f)) : + essInf f μ = ⨅ a, f a := by rw [essInf, ae_eq_top.2 hμ, liminf_top_eq_ciInf hf] + +variable [MeasurableSingletonClass α] + +@[simp] lemma essSup_count_eq_ciSup (hf : BddAbove (Set.range f)) : + essSup f .count = ⨆ a, f a := essSup_eq_ciSup (by simp) hf + +@[simp] lemma essInf_count_eq_ciInf (hf : BddBelow (Set.range f)) : + essInf f .count = ⨅ a, f a := essInf_eq_ciInf (by simp) hf + +@[simp] lemma essSup_uniformOn_eq_ciSup [Finite α] (hf : BddAbove (Set.range f)) : + essSup f (uniformOn univ) = ⨆ a, f a := + essSup_eq_ciSup (by simp [uniformOn, cond_apply, Set.finite_univ]) hf + +@[simp] lemma essInf_cond_count_eq_ciInf [Finite α] (hf : BddBelow (Set.range f)) : + essInf f (uniformOn univ) = ⨅ a, f a := + essInf_eq_ciInf (by simp [uniformOn, cond_apply, Set.finite_univ]) hf + end ConditionallyCompleteLattice section ConditionallyCompleteLinearOrder @@ -172,10 +206,6 @@ theorem essInf_antitone_measure {f : α → β} (hμν : μ ≪ ν) : essInf f refine liminf_le_liminf_of_le (Measure.ae_le_iff_absolutelyContinuous.mpr hμν) ?_ ?_ all_goals isBoundedDefault -theorem essSup_smul_measure {f : α → β} {c : ℝ≥0∞} (hc : c ≠ 0) : - essSup f (c • μ) = essSup f μ := by - simp_rw [essSup, Measure.ae_smul_measure_eq hc] - lemma essSup_eq_iSup (hμ : ∀ a, μ {a} ≠ 0) (f : α → β) : essSup f μ = ⨆ i, f i := by rw [essSup, ae_eq_top.2 hμ, limsup_top_eq_iSup] diff --git a/Mathlib/MeasureTheory/Function/Intersectivity.lean b/Mathlib/MeasureTheory/Function/Intersectivity.lean index 5ea828b2fcf5b..c571061c05018 100644 --- a/Mathlib/MeasureTheory/Function/Intersectivity.lean +++ b/Mathlib/MeasureTheory/Function/Intersectivity.lean @@ -61,8 +61,7 @@ lemma bergelson' {s : ℕ → Set α} (hs : ∀ n, MeasurableSet (s n)) (hr₀ : have hfapp : ∀ n a, f n a = (↑(n + 1))⁻¹ * ∑ k in Finset.range (n + 1), (s k).indicator 1 a := by simp only [f, Pi.natCast_def, Pi.smul_apply, Pi.inv_apply, Finset.sum_apply, eq_self_iff_true, forall_const, imp_true_iff, smul_eq_mul] - have hf n : Measurable (f n) := Measurable.mul' (@measurable_const ℝ≥0∞ _ _ _ (↑(n + 1))⁻¹) - (Finset.measurable_sum' _ fun i _ ↦ measurable_one.indicator <| hs i) + have hf n : Measurable (f n) := by fun_prop (disch := exact hs _) have hf₁ n : f n ≤ 1 := by rintro a rw [hfapp, ← ENNReal.div_eq_inv_mul] diff --git a/Mathlib/MeasureTheory/Function/Jacobian.lean b/Mathlib/MeasureTheory/Function/Jacobian.lean index 3b9bc2e1d765d..ce6116b747cb5 100644 --- a/Mathlib/MeasureTheory/Function/Jacobian.lean +++ b/Mathlib/MeasureTheory/Function/Jacobian.lean @@ -87,7 +87,7 @@ Change of variables in integrals [Fremlin, *Measure Theory* (volume 2)][fremlin_vol2] -/ -open MeasureTheory MeasureTheory.Measure Metric Filter Set FiniteDimensional Asymptotics +open MeasureTheory MeasureTheory.Measure Metric Filter Set Module Asymptotics TopologicalSpace open scoped NNReal ENNReal Topology Pointwise @@ -1185,7 +1185,7 @@ theorem det_one_smulRight {𝕜 : Type*} [NormedField 𝕜] (v : 𝕜) : Algebra.id.smul_eq_mul, one_mul, ContinuousLinearMap.coe_smul', Pi.smul_apply, mul_one] rw [this, ContinuousLinearMap.det, ContinuousLinearMap.coe_smul, ContinuousLinearMap.one_def, ContinuousLinearMap.coe_id, LinearMap.det_smul, - FiniteDimensional.finrank_self, LinearMap.det_id, pow_one, mul_one] + Module.finrank_self, LinearMap.det_id, pow_one, mul_one] /-- Integrability in the change of variable formula for differentiable functions (one-variable version): if a function `f` is injective and differentiable on a measurable set `s ⊆ ℝ`, then a diff --git a/Mathlib/MeasureTheory/Function/L1Space.lean b/Mathlib/MeasureTheory/Function/L1Space.lean index 4e6447b519aa1..9994ae4d6e8b1 100644 --- a/Mathlib/MeasureTheory/Function/L1Space.lean +++ b/Mathlib/MeasureTheory/Function/L1Space.lean @@ -438,9 +438,13 @@ theorem integrable_const [IsFiniteMeasure μ] (c : β) : Integrable (fun _ : α integrable_const_iff.2 <| Or.inr <| measure_lt_top _ _ @[simp] -theorem Integrable.of_finite [Finite α] [MeasurableSpace α] [MeasurableSingletonClass α] - (μ : Measure α) [IsFiniteMeasure μ] (f : α → β) : Integrable (fun a ↦ f a) μ := - ⟨(StronglyMeasurable.of_finite f).aestronglyMeasurable, .of_finite⟩ +lemma Integrable.of_finite [Finite α] [MeasurableSingletonClass α] [IsFiniteMeasure μ] {f : α → β} : + Integrable f μ := ⟨.of_finite, .of_finite⟩ + +/-- This lemma is a special case of `Integrable.of_finite`. -/ +-- Eternal deprecation for discoverability, don't remove +@[deprecated Integrable.of_finite, nolint deprecatedNoSince] +lemma Integrable.of_isEmpty [IsEmpty α] {f : α → β} : Integrable f μ := .of_finite @[deprecated (since := "2024-02-05")] alias integrable_of_fintype := Integrable.of_finite diff --git a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean index db051f36a5bc3..0d8110dc76977 100644 --- a/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean +++ b/Mathlib/MeasureTheory/Function/LocallyIntegrable.lean @@ -127,10 +127,10 @@ theorem LocallyIntegrableOn.aestronglyMeasurable [SecondCountableTopology X] rw [this, aestronglyMeasurable_iUnion_iff] exact fun i : ℕ => (hu i).aestronglyMeasurable -/-- If `s` is either open, or closed, then `f` is locally integrable on `s` iff it is integrable on -every compact subset contained in `s`. -/ +/-- If `s` is locally closed (e.g. open or closed), then `f` is locally integrable on `s` iff it is +integrable on every compact subset contained in `s`. -/ theorem locallyIntegrableOn_iff [LocallyCompactSpace X] (hs : IsLocallyClosed s) : - LocallyIntegrableOn f s μ ↔ ∀ (k : Set X), k ⊆ s → (IsCompact k → IntegrableOn f k μ) := by + LocallyIntegrableOn f s μ ↔ ∀ (k : Set X), k ⊆ s → IsCompact k → IntegrableOn f k μ := by refine ⟨fun hf k hk ↦ hf.integrableOn_compact_subset hk, fun hf x hx ↦ ?_⟩ rcases hs with ⟨U, Z, hU, hZ, rfl⟩ rcases exists_compact_subset hU hx.1 with ⟨K, hK, hxK, hKU⟩ diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean index 75f2bb1b23b55..fdf5f19ca96be 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/Basic.lean @@ -794,10 +794,16 @@ theorem eLpNorm'_smul_measure {p : ℝ} (hp : 0 ≤ p) {f : α → F} (c : ℝ @[deprecated (since := "2024-07-27")] alias snorm'_smul_measure := eLpNorm'_smul_measure -theorem eLpNormEssSup_smul_measure {f : α → F} {c : ℝ≥0∞} (hc : c ≠ 0) : +section SMul +variable {R : Type*} [Zero R] [SMulWithZero R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] + [NoZeroSMulDivisors R ℝ≥0∞] {c : R} + +@[simp] lemma eLpNormEssSup_smul_measure (hc : c ≠ 0) (f : α → F) : eLpNormEssSup f (c • μ) = eLpNormEssSup f μ := by simp_rw [eLpNormEssSup] - exact essSup_smul_measure hc + exact essSup_smul_measure hc _ + +end SMul @[deprecated (since := "2024-07-27")] alias snormEssSup_smul_measure := eLpNormEssSup_smul_measure diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean index dcafb2aeecbec..e7723bfa145de 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/CompareExp.lean @@ -126,7 +126,7 @@ theorem eLpNorm'_lt_top_of_eLpNorm'_lt_top_of_exponent_le {p q : ℝ} [IsFiniteM _ < ∞ := by rw [ENNReal.mul_lt_top_iff] refine Or.inl ⟨hfq_lt_top, ENNReal.rpow_lt_top_of_nonneg ?_ (measure_ne_top μ Set.univ)⟩ - rwa [le_sub_comm, sub_zero, one_div, one_div, inv_le_inv hq_pos hp_pos] + rwa [le_sub_comm, sub_zero, one_div, one_div, inv_le_inv₀ hq_pos hp_pos] @[deprecated (since := "2024-07-27")] alias snorm'_lt_top_of_snorm'_lt_top_of_exponent_le := diff --git a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean index 42f9edb4bd2b4..cc56d954aa492 100644 --- a/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean +++ b/Mathlib/MeasureTheory/Function/LpSeminorm/TriangleInequality.lean @@ -88,9 +88,8 @@ theorem LpAddConst_lt_top (p : ℝ≥0∞) : LpAddConst p < ∞ := by rw [LpAddConst] split_ifs with h · apply ENNReal.rpow_lt_top_of_nonneg _ ENNReal.two_ne_top - simp only [one_div, sub_nonneg] - apply one_le_inv (ENNReal.toReal_pos h.1.ne' (h.2.trans ENNReal.one_lt_top).ne) - simpa using ENNReal.toReal_mono ENNReal.one_ne_top h.2.le + rw [one_div, sub_nonneg, ← ENNReal.toReal_inv, ← ENNReal.one_toReal] + exact ENNReal.toReal_mono (by simpa using h.1.ne') (ENNReal.one_le_inv.2 h.2.le) · exact ENNReal.one_lt_top theorem eLpNorm_add_le' (hf : AEStronglyMeasurable f μ) (hg : AEStronglyMeasurable g μ) diff --git a/Mathlib/MeasureTheory/Function/LpSpace.lean b/Mathlib/MeasureTheory/Function/LpSpace.lean index c44471de29253..22f250535cb26 100644 --- a/Mathlib/MeasureTheory/Function/LpSpace.lean +++ b/Mathlib/MeasureTheory/Function/LpSpace.lean @@ -13,7 +13,7 @@ import Mathlib.MeasureTheory.Function.LpSeminorm.TriangleInequality import Mathlib.MeasureTheory.Measure.OpenPos import Mathlib.MeasureTheory.Measure.Typeclasses import Mathlib.Analysis.NormedSpace.OperatorNorm.NormedSpace -import Mathlib.Topology.ContinuousFunction.Compact +import Mathlib.Topology.ContinuousMap.Compact import Mathlib.Order.Filter.IndicatorFunction /-! @@ -254,7 +254,7 @@ theorem nnnorm_coe_ennreal (f : Lp E p μ) : (‖f‖₊ : ℝ≥0∞) = eLpNorm @[simp] lemma norm_toLp (f : α → E) (hf : Memℒp f p μ) : ‖hf.toLp f‖ = ENNReal.toReal (eLpNorm f p μ) := by - erw [norm_def, eLpNorm_congr_ae (Memℒp.coeFn_toLp hf)] + rw [norm_def, eLpNorm_congr_ae (Memℒp.coeFn_toLp hf)] @[simp] theorem nnnorm_toLp (f : α → E) (hf : Memℒp f p μ) : @@ -1064,7 +1064,7 @@ theorem MeasureTheory.Memℒp.of_comp_antilipschitzWith {α E F} {K'} [Measurabl rw [← dist_zero_right, ← dist_zero_right, ← g0] apply hg'.le_mul_dist have B : AEStronglyMeasurable f μ := - (hg'.uniformEmbedding hg).embedding.aestronglyMeasurable_comp_iff.1 hL.1 + (hg'.isUniformEmbedding hg).embedding.aestronglyMeasurable_comp_iff.1 hL.1 exact hL.of_le_mul B (Filter.Eventually.of_forall A) namespace LipschitzWith diff --git a/Mathlib/MeasureTheory/Function/SimpleFunc.lean b/Mathlib/MeasureTheory/Function/SimpleFunc.lean index 5615eaebce091..ea3760f408df5 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFunc.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFunc.lean @@ -161,7 +161,7 @@ theorem measurableSet_preimage (f : α →ₛ β) (s) : MeasurableSet (f ⁻¹' measurableSet_cut (fun _ b => b ∈ s) f fun b => MeasurableSet.const (b ∈ s) /-- A simple function is measurable -/ -@[measurability] +@[measurability, fun_prop] protected theorem measurable [MeasurableSpace β] (f : α →ₛ β) : Measurable f := fun s _ => measurableSet_preimage f s @@ -773,7 +773,7 @@ theorem sum_eapproxDiff (f : α → ℝ≥0∞) (n : ℕ) (a : α) : induction' n with n IH · simp only [Nat.zero_add, Finset.sum_singleton, Finset.range_one] rfl - · erw [Finset.sum_range_succ, IH, eapproxDiff, coe_map, Function.comp_apply, + · rw [Finset.sum_range_succ, IH, eapproxDiff, coe_map, Function.comp_apply, coe_sub, Pi.sub_apply, ENNReal.coe_toNNReal, add_tsub_cancel_of_le (monotone_eapprox f (Nat.le_succ _) _)] apply (lt_of_le_of_lt _ (eapprox_lt_top f (n + 1) a)).ne diff --git a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean index 0386ca8b2e120..e017f36bbf06c 100644 --- a/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean +++ b/Mathlib/MeasureTheory/Function/SimpleFuncDenseLp.lean @@ -23,7 +23,7 @@ by a sequence of simple functions. measurable and `Memℒp` (for `p < ∞`), then the simple functions `SimpleFunc.approxOn f hf s 0 h₀ n` may be considered as elements of `Lp E p μ`, and they tend in Lᵖ to `f`. -* `Lp.simpleFunc.denseEmbedding`: the embedding `coeToLp` of the `Lp` simple functions into +* `Lp.simpleFunc.isDenseEmbedding`: the embedding `coeToLp` of the `Lp` simple functions into `Lp` is dense. * `Lp.simpleFunc.induction`, `Lp.induction`, `Memℒp.induction`, `Integrable.induction`: to prove a predicate for all elements of one of these classes of functions, it suffices to check that it @@ -679,16 +679,21 @@ variable [Fact (1 ≤ p)] protected theorem uniformContinuous : UniformContinuous ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := uniformContinuous_comap -protected theorem uniformEmbedding : UniformEmbedding ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := - uniformEmbedding_comap Subtype.val_injective +lemma isUniformEmbedding : IsUniformEmbedding ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := + isUniformEmbedding_comap Subtype.val_injective -protected theorem uniformInducing : UniformInducing ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := - simpleFunc.uniformEmbedding.toUniformInducing +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding -protected theorem denseEmbedding (hp_ne_top : p ≠ ∞) : - DenseEmbedding ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := by +theorem isUniformInducing : IsUniformInducing ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := + simpleFunc.isUniformEmbedding.isUniformInducing + +@[deprecated (since := "2024-10-05")] +alias uniformInducing := isUniformInducing + +lemma isDenseEmbedding (hp_ne_top : p ≠ ∞) : + IsDenseEmbedding ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := by borelize E - apply simpleFunc.uniformEmbedding.denseEmbedding + apply simpleFunc.isUniformEmbedding.isDenseEmbedding intro f rw [mem_closure_iff_seq_limit] have hfi' : Memℒp f p μ := Lp.memℒp f @@ -703,13 +708,16 @@ protected theorem denseEmbedding (hp_ne_top : p ≠ ∞) : convert SimpleFunc.tendsto_approxOn_range_Lp hp_ne_top (Lp.stronglyMeasurable f).measurable hfi' rw [toLp_coeFn f (Lp.memℒp f)] -protected theorem denseInducing (hp_ne_top : p ≠ ∞) : - DenseInducing ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := - (simpleFunc.denseEmbedding hp_ne_top).toDenseInducing +@[deprecated (since := "2024-09-30")] +alias denseEmbedding := isDenseEmbedding + +protected theorem isDenseInducing (hp_ne_top : p ≠ ∞) : + IsDenseInducing ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := + (simpleFunc.isDenseEmbedding hp_ne_top).toIsDenseInducing protected theorem denseRange (hp_ne_top : p ≠ ∞) : DenseRange ((↑) : Lp.simpleFunc E p μ → Lp E p μ) := - (simpleFunc.denseInducing hp_ne_top).dense + (simpleFunc.isDenseInducing hp_ne_top).dense protected theorem dense (hp_ne_top : p ≠ ∞) : Dense (Lp.simpleFunc E p μ : Set (Lp E p μ)) := by simpa only [denseRange_subtype_val] using simpleFunc.denseRange (E := E) (μ := μ) hp_ne_top diff --git a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean index d4eafeb177727..b9644215bcca2 100644 --- a/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean +++ b/Mathlib/MeasureTheory/Function/StronglyMeasurable/Basic.lean @@ -127,7 +127,7 @@ theorem SimpleFunc.stronglyMeasurable {α β} {_ : MeasurableSpace α} [Topologi @[nontriviality] theorem StronglyMeasurable.of_finite [Finite α] {_ : MeasurableSpace α} [MeasurableSingletonClass α] [TopologicalSpace β] - (f : α → β) : StronglyMeasurable f := + {f : α → β} : StronglyMeasurable f := ⟨fun _ => SimpleFunc.ofFinite f, fun _ => tendsto_const_nhds⟩ @[deprecated (since := "2024-02-05")] @@ -136,7 +136,7 @@ alias stronglyMeasurable_of_fintype := StronglyMeasurable.of_finite @[deprecated StronglyMeasurable.of_finite (since := "2024-02-06")] theorem stronglyMeasurable_of_isEmpty [IsEmpty α] {_ : MeasurableSpace α} [TopologicalSpace β] (f : α → β) : StronglyMeasurable f := - .of_finite f + .of_finite theorem stronglyMeasurable_const {α β} {_ : MeasurableSpace α} [TopologicalSpace β] {b : β} : StronglyMeasurable fun _ : α => b := @@ -1108,7 +1108,7 @@ variable {m : MeasurableSpace α} {μ ν : Measure α} [TopologicalSpace β] [To {f g : α → β} lemma of_finite [DiscreteMeasurableSpace α] [Finite α] : AEStronglyMeasurable f μ := - ⟨_, .of_finite _, ae_eq_rfl⟩ + ⟨_, .of_finite, ae_eq_rfl⟩ section Mk diff --git a/Mathlib/MeasureTheory/Function/UnifTight.lean b/Mathlib/MeasureTheory/Function/UnifTight.lean index cc50e8c1de965..deaea6b197602 100644 --- a/Mathlib/MeasureTheory/Function/UnifTight.lean +++ b/Mathlib/MeasureTheory/Function/UnifTight.lean @@ -76,7 +76,8 @@ namespace UnifTight theorem eventually_cofinite_indicator (hf : UnifTight f p μ) {ε : ℝ≥0∞} (hε : ε ≠ 0) : ∀ᶠ s in μ.cofinite.smallSets, ∀ i, eLpNorm (s.indicator (f i)) p μ ≤ ε := by - by_cases hε_top : ε = ∞; subst hε_top; simp + by_cases hε_top : ε = ∞ + · subst hε_top; simp rcases hf (pos_iff_ne_zero.2 (toNNReal_ne_zero.mpr ⟨hε,hε_top⟩)) with ⟨s, hμs, hfs⟩ refine (eventually_smallSets' ?_).2 ⟨sᶜ, ?_, fun i ↦ (coe_toNNReal hε_top) ▸ hfs i⟩ · intro s t hst ht i diff --git a/Mathlib/MeasureTheory/Group/Arithmetic.lean b/Mathlib/MeasureTheory/Group/Arithmetic.lean index 1893764f613b0..a265438e4ebd7 100644 --- a/Mathlib/MeasureTheory/Group/Arithmetic.lean +++ b/Mathlib/MeasureTheory/Group/Arithmetic.lean @@ -87,8 +87,8 @@ export MeasurableMul₂ (measurable_mul) section Mul -variable {M α : Type*} [MeasurableSpace M] [Mul M] {m : MeasurableSpace α} {f g : α → M} - {μ : Measure α} +variable {M α β : Type*} [MeasurableSpace M] [Mul M] {m : MeasurableSpace α} + {mβ : MeasurableSpace β} {f g : α → M} {μ : Measure α} @[to_additive (attr := fun_prop, measurability)] theorem Measurable.const_mul [MeasurableMul M] (hf : Measurable f) (c : M) : @@ -110,17 +110,19 @@ theorem AEMeasurable.mul_const [MeasurableMul M] (hf : AEMeasurable f μ) (c : M AEMeasurable (fun x => f x * c) μ := (measurable_mul_const c).comp_aemeasurable hf -@[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] -theorem Measurable.mul' [MeasurableMul₂ M] (hf : Measurable f) (hg : Measurable g) : - Measurable (f * g) := - measurable_mul.comp (hf.prod_mk hg) - @[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] theorem Measurable.mul [MeasurableMul₂ M] (hf : Measurable f) (hg : Measurable g) : Measurable fun a => f a * g a := measurable_mul.comp (hf.prod_mk hg) -@[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] +/-- Compositional version of `Measurable.mul` for use by `fun_prop`. -/ +@[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable])) +"Compositional version of `Measurable.add` for use by `fun_prop`."] +lemma Measurable.mul' [MeasurableMul₂ M] {f g : α → β → M} {h : α → β} (hf : Measurable ↿f) + (hg : Measurable ↿g) (hh : Measurable h) : Measurable fun a ↦ (f a * g a) (h a) := by + simp; fun_prop + +@[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] theorem AEMeasurable.mul' [MeasurableMul₂ M] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) : AEMeasurable (f * g) μ := measurable_mul.comp_aemeasurable (hf.prod_mk hg) @@ -238,8 +240,8 @@ export MeasurableDiv₂ (measurable_div) section Div -variable {G α : Type*} [MeasurableSpace G] [Div G] {m : MeasurableSpace α} {f g : α → G} - {μ : Measure α} +variable {G α β : Type*} [MeasurableSpace G] [Div G] {m : MeasurableSpace α} + {mβ : MeasurableSpace β} {f g : α → G} {μ : Measure α} @[to_additive (attr := measurability)] theorem Measurable.const_div [MeasurableDiv G] (hf : Measurable f) (c : G) : @@ -261,17 +263,17 @@ theorem AEMeasurable.div_const [MeasurableDiv G] (hf : AEMeasurable f μ) (c : G AEMeasurable (fun x => f x / c) μ := (MeasurableDiv.measurable_div_const c).comp_aemeasurable hf -@[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] -theorem Measurable.div' [MeasurableDiv₂ G] (hf : Measurable f) (hg : Measurable g) : - Measurable (f / g) := - measurable_div.comp (hf.prod_mk hg) - @[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] theorem Measurable.div [MeasurableDiv₂ G] (hf : Measurable f) (hg : Measurable g) : Measurable fun a => f a / g a := measurable_div.comp (hf.prod_mk hg) -@[to_additive (attr := aesop safe 20 apply (rule_sets := [Measurable]))] +@[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] +lemma Measurable.div' [MeasurableDiv₂ G] {f g : α → β → G} {h : α → β} (hf : Measurable ↿f) + (hg : Measurable ↿g) (hh : Measurable h) : Measurable fun a ↦ (f a / g a) (h a) := by + simp; fun_prop + +@[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] theorem AEMeasurable.div' [MeasurableDiv₂ G] (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) : AEMeasurable (f / g) μ := measurable_div.comp_aemeasurable (hf.prod_mk hg) @@ -528,42 +530,52 @@ instance Subgroup.measurableSMul {G α} [MeasurableSpace G] [MeasurableSpace α] section SMul -variable {M β α : Type*} [MeasurableSpace M] [MeasurableSpace β] [_root_.SMul M β] - {m : MeasurableSpace α} {f : α → M} {g : α → β} +variable {M X α β : Type*} [MeasurableSpace M] [MeasurableSpace X] [SMul M X] + {m : MeasurableSpace α} {mβ : MeasurableSpace β} {f : α → M} {g : α → X} @[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] -theorem Measurable.smul [MeasurableSMul₂ M β] (hf : Measurable f) (hg : Measurable g) : +theorem Measurable.smul [MeasurableSMul₂ M X] (hf : Measurable f) (hg : Measurable g) : Measurable fun x => f x • g x := measurable_smul.comp (hf.prod_mk hg) +/-- Compositional version of `Measurable.smul` for use by `fun_prop`. -/ +@[to_additive (attr := fun_prop) +"Compositional version of `Measurable.vadd` for use by `fun_prop`."] +lemma Measurable.smul' [MeasurableSMul₂ M X] {f : α → β → M} {g : α → β → X} {h : α → β} + (hf : Measurable ↿f) (hg : Measurable ↿g) (hh : Measurable h) : + Measurable fun a ↦ (f a • g a) (h a) := by simp; fun_prop + @[to_additive (attr := fun_prop, aesop safe 20 apply (rule_sets := [Measurable]))] -theorem AEMeasurable.smul [MeasurableSMul₂ M β] {μ : Measure α} (hf : AEMeasurable f μ) +theorem AEMeasurable.smul [MeasurableSMul₂ M X] {μ : Measure α} (hf : AEMeasurable f μ) (hg : AEMeasurable g μ) : AEMeasurable (fun x => f x • g x) μ := MeasurableSMul₂.measurable_smul.comp_aemeasurable (hf.prod_mk hg) @[to_additive] -instance (priority := 100) MeasurableSMul₂.toMeasurableSMul [MeasurableSMul₂ M β] : - MeasurableSMul M β := +instance (priority := 100) MeasurableSMul₂.toMeasurableSMul [MeasurableSMul₂ M X] : + MeasurableSMul M X := ⟨fun _ => measurable_const.smul measurable_id, fun _ => measurable_id.smul measurable_const⟩ -variable [MeasurableSMul M β] {μ : Measure α} +variable [MeasurableSMul M X] {μ : Measure α} @[to_additive (attr := measurability)] -theorem Measurable.smul_const (hf : Measurable f) (y : β) : Measurable fun x => f x • y := +theorem Measurable.smul_const (hf : Measurable f) (y : X) : Measurable fun x => f x • y := (MeasurableSMul.measurable_smul_const y).comp hf @[to_additive (attr := measurability)] -theorem AEMeasurable.smul_const (hf : AEMeasurable f μ) (y : β) : +theorem AEMeasurable.smul_const (hf : AEMeasurable f μ) (y : X) : AEMeasurable (fun x => f x • y) μ := (MeasurableSMul.measurable_smul_const y).comp_aemeasurable hf -@[to_additive (attr := measurability)] -theorem Measurable.const_smul' (hg : Measurable g) (c : M) : Measurable fun x => c • g x := +@[to_additive (attr := fun_prop, measurability)] +theorem Measurable.const_smul (hg : Measurable g) (c : M) : Measurable (c • g) := (MeasurableSMul.measurable_const_smul c).comp hg -@[to_additive (attr := measurability)] -theorem Measurable.const_smul (hg : Measurable g) (c : M) : Measurable (c • g) := - hg.const_smul' c +/-- Compositional version of `Measurable.const_smul` for use by `fun_prop`. -/ +@[to_additive (attr := fun_prop) +"Compositional version of `Measurable.const_vadd` for use by `fun_prop`."] +lemma Measurable.const_smul' {g : α → β → X} {h : α → β} (hg : Measurable ↿g) (hh : Measurable h) + (c : M) : Measurable fun a ↦ (c • g a) (h a) := + (hg.comp <| measurable_id.prod_mk hh).const_smul _ @[to_additive (attr := measurability)] theorem AEMeasurable.const_smul' (hg : AEMeasurable g μ) (c : M) : @@ -638,12 +650,12 @@ variable {G : Type*} [Group G] [MeasurableSpace G] [MulAction G β] [MeasurableS @[to_additive] theorem measurable_const_smul_iff (c : G) : (Measurable fun x => c • f x) ↔ Measurable f := - ⟨fun h => by simpa only [inv_smul_smul] using h.const_smul' c⁻¹, fun h => h.const_smul c⟩ + ⟨fun h => by simpa [inv_smul_smul, Pi.smul_def] using h.const_smul c⁻¹, fun h => h.const_smul c⟩ @[to_additive] theorem aemeasurable_const_smul_iff (c : G) : AEMeasurable (fun x => c • f x) μ ↔ AEMeasurable f μ := - ⟨fun h => by simpa only [inv_smul_smul] using h.const_smul' c⁻¹, fun h => h.const_smul c⟩ + ⟨fun h => by simpa [inv_smul_smul, Pi.smul_def] using h.const_smul c⁻¹, fun h => h.const_smul c⟩ @[to_additive] instance Units.instMeasurableSpace : MeasurableSpace Mˣ := MeasurableSpace.comap ((↑) : Mˣ → M) ‹_› @@ -782,8 +794,8 @@ end Monoid section CommMonoid -variable {M ι α : Type*} [CommMonoid M] [MeasurableSpace M] [MeasurableMul₂ M] - {m : MeasurableSpace α} {μ : Measure α} {f : ι → α → M} +variable {M ι α β : Type*} [CommMonoid M] [MeasurableSpace M] [MeasurableMul₂ M] + {m : MeasurableSpace α} {mβ : MeasurableSpace β} {μ : Measure α} {f : ι → α → M} @[to_additive (attr := measurability)] theorem Multiset.measurable_prod' (l : Multiset (α → M)) (hl : ∀ f ∈ l, Measurable f) : @@ -807,15 +819,18 @@ theorem Multiset.aemeasurable_prod (s : Multiset (α → M)) (hs : ∀ f ∈ s, AEMeasurable (fun x => (s.map fun f : α → M => f x).prod) μ := by simpa only [← Pi.multiset_prod_apply] using s.aemeasurable_prod' hs -@[to_additive (attr := measurability)] -theorem Finset.measurable_prod' (s : Finset ι) (hf : ∀ i ∈ s, Measurable (f i)) : - Measurable (∏ i ∈ s, f i) := - Finset.prod_induction _ _ (fun _ _ => Measurable.mul) (@measurable_one M _ _ _ _) hf - -@[to_additive (attr := measurability)] +@[to_additive (attr := fun_prop, measurability)] theorem Finset.measurable_prod (s : Finset ι) (hf : ∀ i ∈ s, Measurable (f i)) : - Measurable fun a => ∏ i ∈ s, f i a := by - simpa only [← Finset.prod_apply] using s.measurable_prod' hf + Measurable fun a ↦ ∏ i ∈ s, f i a := by + simp_rw [← Finset.prod_apply] + exact Finset.prod_induction _ _ (fun _ _ => Measurable.mul) (@measurable_one M _ _ _ _) hf + +/-- Compositional version of `Finset.measurable_prod` for use by `fun_prop`. -/ +@[to_additive (attr := measurability, fun_prop) +"Compositional version of `Finset.measurable_sum` for use by `fun_prop`."] +lemma Finset.measurable_prod' {f : ι → α → β → M} {g : α → β} {s : Finset ι} + (hf : ∀ i, Measurable ↿(f i)) (hg : Measurable g) : + Measurable fun a ↦ (∏ i ∈ s, f i a) (g a) := by simp; fun_prop @[to_additive (attr := measurability)] theorem Finset.aemeasurable_prod' (s : Finset ι) (hf : ∀ i ∈ s, AEMeasurable (f i) μ) : diff --git a/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean b/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean index fb1be755747f1..4f7644744e85c 100644 --- a/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean +++ b/Mathlib/MeasureTheory/Group/GeometryOfNumbers.lean @@ -36,7 +36,7 @@ Hermann Minkowski. namespace MeasureTheory -open ENNReal FiniteDimensional MeasureTheory MeasureTheory.Measure Set Filter +open ENNReal Module MeasureTheory MeasureTheory.Measure Set Filter open scoped Pointwise NNReal @@ -134,7 +134,7 @@ theorem exists_ne_zero_mem_lattice_of_measure_mul_two_pow_le_measure [NormedAddC rw [show μ s < _ ↔ 1 * μ s < _ by rw [one_mul]] refine (mul_lt_mul_right h_mes (ne_of_lt h_cpt.measure_lt_top)).mpr ?_ rw [ofReal_pow (NNReal.coe_nonneg _)] - refine one_lt_pow ?_ (ne_of_gt finrank_pos) + refine one_lt_pow₀ ?_ (ne_of_gt finrank_pos) simp [(exists_seq_strictAnti_tendsto (0 : ℝ≥0)).choose_spec.2.1 n] end MeasureTheory diff --git a/Mathlib/MeasureTheory/Group/Measure.lean b/Mathlib/MeasureTheory/Group/Measure.lean index 66eafadc4d30a..3e36cb114970b 100644 --- a/Mathlib/MeasureTheory/Group/Measure.lean +++ b/Mathlib/MeasureTheory/Group/Measure.lean @@ -5,7 +5,7 @@ Authors: Floris van Doorn -/ import Mathlib.MeasureTheory.Constructions.Prod.Basic import Mathlib.MeasureTheory.Group.Action -import Mathlib.Topology.ContinuousFunction.CocompactMap +import Mathlib.Topology.ContinuousMap.CocompactMap /-! # Measures on Groups diff --git a/Mathlib/MeasureTheory/Integral/Average.lean b/Mathlib/MeasureTheory/Integral/Average.lean index 2b93b827a0339..86ca2d01fcaf8 100644 --- a/Mathlib/MeasureTheory/Integral/Average.lean +++ b/Mathlib/MeasureTheory/Integral/Average.lean @@ -321,7 +321,7 @@ theorem average_congr {f g : α → E} (h : f =ᵐ[μ] g) : ⨍ x, f x ∂μ = simp only [average_eq, integral_congr_ae h] theorem setAverage_congr (h : s =ᵐ[μ] t) : ⨍ x in s, f x ∂μ = ⨍ x in t, f x ∂μ := by - simp only [setAverage_eq, setIntegral_congr_set_ae h, measure_congr h] + simp only [setAverage_eq, setIntegral_congr_set h, measure_congr h] theorem setAverage_congr_fun (hs : MeasurableSet s) (h : ∀ᵐ x ∂μ, x ∈ s → f x = g x) : ⨍ x in s, f x ∂μ = ⨍ x in s, g x ∂μ := by simp only [average_eq, setIntegral_congr_ae hs h] diff --git a/Mathlib/MeasureTheory/Integral/Bochner.lean b/Mathlib/MeasureTheory/Integral/Bochner.lean index 43d62ecfb9b43..411b231ffbadc 100644 --- a/Mathlib/MeasureTheory/Integral/Bochner.lean +++ b/Mathlib/MeasureTheory/Integral/Bochner.lean @@ -588,7 +588,7 @@ variable (𝕜) /-- The Bochner integral in L1 space as a continuous linear map. -/ nonrec def integralCLM' : (α →₁[μ] E) →L[𝕜] E := (integralCLM' α E 𝕜 μ).extend (coeToLp α E 𝕜) (simpleFunc.denseRange one_ne_top) - simpleFunc.uniformInducing + simpleFunc.isUniformInducing variable {𝕜} @@ -1472,6 +1472,9 @@ theorem integral_zero_measure {m : MeasurableSpace α} (f : α → G) : theorem setIntegral_zero_measure (f : α → G) {μ : Measure α} {s : Set α} (hs : μ s = 0) : ∫ x in s, f x ∂μ = 0 := Measure.restrict_eq_zero.mpr hs ▸ integral_zero_measure f +lemma integral_of_isEmpty [IsEmpty α] {f : α → G} : ∫ x, f x ∂μ = 0 := + μ.eq_zero_of_isEmpty ▸ integral_zero_measure _ + theorem integral_finset_sum_measure {ι} {m : MeasurableSpace α} {f : α → G} {μ : ι → Measure α} {s : Finset ι} (hf : ∀ i ∈ s, Integrable f (μ i)) : ∫ a, f a ∂(∑ i ∈ s, μ i) = ∑ i ∈ s, ∫ a, f a ∂μ i := by diff --git a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean index 673ac92017bbf..bd267c4c74fe6 100644 --- a/Mathlib/MeasureTheory/Integral/CircleIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/CircleIntegral.lean @@ -286,7 +286,7 @@ theorem circleIntegrable_sub_zpow_iff {c w : ℂ} {R : ℝ} {n : ℤ} : not_false_iff] using this have : x ∈ Ioo (0 : ℝ) 1 := by simpa [x, and_comm] using hθ' rw [← zpow_neg_one] - refine (zpow_strictAnti this.1 this.2).le_iff_le.2 (Int.lt_add_one_iff.1 ?_); exact hn + refine (zpow_right_strictAnti₀ this.1 this.2).le_iff_le.2 (Int.lt_add_one_iff.1 ?_); exact hn · rintro (rfl | H) exacts [circleIntegrable_zero_radius, ((continuousOn_id.sub continuousOn_const).zpow₀ _ fun z hz => diff --git a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean index 2280f163883e0..c42a397ec5d54 100644 --- a/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean +++ b/Mathlib/MeasureTheory/Integral/DivergenceTheorem.lean @@ -116,7 +116,7 @@ theorem integral_divergence_of_hasFDerivWithinAt_off_countable_aux₁ (I : Box ( ∑ i : Fin (n + 1), ((∫ x in Box.Icc (I.face i), f (i.insertNth (I.upper i) x) i) - ∫ x in Box.Icc (I.face i), f (i.insertNth (I.lower i) x) i) := by - simp only [← setIntegral_congr_set_ae (Box.coe_ae_eq_Icc _)] + simp only [← setIntegral_congr_set (Box.coe_ae_eq_Icc _)] have A := (Hi.mono_set Box.coe_subset_Icc).hasBoxIntegral ⊥ rfl have B := hasIntegral_GP_divergence_of_forall_hasDerivWithinAt I f f' (s ∩ Box.Icc I) @@ -273,10 +273,10 @@ theorem integral_divergence_of_hasFDerivWithinAt_off_countable (hle : a ≤ b) ((∫ x in face i, f (frontFace i x) i) - ∫ x in face i, f (backFace i x) i) := by rcases em (∃ i, a i = b i) with (⟨i, hi⟩ | hne) · -- First we sort out the trivial case `∃ i, a i = b i`. - rw [volume_pi, ← setIntegral_congr_set_ae Measure.univ_pi_Ioc_ae_eq_Icc] + rw [volume_pi, ← setIntegral_congr_set Measure.univ_pi_Ioc_ae_eq_Icc] have hi' : Ioc (a i) (b i) = ∅ := Ioc_eq_empty hi.not_lt have : (pi Set.univ fun j => Ioc (a j) (b j)) = ∅ := univ_pi_eq_empty hi' - rw [this, integral_empty, sum_eq_zero] + rw [this, setIntegral_empty, sum_eq_zero] rintro j - rcases eq_or_ne i j with (rfl | hne) · simp [hi] @@ -284,8 +284,8 @@ theorem integral_divergence_of_hasFDerivWithinAt_off_countable (hle : a ≤ b) have : Icc (a ∘ j.succAbove) (b ∘ j.succAbove) =ᵐ[volume] (∅ : Set ℝⁿ) := by rw [ae_eq_empty, Real.volume_Icc_pi, prod_eq_zero (Finset.mem_univ i)] simp [hi] - rw [setIntegral_congr_set_ae this, setIntegral_congr_set_ae this, integral_empty, - integral_empty, sub_self] + rw [setIntegral_congr_set this, setIntegral_congr_set this, setIntegral_empty, + setIntegral_empty, sub_self] · -- In the non-trivial case `∀ i, a i < b i`, we apply a lemma we proved above. have hlt : ∀ i, a i < b i := fun i => (hle i).lt_of_ne fun hi => hne ⟨i, hi⟩ exact integral_divergence_of_hasFDerivWithinAt_off_countable_aux₂ ⟨a, b, hlt⟩ f f' s hs Hc @@ -382,7 +382,7 @@ theorem integral_eq_of_hasDerivWithinAt_off_countable_of_le (f f' : ℝ → E) { have hF' : ∀ x y, F' x y = y • f' x := fun x y => rfl calc ∫ x in a..b, f' x = ∫ x in Icc a b, f' x := by - rw [intervalIntegral.integral_of_le hle, setIntegral_congr_set_ae Ioc_ae_eq_Icc] + rw [intervalIntegral.integral_of_le hle, setIntegral_congr_set Ioc_ae_eq_Icc] _ = ∑ i : Fin 1, ((∫ x in Icc (e a ∘ i.succAbove) (e b ∘ i.succAbove), f (e.symm <| i.insertNth (e b i) x)) - @@ -467,7 +467,7 @@ theorem integral_divergence_prod_Icc_of_hasFDerivWithinAt_off_countable_of_le (f _ = (((∫ x in a.1..b.1, g (x, b.2)) - ∫ x in a.1..b.1, g (x, a.2)) + ∫ y in a.2..b.2, f (b.1, y)) - ∫ y in a.2..b.2, f (a.1, y) := by simp only [intervalIntegral.integral_of_le hle.1, intervalIntegral.integral_of_le hle.2, - setIntegral_congr_set_ae (Ioc_ae_eq_Icc (α := ℝ) (μ := volume))] + setIntegral_congr_set (Ioc_ae_eq_Icc (α := ℝ) (μ := volume))] abel /-- **Divergence theorem** for functions on the plane. It is formulated in terms of two functions @@ -506,7 +506,7 @@ theorem integral2_divergence_prod_of_hasFDerivWithinAt_off_countable (f g : ℝ (∫ x in a₁..b₁, ∫ y in a₂..b₂, f' (x, y) (1, 0) + g' (x, y) (0, 1)) = ∫ x in Icc a₁ b₁, ∫ y in Icc a₂ b₂, f' (x, y) (1, 0) + g' (x, y) (0, 1) := by simp only [intervalIntegral.integral_of_le, h₁, h₂, - setIntegral_congr_set_ae (Ioc_ae_eq_Icc (α := ℝ) (μ := volume))] + setIntegral_congr_set (Ioc_ae_eq_Icc (α := ℝ) (μ := volume))] _ = ∫ x in Icc a₁ b₁ ×ˢ Icc a₂ b₂, f' x (1, 0) + g' x (0, 1) := (setIntegral_prod _ Hi).symm _ = (((∫ x in a₁..b₁, g (x, b₂)) - ∫ x in a₁..b₁, g (x, a₂)) + ∫ y in a₂..b₂, f (b₁, y)) - ∫ y in a₂..b₂, f (a₁, y) := by diff --git a/Mathlib/MeasureTheory/Integral/Gamma.lean b/Mathlib/MeasureTheory/Integral/Gamma.lean index e45745db0df27..e8364efdee04a 100644 --- a/Mathlib/MeasureTheory/Integral/Gamma.lean +++ b/Mathlib/MeasureTheory/Integral/Gamma.lean @@ -24,11 +24,11 @@ theorem integral_rpow_mul_exp_neg_rpow {p q : ℝ} (hp : 0 < p) (hq : - 1 < q) : _ = ∫ (x : ℝ) in Ioi 0, (1 / p * x ^ (1 / p - 1)) • ((x ^ (1 / p)) ^ q * exp (-x)) := by rw [← integral_comp_rpow_Ioi _ (one_div_ne_zero (ne_of_gt hp)), abs_eq_self.mpr (le_of_lt (one_div_pos.mpr hp))] - refine setIntegral_congr measurableSet_Ioi (fun _ hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun _ hx => ?_) rw [← rpow_mul (le_of_lt hx) _ p, one_div_mul_cancel (ne_of_gt hp), rpow_one] _ = ∫ (x : ℝ) in Ioi 0, 1 / p * exp (-x) * x ^ (1 / p - 1 + q / p) := by simp_rw [smul_eq_mul, mul_assoc] - refine setIntegral_congr measurableSet_Ioi (fun _ hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun _ hx => ?_) rw [← rpow_mul (le_of_lt hx), div_mul_eq_mul_div, one_mul, rpow_add hx] ring_nf _ = (1 / p) * Gamma ((q + 1) / p) := by @@ -41,7 +41,7 @@ theorem integral_rpow_mul_exp_neg_mul_rpow {p q b : ℝ} (hp : 0 < p) (hq : - 1 b ^ (-(q + 1) / p) * (1 / p) * Gamma ((q + 1) / p) := by calc _ = ∫ x in Ioi (0 : ℝ), b ^ (-p⁻¹ * q) * ((b ^ p⁻¹ * x) ^ q * rexp (-(b ^ p⁻¹ * x) ^ p)) := by - refine setIntegral_congr measurableSet_Ioi (fun _ hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun _ hx => ?_) rw [mul_rpow _ (le_of_lt hx), mul_rpow _ (le_of_lt hx), ← rpow_mul, ← rpow_mul, inv_mul_cancel₀, rpow_one, mul_assoc, ← mul_assoc, ← rpow_add, neg_mul p⁻¹, neg_add_cancel, rpow_zero, one_mul, neg_mul] @@ -88,7 +88,7 @@ theorem Complex.integral_rpow_mul_exp_neg_rpow {p q : ℝ} (hp : 1 ≤ p) (hq : smul_eq_mul, mul_one, mul_comm] _ = 2 * π * ∫ x in Ioi (0 : ℝ), x ^ (q + 1) * rexp (-x ^ p) := by congr 1 - refine setIntegral_congr measurableSet_Ioi (fun x hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun x hx => ?_) rw [mem_Ioi] at hx rw [abs_eq_self.mpr hx.le, rpow_add hx, rpow_one] ring @@ -115,7 +115,7 @@ theorem Complex.integral_rpow_mul_exp_neg_mul_rpow {p q b : ℝ} (hp : 1 ≤ p) smul_eq_mul, mul_one, mul_comm] _ = 2 * π * ∫ x in Ioi (0 : ℝ), x ^ (q + 1) * rexp (-b * x ^ p) := by congr 1 - refine setIntegral_congr measurableSet_Ioi (fun x hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun x hx => ?_) rw [mem_Ioi] at hx rw [abs_eq_self.mpr hx.le, rpow_add hx, rpow_one] ring diff --git a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean index 902812d6d999d..10441a23710fa 100644 --- a/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean +++ b/Mathlib/MeasureTheory/Integral/IntegralEqImproper.lean @@ -712,7 +712,7 @@ theorem tendsto_zero_of_hasDerivAt_of_integrableOn_Ioi rw [← top_le_iff, ← volume_Ici (a := b)] exact measure_mono hb rwa [B, ← Embedding.tendsto_nhds_iff] at A - exact (Completion.uniformEmbedding_coe E).embedding + exact (Completion.isUniformEmbedding_coe E).embedding variable [CompleteSpace E] @@ -793,7 +793,7 @@ theorem integrableOn_Ioi_deriv_of_nonneg (hcont : ContinuousWithinAt g (Ici a) a (fun y hy => hderiv y hy.1) fun y hy => g'pos y hy.1 _ = ∫ y in a..id x, ‖g' y‖ := by simp_rw [intervalIntegral.integral_of_le h'x] - refine setIntegral_congr measurableSet_Ioc fun y hy => ?_ + refine setIntegral_congr_fun measurableSet_Ioc fun y hy => ?_ dsimp rw [abs_of_nonneg] exact g'pos _ hy.1 @@ -909,7 +909,7 @@ theorem tendsto_zero_of_hasDerivAt_of_integrableOn_Iic rw [← volume_Iic (a := b)] exact measure_mono hb rwa [B, ← Embedding.tendsto_nhds_iff] at A - exact (Completion.uniformEmbedding_coe E).embedding + exact (Completion.isUniformEmbedding_coe E).embedding variable [CompleteSpace E] @@ -996,8 +996,8 @@ see `tendsto_limUnder_of_hasDerivAt_of_integrableOn_Iic` and theorem integral_of_hasDerivAt_of_tendsto [CompleteSpace E] (hderiv : ∀ x, HasDerivAt f (f' x) x) (hf' : Integrable f') (hbot : Tendsto f atBot (𝓝 m)) (htop : Tendsto f atTop (𝓝 n)) : ∫ x, f' x = n - m := by - rw [← integral_univ, ← Set.Iic_union_Ioi (a := 0), - integral_union (Iic_disjoint_Ioi le_rfl) measurableSet_Ioi hf'.integrableOn hf'.integrableOn, + rw [← setIntegral_univ, ← Set.Iic_union_Ioi (a := 0), + setIntegral_union (Iic_disjoint_Ioi le_rfl) measurableSet_Ioi hf'.integrableOn hf'.integrableOn, integral_Iic_of_hasDerivAt_of_tendsto' (fun x _ ↦ hderiv x) hf'.integrableOn hbot, integral_Ioi_of_hasDerivAt_of_tendsto' (fun x _ ↦ hderiv x) hf'.integrableOn htop] abel @@ -1075,7 +1075,7 @@ theorem integral_comp_rpow_Ioi (g : ℝ → E) {p : ℝ} (hp : p ≠ 0) : rcases lt_or_gt_of_ne hp with (h | h) · apply StrictAntiOn.injOn intro x hx y hy hxy - rw [← inv_lt_inv (rpow_pos_of_pos hx p) (rpow_pos_of_pos hy p), ← rpow_neg (le_of_lt hx), + rw [← inv_lt_inv₀ (rpow_pos_of_pos hx p) (rpow_pos_of_pos hy p), ← rpow_neg (le_of_lt hx), ← rpow_neg (le_of_lt hy)] exact rpow_lt_rpow (le_of_lt hx) hxy (neg_pos.mpr h) exact StrictMonoOn.injOn fun x hx y _ hxy => rpow_lt_rpow (mem_Ioi.mp hx).le hxy h @@ -1086,7 +1086,7 @@ theorem integral_comp_rpow_Ioi (g : ℝ → E) {p : ℝ} (hp : p ≠ 0) : rw [← rpow_mul (le_of_lt hx), one_div_mul_cancel hp, rpow_one] have := integral_image_eq_integral_abs_deriv_smul measurableSet_Ioi a1 a2 g rw [a3] at this; rw [this] - refine setIntegral_congr measurableSet_Ioi ?_ + refine setIntegral_congr_fun measurableSet_Ioi ?_ intro x hx; dsimp only rw [abs_mul, abs_of_nonneg (rpow_nonneg (le_of_lt hx) _)] @@ -1129,7 +1129,7 @@ theorem integrableOn_Ioi_comp_rpow_iff [NormedSpace ℝ E] (f : ℝ → E) {p : rcases lt_or_gt_of_ne hp with (h | h) · apply StrictAntiOn.injOn intro x hx y hy hxy - rw [← inv_lt_inv (rpow_pos_of_pos hx p) (rpow_pos_of_pos hy p), ← rpow_neg (le_of_lt hx), ← + rw [← inv_lt_inv₀ (rpow_pos_of_pos hx p) (rpow_pos_of_pos hy p), ← rpow_neg (le_of_lt hx), ← rpow_neg (le_of_lt hy)] exact rpow_lt_rpow (le_of_lt hx) hxy (neg_pos.mpr h) exact StrictMonoOn.injOn fun x hx y _hy hxy => rpow_lt_rpow (mem_Ioi.mp hx).le hxy h diff --git a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean index fc342e5424d56..0c443e0792ad6 100644 --- a/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/IntervalIntegral.lean @@ -786,14 +786,14 @@ theorem integral_congr {a b : ℝ} (h : EqOn f g [[a, b]]) : ∫ x in a..b, f x ∂μ = ∫ x in a..b, g x ∂μ := by rcases le_total a b with hab | hab <;> simpa [hab, integral_of_le, integral_of_ge] using - setIntegral_congr measurableSet_Ioc (h.mono Ioc_subset_Icc_self) + setIntegral_congr_fun measurableSet_Ioc (h.mono Ioc_subset_Icc_self) theorem integral_add_adjacent_intervals_cancel (hab : IntervalIntegrable f μ a b) (hbc : IntervalIntegrable f μ b c) : (((∫ x in a..b, f x ∂μ) + ∫ x in b..c, f x ∂μ) + ∫ x in c..a, f x ∂μ) = 0 := by have hac := hab.trans hbc simp only [intervalIntegral, sub_add_sub_comm, sub_eq_zero] - iterate 4 rw [← integral_union] + iterate 4 rw [← setIntegral_union] · suffices Ioc a b ∪ Ioc b c ∪ Ioc c a = Ioc b a ∪ Ioc c b ∪ Ioc a c by rw [this] rw [Ioc_union_Ioc_union_Ioc_cycle, union_right_comm, Ioc_union_Ioc_union_Ioc_cycle, min_left_comm, max_left_comm] @@ -857,20 +857,20 @@ theorem integral_Iic_sub_Iic (ha : IntegrableOn f (Iic a) μ) (hb : IntegrableOn ((∫ x in Iic b, f x ∂μ) - ∫ x in Iic a, f x ∂μ) = ∫ x in a..b, f x ∂μ := by wlog hab : a ≤ b generalizing a b · rw [integral_symm, ← this hb ha (le_of_not_le hab), neg_sub] - rw [sub_eq_iff_eq_add', integral_of_le hab, ← integral_union (Iic_disjoint_Ioc le_rfl), + rw [sub_eq_iff_eq_add', integral_of_le hab, ← setIntegral_union (Iic_disjoint_Ioc le_rfl), Iic_union_Ioc_eq_Iic hab] exacts [measurableSet_Ioc, ha, hb.mono_set fun _ => And.right] theorem integral_Iic_add_Ioi (h_left : IntegrableOn f (Iic b) μ) (h_right : IntegrableOn f (Ioi b) μ) : (∫ x in Iic b, f x ∂μ) + (∫ x in Ioi b, f x ∂μ) = ∫ (x : ℝ), f x ∂μ := by - convert (integral_union (Iic_disjoint_Ioi <| Eq.le rfl) measurableSet_Ioi h_left h_right).symm + convert (setIntegral_union (Iic_disjoint_Ioi <| Eq.le rfl) measurableSet_Ioi h_left h_right).symm rw [Iic_union_Ioi, Measure.restrict_univ] theorem integral_Iio_add_Ici (h_left : IntegrableOn f (Iio b) μ) (h_right : IntegrableOn f (Ici b) μ) : (∫ x in Iio b, f x ∂μ) + (∫ x in Ici b, f x ∂μ) = ∫ (x : ℝ), f x ∂μ := by - convert (integral_union (Iio_disjoint_Ici <| Eq.le rfl) measurableSet_Ici h_left h_right).symm + convert (setIntegral_union (Iio_disjoint_Ici <| Eq.le rfl) measurableSet_Ici h_left h_right).symm rw [Iio_union_Ici, Measure.restrict_univ] /-- If `μ` is a finite measure then `∫ x in a..b, c ∂μ = (μ (Iic b) - μ (Iic a)) • c`. -/ @@ -1021,6 +1021,12 @@ theorem abs_integral_le_integral_abs (hab : a ≤ b) : |∫ x in a..b, f x ∂μ| ≤ ∫ x in a..b, |f x| ∂μ := by simpa only [← Real.norm_eq_abs] using norm_integral_le_integral_norm hab +lemma integral_pos (hab : a < b) + (hfc : ContinuousOn f (Icc a b)) (hle : ∀ x ∈ Ioc a b, 0 ≤ f x) (hlt : ∃ c ∈ Icc a b, 0 < f c) : + 0 < ∫ x in a..b, f x := + (integral_lt_integral_of_continuousOn_of_le_of_exists_lt hab + continuousOn_const hfc hle hlt).trans_eq' (by simp) + section Mono theorem integral_mono_interval {c d} (hca : c ≤ a) (hab : a ≤ b) (hbd : b ≤ d) @@ -1069,7 +1075,7 @@ variable {μ : Measure ℝ} {f : ℝ → E} theorem _root_.MeasureTheory.Integrable.hasSum_intervalIntegral (hfi : Integrable f μ) (y : ℝ) : HasSum (fun n : ℤ => ∫ x in y + n..y + n + 1, f x ∂μ) (∫ x, f x ∂μ) := by simp_rw [integral_of_le (le_add_of_nonneg_right zero_le_one)] - rw [← integral_univ, ← iUnion_Ioc_add_intCast y] + rw [← setIntegral_univ, ← iUnion_Ioc_add_intCast y] exact hasSum_integral_iUnion (fun i => measurableSet_Ioc) (pairwise_disjoint_Ioc_add_intCast y) hfi.integrableOn diff --git a/Mathlib/MeasureTheory/Integral/Lebesgue.lean b/Mathlib/MeasureTheory/Integral/Lebesgue.lean index 4b2e98b074018..184a66e158c30 100644 --- a/Mathlib/MeasureTheory/Integral/Lebesgue.lean +++ b/Mathlib/MeasureTheory/Integral/Lebesgue.lean @@ -530,7 +530,7 @@ theorem lintegral_add_aux {f g : α → ℝ≥0∞} (hf : Measurable f) (hg : Me funext n rw [← SimpleFunc.add_lintegral, ← SimpleFunc.lintegral_eq_lintegral] simp only [Pi.add_apply, SimpleFunc.coe_add] - · measurability + · fun_prop · intro i j h a dsimp gcongr <;> exact monotone_eapprox _ h _ @@ -765,12 +765,21 @@ theorem lintegral_indicator (f : α → ℝ≥0∞) {s : Set α} (hs : Measurabl refine ⟨⟨φ.restrict s, fun x => ?_⟩, le_rfl⟩ simp [hφ x, hs, indicator_le_indicator] +lemma setLIntegral_indicator (f : α → ℝ≥0∞) {s t : Set α} (hs : MeasurableSet s) : + ∫⁻ a in t, s.indicator f a ∂μ = ∫⁻ a in s ∩ t, f a ∂μ := by + rw [lintegral_indicator _ hs, Measure.restrict_restrict hs] + theorem lintegral_indicator₀ (f : α → ℝ≥0∞) {s : Set α} (hs : NullMeasurableSet s μ) : ∫⁻ a, s.indicator f a ∂μ = ∫⁻ a in s, f a ∂μ := by rw [← lintegral_congr_ae (indicator_ae_eq_of_ae_eq_set hs.toMeasurable_ae_eq), lintegral_indicator _ (measurableSet_toMeasurable _ _), Measure.restrict_congr_set hs.toMeasurable_ae_eq] +lemma setLIntegral_indicator₀ (f : α → ℝ≥0∞) {s t : Set α} + (hs : NullMeasurableSet s (μ.restrict t)) : + ∫⁻ a in t, s.indicator f a ∂μ = ∫⁻ a in s ∩ t, f a ∂μ := by + rw [lintegral_indicator₀ _ hs, Measure.restrict_restrict₀ hs] + theorem lintegral_indicator_const_le (s : Set α) (c : ℝ≥0∞) : ∫⁻ a, s.indicator (fun _ => c) a ∂μ ≤ c * μ s := (lintegral_indicator_le _ _).trans (setLIntegral_const s c).le @@ -860,6 +869,13 @@ lemma lintegral_le_meas {s : Set α} {f : α → ℝ≥0∞} (hf : ∀ a, f a · simpa [hx] using hf x · simpa [hx] using h'f x hx +lemma setLIntegral_le_meas {s t : Set α} (hs : MeasurableSet s) + {f : α → ℝ≥0∞} (hf : ∀ a ∈ s, a ∈ t → f a ≤ 1) + (hf' : ∀ a ∈ s, a ∉ t → f a = 0) : ∫⁻ a in s, f a ∂μ ≤ μ t := by + rw [← lintegral_indicator _ hs] + refine lintegral_le_meas (fun a ↦ ?_) (by aesop) + by_cases has : a ∈ s <;> [by_cases hat : a ∈ t; skip] <;> simp [*] + theorem lintegral_eq_top_of_measure_eq_top_ne_zero {f : α → ℝ≥0∞} (hf : AEMeasurable f μ) (hμf : μ {x | f x = ∞} ≠ 0) : ∫⁻ x, f x ∂μ = ∞ := eq_top_iff.mpr <| @@ -1995,8 +2011,7 @@ theorem SimpleFunc.exists_lt_lintegral_simpleFunc_of_lt_lintegral {m : Measurabl rcases h₁ hL with ⟨g, g_le, g_top, gL⟩ refine ⟨g, fun x => (g_le x).trans ?_, g_top, gL⟩ simp only [SimpleFunc.coe_add, Pi.add_apply, le_add_iff_nonneg_right, zero_le'] - obtain ⟨L₁, L₂, hL₁, hL₂, hL⟩ : - ∃ L₁ L₂ : ℝ≥0∞, (L₁ < ∫⁻ x, f₁ x ∂μ) ∧ (L₂ < ∫⁻ x, f₂ x ∂μ) ∧ L < L₁ + L₂ := + obtain ⟨L₁, hL₁, L₂, hL₂, hL⟩ : ∃ L₁ < ∫⁻ x, f₁ x ∂μ, ∃ L₂ < ∫⁻ x, f₂ x ∂μ, L < L₁ + L₂ := ENNReal.exists_lt_add_of_lt_add hL hf₁ hf₂ rcases h₁ hL₁ with ⟨g₁, g₁_le, g₁_top, hg₁⟩ rcases h₂ hL₂ with ⟨g₂, g₂_le, g₂_top, hg₂⟩ diff --git a/Mathlib/MeasureTheory/Integral/MeanInequalities.lean b/Mathlib/MeasureTheory/Integral/MeanInequalities.lean index 39a15c80e968f..424952fb5cb92 100644 --- a/Mathlib/MeasureTheory/Integral/MeanInequalities.lean +++ b/Mathlib/MeasureTheory/Integral/MeanInequalities.lean @@ -180,8 +180,7 @@ theorem lintegral_mul_norm_pow_le {α} [MeasurableSpace α] {μ : Measure α} · rw [add_zero] at hpq simp [hpq] have h2p : 1 < 1 / p := by - rw [one_div] - apply one_lt_inv hp + rw [one_div, one_lt_inv₀ hp] linarith have h2pq : (1 / p)⁻¹ + (1 / q)⁻¹ = 1 := by simp [hp.ne', hq.ne', hpq] have := ENNReal.lintegral_mul_le_Lp_mul_Lq μ ⟨h2p, h2pq⟩ (hf.pow_const p) (hg.pow_const q) @@ -312,7 +311,7 @@ theorem lintegral_Lp_mul_le_Lq_mul_Lr {α} [MeasurableSpace α] {p q r : ℝ} (h let p2 := q / p let q2 := p2.conjExponent have hp2q2 : p2.IsConjExponent q2 := - .conjExponent (by simp [p2, q2, _root_.lt_div_iff, hpq, hp0_lt]) + .conjExponent (by simp [p2, q2, _root_.lt_div_iff₀, hpq, hp0_lt]) calc (∫⁻ a : α, (f * g) a ^ p ∂μ) ^ (1 / p) = (∫⁻ a : α, f a ^ p * g a ^ p ∂μ) ^ (1 / p) := by simp_rw [Pi.mul_apply, ENNReal.mul_rpow_of_nonneg _ _ hp0] diff --git a/Mathlib/MeasureTheory/Integral/PeakFunction.lean b/Mathlib/MeasureTheory/Integral/PeakFunction.lean index 8db2aa64138ec..e9adaff6ffe0a 100644 --- a/Mathlib/MeasureTheory/Integral/PeakFunction.lean +++ b/Mathlib/MeasureTheory/Integral/PeakFunction.lean @@ -147,7 +147,7 @@ theorem tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto_aux · exact Eventually.of_forall fun x => mul_nonneg (norm_nonneg _) δpos.le · exact Eventually.of_forall ut _ = ∫ x in t, φ i x * δ ∂μ := by - apply setIntegral_congr ht fun x hx => ?_ + apply setIntegral_congr_fun ht fun x hx => ?_ rw [Real.norm_of_nonneg (hφpos _ (hts hx))] _ = (∫ x in t, φ i x ∂μ) * δ := by rw [integral_mul_right] _ ≤ 2 * δ := by gcongr; linarith [(le_abs_self _).trans h'i.le] @@ -171,7 +171,7 @@ theorem tendsto_setIntegral_peak_smul_of_integrableOn_of_tendsto_aux ‖∫ x in s, φ i x • g x ∂μ‖ = ‖(∫ x in s \ u, φ i x • g x ∂μ) + ∫ x in s ∩ u, φ i x • g x ∂μ‖ := by conv_lhs => rw [← diff_union_inter s u] - rw [integral_union disjoint_sdiff_inter (hs.inter u_open.measurableSet) + rw [setIntegral_union disjoint_sdiff_inter (hs.inter u_open.measurableSet) (h''i.mono_set diff_subset) (h''i.mono_set inter_subset_left)] _ ≤ ‖∫ x in s \ u, φ i x • g x ∂μ‖ + ‖∫ x in s ∩ u, φ i x • g x ∂μ‖ := norm_add_le _ _ _ ≤ (δ * ∫ x in s, ‖g x‖ ∂μ) + 2 * δ := add_le_add C B @@ -392,7 +392,7 @@ theorem tendsto_setIntegral_pow_smul_of_unique_maximum_of_isCompact_of_continuou ### Peak functions of the form `x ↦ c ^ dim * φ (c x)` -/ -open FiniteDimensional Bornology +open Module Bornology variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] [FiniteDimensional ℝ F] [MeasurableSpace F] [BorelSpace F] {μ : Measure F} [IsAddHaarMeasure μ] @@ -438,7 +438,7 @@ theorem tendsto_integral_comp_smul_smul_of_integrable simp [norm_smul, abs_of_pos cpos, mul_pow]; ring _ < δ ^ finrank ℝ F * ε := by apply hM - rw [div_lt_iff δpos] at hc + rw [div_lt_iff₀ δpos] at hc simp only [mem_compl_iff, mem_closedBall, dist_zero_right, norm_smul, Real.norm_eq_abs, abs_of_nonneg cpos.le, not_le, gt_iff_lt] exact hc.trans_le (by gcongr) diff --git a/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean b/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean index 20a484f42774c..b6a9c18db7857 100644 --- a/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean +++ b/Mathlib/MeasureTheory/Integral/RieszMarkovKakutani.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Jesse Reimann. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jesse Reimann, Kalle Kytölä -/ -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded import Mathlib.Topology.Sets.Compacts /-! diff --git a/Mathlib/MeasureTheory/Integral/SetIntegral.lean b/Mathlib/MeasureTheory/Integral/SetIntegral.lean index 38f00f6fd9293..0174fcb3cd94f 100644 --- a/Mathlib/MeasureTheory/Integral/SetIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/SetIntegral.lean @@ -7,7 +7,7 @@ import Mathlib.MeasureTheory.Integral.IntegrableOn import Mathlib.MeasureTheory.Integral.Bochner import Mathlib.MeasureTheory.Function.LocallyIntegrable import Mathlib.Topology.MetricSpace.ThickenedIndicator -import Mathlib.Topology.ContinuousFunction.ContinuousMapZero +import Mathlib.Topology.ContinuousMap.ContinuousMapZero import Mathlib.Analysis.NormedSpace.HahnBanach.SeparatingDual /-! @@ -21,7 +21,7 @@ and is zero otherwise. Since `∫ x in s, f x ∂μ` is a notation, one can rewrite or apply any theorem about `∫ x, f x ∂μ` directly. In this file we prove some theorems about dependence of `∫ x in s, f x ∂μ` on `s`, e.g. -`integral_union`, `integral_empty`, `integral_univ`. +`setIntegral_union`, `setIntegral_empty`, `setIntegral_univ`. We use the property `IntegrableOn f s μ := Integrable f (μ.restrict s)`, defined in `MeasureTheory.IntegrableOn`. We also defined in that same file a predicate @@ -82,38 +82,50 @@ theorem setIntegral_congr_ae (hs : MeasurableSet s) (h : ∀ᵐ x ∂μ, x ∈ s @[deprecated (since := "2024-04-17")] alias set_integral_congr_ae := setIntegral_congr_ae -theorem setIntegral_congr₀ (hs : NullMeasurableSet s μ) (h : EqOn f g s) : +theorem setIntegral_congr_fun₀ (hs : NullMeasurableSet s μ) (h : EqOn f g s) : ∫ x in s, f x ∂μ = ∫ x in s, g x ∂μ := setIntegral_congr_ae₀ hs <| Eventually.of_forall h +@[deprecated (since := "2024-10-12")] +alias setIntegral_congr₀ := setIntegral_congr_fun₀ + @[deprecated (since := "2024-04-17")] -alias set_integral_congr₀ := setIntegral_congr₀ +alias set_integral_congr₀ := setIntegral_congr_fun₀ -theorem setIntegral_congr (hs : MeasurableSet s) (h : EqOn f g s) : +theorem setIntegral_congr_fun (hs : MeasurableSet s) (h : EqOn f g s) : ∫ x in s, f x ∂μ = ∫ x in s, g x ∂μ := setIntegral_congr_ae hs <| Eventually.of_forall h +@[deprecated (since := "2024-10-12")] +alias setIntegral_congr := setIntegral_congr_fun + @[deprecated (since := "2024-04-17")] -alias set_integral_congr := setIntegral_congr +alias set_integral_congr := setIntegral_congr_fun -theorem setIntegral_congr_set_ae (hst : s =ᵐ[μ] t) : ∫ x in s, f x ∂μ = ∫ x in t, f x ∂μ := by +theorem setIntegral_congr_set (hst : s =ᵐ[μ] t) : ∫ x in s, f x ∂μ = ∫ x in t, f x ∂μ := by rw [Measure.restrict_congr_set hst] +@[deprecated (since := "2024-10-12")] +alias setIntegral_congr_set_ae := setIntegral_congr_set + @[deprecated (since := "2024-04-17")] -alias set_integral_congr_set_ae := setIntegral_congr_set_ae +alias set_integral_congr_set_ae := setIntegral_congr_set theorem integral_union_ae (hst : AEDisjoint μ s t) (ht : NullMeasurableSet t μ) (hfs : IntegrableOn f s μ) (hft : IntegrableOn f t μ) : ∫ x in s ∪ t, f x ∂μ = ∫ x in s, f x ∂μ + ∫ x in t, f x ∂μ := by simp only [IntegrableOn, Measure.restrict_union₀ hst ht, integral_add_measure hfs hft] -theorem integral_union (hst : Disjoint s t) (ht : MeasurableSet t) (hfs : IntegrableOn f s μ) +theorem setIntegral_union (hst : Disjoint s t) (ht : MeasurableSet t) (hfs : IntegrableOn f s μ) (hft : IntegrableOn f t μ) : ∫ x in s ∪ t, f x ∂μ = ∫ x in s, f x ∂μ + ∫ x in t, f x ∂μ := integral_union_ae hst.aedisjoint ht.nullMeasurableSet hfs hft +@[deprecated (since := "2024-10-12")] +alias integral_union := setIntegral_union + theorem integral_diff (ht : MeasurableSet t) (hfs : IntegrableOn f s μ) (hts : t ⊆ s) : ∫ x in s \ t, f x ∂μ = ∫ x in s, f x ∂μ - ∫ x in t, f x ∂μ := by - rw [eq_sub_iff_add_eq, ← integral_union, diff_union_of_subset hts] + rw [eq_sub_iff_add_eq, ← setIntegral_union, diff_union_of_subset hts] exacts [disjoint_sdiff_self_left, ht, hfs.mono_set diff_subset, hfs.mono_set hts] theorem integral_inter_add_diff₀ (ht : NullMeasurableSet t μ) (hfs : IntegrableOn f s μ) : @@ -134,7 +146,7 @@ theorem integral_finset_biUnion {ι : Type*} (t : Finset ι) {s : ι → Set X} · simp · simp only [Finset.coe_insert, Finset.forall_mem_insert, Set.pairwise_insert, Finset.set_biUnion_insert] at hs hf h's ⊢ - rw [integral_union _ _ hf.1 (integrableOn_finset_iUnion.2 hf.2)] + rw [setIntegral_union _ _ hf.1 (integrableOn_finset_iUnion.2 hf.2)] · rw [Finset.sum_insert hat, IH hs.2 h's.1 hf.2] · simp only [disjoint_iUnion_right] exact fun i hi => (h's.2 i hi (ne_of_mem_of_not_mem hi hat).symm).1 @@ -147,16 +159,22 @@ theorem integral_fintype_iUnion {ι : Type*} [Fintype ι] {s : ι → Set X} · simp · simp [pairwise_univ, h's] -theorem integral_empty : ∫ x in ∅, f x ∂μ = 0 := by +theorem setIntegral_empty : ∫ x in ∅, f x ∂μ = 0 := by rw [Measure.restrict_empty, integral_zero_measure] -theorem integral_univ : ∫ x in univ, f x ∂μ = ∫ x, f x ∂μ := by rw [Measure.restrict_univ] +@[deprecated (since := "2024-10-12")] +alias integral_empty := setIntegral_empty + +theorem setIntegral_univ : ∫ x in univ, f x ∂μ = ∫ x, f x ∂μ := by rw [Measure.restrict_univ] + +@[deprecated (since := "2024-10-12")] +alias integral_univ := setIntegral_univ theorem integral_add_compl₀ (hs : NullMeasurableSet s μ) (hfi : Integrable f μ) : ∫ x in s, f x ∂μ + ∫ x in sᶜ, f x ∂μ = ∫ x, f x ∂μ := by rw [ ← integral_union_ae disjoint_compl_right.aedisjoint hs.compl hfi.integrableOn hfi.integrableOn, - union_compl_self, integral_univ] + union_compl_self, setIntegral_univ] theorem integral_add_compl (hs : MeasurableSet s) (hfi : Integrable f μ) : ∫ x in s, f x ∂μ + ∫ x in sᶜ, f x ∂μ = ∫ x, f x ∂μ := @@ -328,7 +346,7 @@ theorem integral_union_eq_left_of_ae_aux (ht_eq : ∀ᵐ x ∂μ.restrict t, f x setIntegral_eq_zero_of_forall_eq_zero fun x hx => hx.2 rw [← integral_inter_add_diff hk h's, ← integral_inter_add_diff hk H, A, A, zero_add, zero_add, union_diff_distrib, union_comm] - apply setIntegral_congr_set_ae + apply setIntegral_congr_set rw [union_ae_eq_right] apply measure_mono_null diff_subset rw [measure_zero_iff_ae_nmem] @@ -371,7 +389,7 @@ theorem setIntegral_eq_of_subset_of_ae_diff_eq_zero_aux (hts : s ⊆ t) _ = ∫ x in t \ k, f x ∂μ := by rw [setIntegral_eq_zero_of_forall_eq_zero fun x hx => ?_, zero_add]; exact hx.2 _ = ∫ x in s \ k, f x ∂μ := by - apply setIntegral_congr_set_ae + apply setIntegral_congr_set filter_upwards [h't] with x hx change (x ∈ t \ k) = (x ∈ s \ k) simp only [mem_preimage, mem_singleton_iff, eq_iff_iff, and_congr_left_iff, mem_diff] @@ -430,7 +448,7 @@ coincides with its integral on the whole space. -/ theorem setIntegral_eq_integral_of_ae_compl_eq_zero (h : ∀ᵐ x ∂μ, x ∉ s → f x = 0) : ∫ x in s, f x ∂μ = ∫ x, f x ∂μ := by symm - nth_rw 1 [← integral_univ] + nth_rw 1 [← setIntegral_univ] apply setIntegral_eq_of_subset_of_ae_diff_eq_zero nullMeasurableSet_univ (subset_univ _) filter_upwards [h] with x hx h'x using hx h'x.2 @@ -471,14 +489,14 @@ theorem integral_norm_eq_pos_sub_neg {f : X → ℝ} (hfi : Integrable f μ) : rw [← integral_add_compl₀ h_meas hfi.norm] _ = ∫ x in {x | 0 ≤ f x}, f x ∂μ + ∫ x in {x | 0 ≤ f x}ᶜ, ‖f x‖ ∂μ := by congr 1 - refine setIntegral_congr₀ h_meas fun x hx => ?_ + refine setIntegral_congr_fun₀ h_meas fun x hx => ?_ dsimp only rw [Real.norm_eq_abs, abs_eq_self.mpr _] exact hx _ = ∫ x in {x | 0 ≤ f x}, f x ∂μ - ∫ x in {x | 0 ≤ f x}ᶜ, f x ∂μ := by congr 1 rw [← integral_neg] - refine setIntegral_congr₀ h_meas.compl fun x hx => ?_ + refine setIntegral_congr_fun₀ h_meas.compl fun x hx => ?_ dsimp only rw [Real.norm_eq_abs, abs_eq_neg_self.mpr _] rw [Set.mem_compl_iff, Set.nmem_setOf_iff] at hx @@ -518,7 +536,7 @@ theorem integral_indicatorConstLp [CompleteSpace E] ∫ x, indicatorConstLp p ht hμt e x ∂μ = (μ t).toReal • e := calc ∫ x, indicatorConstLp p ht hμt e x ∂μ = ∫ x in univ, indicatorConstLp p ht hμt e x ∂μ := by - rw [integral_univ] + rw [setIntegral_univ] _ = (μ (t ∩ univ)).toReal • e := setIntegral_indicatorConstLp MeasurableSet.univ ht hμt e _ = (μ t).toReal • e := by rw [inter_univ] @@ -676,31 +694,31 @@ variable [PartialOrder X] {x y : X} theorem integral_Icc_eq_integral_Ioc' (hx : μ {x} = 0) : ∫ t in Icc x y, f t ∂μ = ∫ t in Ioc x y, f t ∂μ := - setIntegral_congr_set_ae (Ioc_ae_eq_Icc' hx).symm + setIntegral_congr_set (Ioc_ae_eq_Icc' hx).symm theorem integral_Icc_eq_integral_Ico' (hy : μ {y} = 0) : ∫ t in Icc x y, f t ∂μ = ∫ t in Ico x y, f t ∂μ := - setIntegral_congr_set_ae (Ico_ae_eq_Icc' hy).symm + setIntegral_congr_set (Ico_ae_eq_Icc' hy).symm theorem integral_Ioc_eq_integral_Ioo' (hy : μ {y} = 0) : ∫ t in Ioc x y, f t ∂μ = ∫ t in Ioo x y, f t ∂μ := - setIntegral_congr_set_ae (Ioo_ae_eq_Ioc' hy).symm + setIntegral_congr_set (Ioo_ae_eq_Ioc' hy).symm theorem integral_Ico_eq_integral_Ioo' (hx : μ {x} = 0) : ∫ t in Ico x y, f t ∂μ = ∫ t in Ioo x y, f t ∂μ := - setIntegral_congr_set_ae (Ioo_ae_eq_Ico' hx).symm + setIntegral_congr_set (Ioo_ae_eq_Ico' hx).symm theorem integral_Icc_eq_integral_Ioo' (hx : μ {x} = 0) (hy : μ {y} = 0) : ∫ t in Icc x y, f t ∂μ = ∫ t in Ioo x y, f t ∂μ := - setIntegral_congr_set_ae (Ioo_ae_eq_Icc' hx hy).symm + setIntegral_congr_set (Ioo_ae_eq_Icc' hx hy).symm theorem integral_Iic_eq_integral_Iio' (hx : μ {x} = 0) : ∫ t in Iic x, f t ∂μ = ∫ t in Iio x, f t ∂μ := - setIntegral_congr_set_ae (Iio_ae_eq_Iic' hx).symm + setIntegral_congr_set (Iio_ae_eq_Iic' hx).symm theorem integral_Ici_eq_integral_Ioi' (hx : μ {x} = 0) : ∫ t in Ici x, f t ∂μ = ∫ t in Ioi x, f t ∂μ := - setIntegral_congr_set_ae (Ioi_ae_eq_Ici' hx).symm + setIntegral_congr_set (Ioi_ae_eq_Ici' hx).symm variable [NoAtoms μ] @@ -1260,7 +1278,7 @@ variable [NormedSpace ℝ F] [NormedSpace ℝ E] theorem integral_comp_comm (L : E ≃L[𝕜] F) (φ : X → E) : ∫ x, L (φ x) ∂μ = L (∫ x, φ x ∂μ) := by have : CompleteSpace E ↔ CompleteSpace F := - completeSpace_congr (e := L.toEquiv) L.uniformEmbedding + completeSpace_congr (e := L.toEquiv) L.isUniformEmbedding obtain ⟨_, _⟩|⟨_, _⟩ := iff_iff_and_or_not_and_not.mp this · exact L.toContinuousLinearMap.integral_comp_comm' L.antilipschitz _ · simp [integral, *] diff --git a/Mathlib/MeasureTheory/Integral/SetToL1.lean b/Mathlib/MeasureTheory/Integral/SetToL1.lean index 02dbf1cdd368b..b1c2e325add44 100644 --- a/Mathlib/MeasureTheory/Integral/SetToL1.lean +++ b/Mathlib/MeasureTheory/Integral/SetToL1.lean @@ -920,18 +920,18 @@ variable (𝕜) [NontriviallyNormedField 𝕜] [NormedSpace 𝕜 E] [NormedSpace def setToL1' (hT : DominatedFinMeasAdditive μ T C) (h_smul : ∀ c : 𝕜, ∀ s x, T s (c • x) = c • T s x) : (α →₁[μ] E) →L[𝕜] F := (setToL1SCLM' α E 𝕜 μ hT h_smul).extend (coeToLp α E 𝕜) (simpleFunc.denseRange one_ne_top) - simpleFunc.uniformInducing + simpleFunc.isUniformInducing variable {𝕜} /-- Extend `Set α → E →L[ℝ] F` to `(α →₁[μ] E) →L[ℝ] F`. -/ def setToL1 (hT : DominatedFinMeasAdditive μ T C) : (α →₁[μ] E) →L[ℝ] F := (setToL1SCLM α E μ hT).extend (coeToLp α E ℝ) (simpleFunc.denseRange one_ne_top) - simpleFunc.uniformInducing + simpleFunc.isUniformInducing theorem setToL1_eq_setToL1SCLM (hT : DominatedFinMeasAdditive μ T C) (f : α →₁ₛ[μ] E) : setToL1 hT f = setToL1SCLM α E μ hT f := - uniformly_extend_of_ind simpleFunc.uniformInducing (simpleFunc.denseRange one_ne_top) + uniformly_extend_of_ind simpleFunc.isUniformInducing (simpleFunc.denseRange one_ne_top) (setToL1SCLM α E μ hT).uniformContinuous _ theorem setToL1_eq_setToL1' (hT : DominatedFinMeasAdditive μ T C) diff --git a/Mathlib/MeasureTheory/Integral/TorusIntegral.lean b/Mathlib/MeasureTheory/Integral/TorusIntegral.lean index 2ac46ce80a629..9591233916874 100644 --- a/Mathlib/MeasureTheory/Integral/TorusIntegral.lean +++ b/Mathlib/MeasureTheory/Integral/TorusIntegral.lean @@ -220,10 +220,10 @@ theorem torusIntegral_succAbove ((Fin.insertNthOrderIso (fun _ => ℝ) i).preimage_Icc _ _).trans (Icc_prod_eq _ _) rw [torusIntegral, ← hem.map_eq, setIntegral_map_equiv, heπ, Measure.volume_eq_prod, setIntegral_prod, circleIntegral_def_Icc] - · refine setIntegral_congr measurableSet_Icc fun θ _ => ?_ + · refine setIntegral_congr_fun measurableSet_Icc fun θ _ => ?_ simp (config := { unfoldPartialApp := true }) only [e, torusIntegral, ← integral_smul, deriv_circleMap, i.prod_univ_succAbove _, smul_smul, torusMap, circleMap_zero] - refine setIntegral_congr measurableSet_Icc fun Θ _ => ?_ + refine setIntegral_congr_fun measurableSet_Icc fun Θ _ => ?_ simp only [MeasurableEquiv.piFinSuccAbove_symm_apply, i.insertNth_apply_same, i.insertNth_apply_succAbove, (· ∘ ·), Fin.insertNthEquiv, Equiv.coe_fn_mk] congr 2 diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean index b47c60a0d8a7f..61c55dee0d648 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Basic.lean @@ -231,7 +231,7 @@ theorem Subsingleton.measurable [Subsingleton α] : Measurable f := fun _ _ => theorem measurable_of_subsingleton_codomain [Subsingleton β] (f : α → β) : Measurable f := fun s _ => Subsingleton.set_cases MeasurableSet.empty MeasurableSet.univ s -@[to_additive (attr := measurability)] +@[to_additive (attr := measurability, fun_prop)] theorem measurable_one [One α] : Measurable (1 : β → α) := @measurable_const _ _ _ _ 1 diff --git a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean index 19be50fbff257..9ff18dc3605be 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/CountablyGenerated.lean @@ -516,7 +516,8 @@ variable [MeasurableSpace β] /-- A class registering that either `α` is countable or `β` is a countably generated measurable space. -/ -class CountableOrCountablyGenerated (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] : Prop := +class CountableOrCountablyGenerated (α β : Type*) [MeasurableSpace α] [MeasurableSpace β] : + Prop where countableOrCountablyGenerated : Countable α ∨ MeasurableSpace.CountablyGenerated β instance instCountableOrCountablyGeneratedOfCountable [h1 : Countable α] : diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean index 6345012319658..5c9f7d9d195dc 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Defs.lean @@ -534,7 +534,7 @@ variable [MeasurableSpace α] [MeasurableSpace β] [DiscreteMeasurableSpace α] @[measurability] lemma MeasurableSet.of_discrete : MeasurableSet s := DiscreteMeasurableSpace.forall_measurableSet _ -@[measurability] lemma Measurable.of_discrete : Measurable f := fun _ _ ↦ .of_discrete +@[measurability, fun_prop] lemma Measurable.of_discrete : Measurable f := fun _ _ ↦ .of_discrete @[deprecated MeasurableSet.of_discrete (since := "2024-08-25")] lemma measurableSet_discrete (s : Set α) : MeasurableSet s := .of_discrete diff --git a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean index 539df69ae463e..295f11d4408f2 100644 --- a/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean +++ b/Mathlib/MeasureTheory/MeasurableSpace/Embedding.lean @@ -60,6 +60,8 @@ structure MeasurableEmbedding [MeasurableSpace α] [MeasurableSpace β] (f : α /-- The image of a measurable set under a measurable embedding is a measurable set. -/ protected measurableSet_image' : ∀ ⦃s⦄, MeasurableSet s → MeasurableSet (f '' s) +attribute [fun_prop] MeasurableEmbedding.measurable + namespace MeasurableEmbedding variable {mα : MeasurableSpace α} [MeasurableSpace β] [MeasurableSpace γ] {f : α → β} {g : β → γ} @@ -155,7 +157,7 @@ instance instEquivLike : EquivLike (α ≃ᵐ β) α β where theorem coe_toEquiv (e : α ≃ᵐ β) : (e.toEquiv : α → β) = e := rfl -@[measurability] +@[measurability, fun_prop] protected theorem measurable (e : α ≃ᵐ β) : Measurable (e : α → β) := e.measurable_toFun @@ -350,6 +352,18 @@ def prodAssoc : (α × β) × γ ≃ᵐ α × β × γ where measurable_toFun := measurable_fst.fst.prod_mk <| measurable_fst.snd.prod_mk measurable_snd measurable_invFun := (measurable_fst.prod_mk measurable_snd.fst).prod_mk measurable_snd.snd +/-- `PUnit` is a left identity for product of measurable spaces up to a measurable equivalence. -/ +def punitProd : PUnit × α ≃ᵐ α where + toEquiv := Equiv.punitProd α + measurable_toFun := measurable_snd + measurable_invFun := measurable_prod_mk_left + +/-- `PUnit` is a right identity for product of measurable spaces up to a measurable equivalence. -/ +def prodPUnit : α × PUnit ≃ᵐ α where + toEquiv := Equiv.prodPUnit α + measurable_toFun := measurable_fst + measurable_invFun := measurable_prod_mk_right + variable [MeasurableSpace δ] in /-- Sums of measurable spaces are symmetric. -/ def sumCongr (ab : α ≃ᵐ β) (cd : γ ≃ᵐ δ) : α ⊕ γ ≃ᵐ β ⊕ δ where diff --git a/Mathlib/MeasureTheory/Measure/AddContent.lean b/Mathlib/MeasureTheory/Measure/AddContent.lean index b2e51584933b0..e07a40a78c24f 100644 --- a/Mathlib/MeasureTheory/Measure/AddContent.lean +++ b/Mathlib/MeasureTheory/Measure/AddContent.lean @@ -63,9 +63,8 @@ instance : Inhabited (AddContent C) := 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 + coe m s := m.toFun s + coe_injective' m m' _ := by cases m cases m' congr diff --git a/Mathlib/MeasureTheory/Measure/Content.lean b/Mathlib/MeasureTheory/Measure/Content.lean index 5306eb0281091..b07a09b9ad57e 100644 --- a/Mathlib/MeasureTheory/Measure/Content.lean +++ b/Mathlib/MeasureTheory/Measure/Content.lean @@ -310,7 +310,7 @@ variable [S : MeasurableSpace G] [BorelSpace G] /-- For the outer measure coming from a content, all Borel sets are measurable. -/ theorem borel_le_caratheodory : S ≤ μ.outerMeasure.caratheodory := by - rw [@BorelSpace.measurable_eq G _ _] + rw [BorelSpace.measurable_eq (α := G)] refine MeasurableSpace.generateFrom_le ?_ intro U hU rw [μ.outerMeasure_caratheodory] diff --git a/Mathlib/MeasureTheory/Measure/GiryMonad.lean b/Mathlib/MeasureTheory/Measure/GiryMonad.lean index c84c4f1258001..502d9433a781a 100644 --- a/Mathlib/MeasureTheory/Measure/GiryMonad.lean +++ b/Mathlib/MeasureTheory/Measure/GiryMonad.lean @@ -154,6 +154,11 @@ theorem bind_apply {m : Measure α} {f : α → Measure β} {s : Set β} (hs : M (hf : Measurable f) : bind m f s = ∫⁻ a, f a s ∂m := by rw [bind, join_apply hs, lintegral_map (measurable_coe hs) hf] +@[simp] +lemma bind_const {m : Measure α} {ν : Measure β} : m.bind (fun _ ↦ ν) = m Set.univ • ν := by + ext s hs + rw [bind_apply hs measurable_const, lintegral_const, smul_apply, smul_eq_mul, mul_comm] + theorem measurable_bind' {g : α → Measure β} (hg : Measurable g) : Measurable fun m => bind m g := measurable_join.comp (measurable_map _ hg) @@ -169,16 +174,27 @@ theorem bind_bind {γ} [MeasurableSpace γ] {m : Measure α} {f : α → Measure conv_rhs => enter [2, a]; erw [bind_apply hs hg] rfl -theorem bind_dirac {f : α → Measure β} (hf : Measurable f) (a : α) : bind (dirac a) f = f a := by +theorem dirac_bind {f : α → Measure β} (hf : Measurable f) (a : α) : bind (dirac a) f = f a := by ext1 s hs erw [bind_apply hs hf, lintegral_dirac' a ((measurable_coe hs).comp hf)] rfl -theorem dirac_bind {m : Measure α} : bind m dirac = m := by +@[simp] +theorem bind_dirac {m : Measure α} : bind m dirac = m := by ext1 s hs simp only [bind_apply hs measurable_dirac, dirac_apply' _ hs, lintegral_indicator 1 hs, Pi.one_apply, lintegral_one, restrict_apply, MeasurableSet.univ, univ_inter] +@[simp] +lemma bind_dirac_eq_map (m : Measure α) {f : α → β} (hf : Measurable f) : + m.bind (fun x ↦ Measure.dirac (f x)) = m.map f := by + ext s hs + rw [bind_apply hs] + swap; · exact measurable_dirac.comp hf + simp_rw [dirac_apply' _ hs] + rw [← lintegral_map _ hf, lintegral_indicator_one hs] + exact measurable_const.indicator hs + theorem join_eq_bind (μ : Measure (Measure α)) : join μ = bind μ id := by rw [bind, map_id] theorem join_map_map {f : α → β} (hf : Measurable f) (μ : Measure (Measure α)) : @@ -195,11 +211,10 @@ theorem join_map_join (μ : Measure (Measure (Measure α))) : join (map join μ) funext ν exact join_eq_bind ν -theorem join_map_dirac (μ : Measure α) : join (map dirac μ) = μ := - dirac_bind +theorem join_map_dirac (μ : Measure α) : join (map dirac μ) = μ := bind_dirac theorem join_dirac (μ : Measure α) : join (dirac μ) = μ := - (join_eq_bind (dirac μ)).trans (bind_dirac measurable_id _) + (join_eq_bind (dirac μ)).trans (dirac_bind measurable_id _) end Measure diff --git a/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean b/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean index cc3daa531971b..71eec8c794d88 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/InnerProductSpace.lean @@ -16,7 +16,7 @@ measure `1` to the parallelepiped spanned by any orthonormal basis, and that it the canonical `volume` from the `MeasureSpace` instance. -/ -open FiniteDimensional MeasureTheory MeasureTheory.Measure Set +open Module MeasureTheory MeasureTheory.Measure Set variable {ι E F : Type*} diff --git a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean index 29af339ad2552..a4030ed00f9d7 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/NormedSpace.lean @@ -18,7 +18,7 @@ open scoped NNReal ENNReal Pointwise Topology open Inv Set Function MeasureTheory.Measure Filter -open FiniteDimensional +open Module namespace MeasureTheory @@ -122,11 +122,11 @@ alias set_integral_comp_smul_of_pos := setIntegral_comp_smul_of_pos theorem integral_comp_mul_left (g : ℝ → F) (a : ℝ) : (∫ x : ℝ, g (a * x)) = |a⁻¹| • ∫ y : ℝ, g y := by - simp_rw [← smul_eq_mul, Measure.integral_comp_smul, FiniteDimensional.finrank_self, pow_one] + simp_rw [← smul_eq_mul, Measure.integral_comp_smul, Module.finrank_self, pow_one] theorem integral_comp_inv_mul_left (g : ℝ → F) (a : ℝ) : (∫ x : ℝ, g (a⁻¹ * x)) = |a| • ∫ y : ℝ, g y := by - simp_rw [← smul_eq_mul, Measure.integral_comp_inv_smul, FiniteDimensional.finrank_self, pow_one] + simp_rw [← smul_eq_mul, Measure.integral_comp_inv_smul, Module.finrank_self, pow_one] theorem integral_comp_mul_right (g : ℝ → F) (a : ℝ) : (∫ x : ℝ, g (x * a)) = |a⁻¹| • ∫ y : ℝ, g y := by diff --git a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean index 5c2649473b452..853e3faeab186 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/OfBasis.lean @@ -26,7 +26,7 @@ of the basis). -/ -open Set TopologicalSpace MeasureTheory MeasureTheory.Measure FiniteDimensional +open Set TopologicalSpace MeasureTheory MeasureTheory.Measure Module open scoped Pointwise @@ -162,7 +162,7 @@ theorem parallelepiped_single [DecidableEq ι] (a : ι → ℝ) : · rw [sup_eq_left.mpr hai, inf_eq_right.mpr hai] at h exact ⟨div_nonneg_of_nonpos h.2 hai, div_le_one_of_ge h.1 hai⟩ · rw [sup_eq_right.mpr hai, inf_eq_left.mpr hai] at h - exact ⟨div_nonneg h.1 hai, div_le_one_of_le h.2 hai⟩ + exact ⟨div_nonneg h.1 hai, div_le_one_of_le₀ h.2 hai⟩ · specialize h i simp only [smul_eq_mul, Pi.mul_apply] rcases eq_or_ne (a i) 0 with hai | hai @@ -290,7 +290,18 @@ end Fintype /-- A finite dimensional inner product space has a canonical measure, the Lebesgue measure giving volume `1` to the parallelepiped spanned by any orthonormal basis. We define the measure using some arbitrary choice of orthonormal basis. The fact that it works with any orthonormal basis -is proved in `orthonormalBasis.volume_parallelepiped`. -/ +is proved in `orthonormalBasis.volume_parallelepiped`. + +This instance creates: + +- a potential non-defeq diamond with the natural instance for `MeasureSpace (ULift E)`, + which does not exist in Mathlib at the moment; + +- a diamond with the existing instance `MeasureTheory.Measure.instMeasureSpacePUnit`. + +However, we've decided not to refactor until one of these diamonds starts creating issues, see +https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Hausdorff.20measure.20normalisation +-/ instance (priority := 100) measureSpaceOfInnerProductSpace [NormedAddCommGroup E] [InnerProductSpace ℝ E] [FiniteDimensional ℝ E] [MeasurableSpace E] [BorelSpace E] : MeasureSpace E where volume := (stdOrthonormalBasis ℝ E).toBasis.addHaar diff --git a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean index 4882bfa945404..6cb8d92d7d95f 100644 --- a/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean +++ b/Mathlib/MeasureTheory/Measure/Haar/Quotient.lean @@ -223,7 +223,7 @@ theorem MeasureTheory.QuotientMeasureEqMeasurePreimage.haarMeasure_quotient [Loc [IsFiniteMeasure μ] : IsHaarMeasure μ := by obtain ⟨K⟩ := PositiveCompacts.nonempty' (α := G) let K' : PositiveCompacts (G ⧸ Γ) := - K.map π continuous_coinduced_rng (QuotientGroup.isOpenMap_coe Γ) + K.map π QuotientGroup.continuous_mk QuotientGroup.isOpenMap_coe haveI : IsMulLeftInvariant μ := MeasureTheory.QuotientMeasureEqMeasurePreimage.mulInvariantMeasure_quotient ν rw [haarMeasure_unique μ K'] diff --git a/Mathlib/MeasureTheory/Measure/Hausdorff.lean b/Mathlib/MeasureTheory/Measure/Hausdorff.lean index 84bfe07b9e3fb..2558bd6c6aa54 100644 --- a/Mathlib/MeasureTheory/Measure/Hausdorff.lean +++ b/Mathlib/MeasureTheory/Measure/Hausdorff.lean @@ -109,7 +109,7 @@ Hausdorff measure, measure, metric measure open scoped NNReal ENNReal Topology -open EMetric Set Function Filter Encodable FiniteDimensional TopologicalSpace +open EMetric Set Function Filter Encodable Module TopologicalSpace noncomputable section @@ -183,7 +183,7 @@ theorem borel_le_caratheodory (hm : IsMetric μ) : borel X ≤ μ.caratheodory : suffices μ (⋃ n, S n) ≤ ⨆ n, μ (S n) by calc μ (s ∩ t) + μ (s \ t) = μ (s ∩ t) + μ (⋃ n, S n) := by rw [iUnion_S] _ ≤ μ (s ∩ t) + ⨆ n, μ (S n) := by gcongr - _ = ⨆ n, μ (s ∩ t) + μ (S n) := ENNReal.add_iSup + _ = ⨆ n, μ (s ∩ t) + μ (S n) := ENNReal.add_iSup .. _ ≤ μ s := iSup_le hSs /- It suffices to show that `∑' k, μ (S (k + 1) \ S k) ≠ ∞`. Indeed, if we have this, then for all `N` we have `μ (⋃ n, S n) ≤ μ (S N) + ∑' k, m (S (N + k + 1) \ S (N + k))` @@ -470,7 +470,7 @@ theorem mkMetric_apply (m : ℝ≥0∞ → ℝ≥0∞) (s : Set X) : simp only [← OuterMeasure.coe_mkMetric, OuterMeasure.mkMetric, OuterMeasure.mkMetric', OuterMeasure.iSup_apply, OuterMeasure.mkMetric'.pre, OuterMeasure.boundedBy_apply, extend] refine - surjective_id.iSup_congr (fun r => r) fun r => + surjective_id.iSup_congr (id) fun r => iSup_congr_Prop Iff.rfl fun _ => surjective_id.iInf_congr _ fun t => iInf_congr_Prop Iff.rfl fun ht => ?_ dsimp diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean index 264bf06f72a92..9ede8fdf04384 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/EqHaar.lean @@ -100,7 +100,7 @@ theorem Basis.map_addHaar {ι E F : Type*} [Fintype ι] [NormedAddCommGroup E] [ namespace MeasureTheory -open Measure TopologicalSpace.PositiveCompacts FiniteDimensional +open Measure TopologicalSpace.PositiveCompacts Module /-! ### The Lebesgue measure is a Haar measure on `ℝ` and on `ℝ^ι`. @@ -607,7 +607,6 @@ theorem tendsto_addHaar_inter_smul_zero_of_density_zero_aux1 (s : Set E) (x : E) rintro r (rpos : 0 < r) rw [← affinity_unitClosedBall rpos.le, singleton_add, ← image_vadd] gcongr - exact smul_set_mono t_bound have B : Tendsto (fun r : ℝ => μ (closedBall x r) / μ ({x} + r • u)) (𝓝[>] 0) (𝓝 (μ (closedBall x 1) / μ ({x} + u))) := by @@ -746,10 +745,8 @@ theorem tendsto_addHaar_inter_smul_one_of_density_one_aux (s : Set E) (hs : Meas rw [← ENNReal.sub_mul]; swap · simp only [uzero, ENNReal.inv_eq_top, imp_true_iff, Ne, not_false_iff] congr 1 - apply - ENNReal.sub_eq_of_add_eq (ne_top_of_le_ne_top utop (measure_mono inter_subset_right)) - rw [inter_comm _ u, inter_comm _ u] - exact measure_inter_add_diff u vmeas + rw [inter_comm _ u, inter_comm _ u, eq_comm] + exact ENNReal.eq_sub_of_add_eq' utop (measure_inter_add_diff u vmeas) have L : Tendsto (fun r => μ (sᶜ ∩ closedBall x r) / μ (closedBall x r)) (𝓝[>] 0) (𝓝 0) := by have A : Tendsto (fun r => μ (closedBall x r) / μ (closedBall x r)) (𝓝[>] 0) (𝓝 1) := by apply tendsto_const_nhds.congr' _ diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean index 15ee5ceb0977a..1b31285651c1c 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/Integral.lean @@ -95,7 +95,7 @@ theorem integral_comp_neg_Ioi {E : Type*} [NormedAddCommGroup E] [NormedSpace theorem integral_comp_abs {f : ℝ → ℝ} : ∫ x, f |x| = 2 * ∫ x in Ioi (0 : ℝ), f x := by have eq : ∫ (x : ℝ) in Ioi 0, f |x| = ∫ (x : ℝ) in Ioi 0, f x := by - refine setIntegral_congr measurableSet_Ioi (fun _ hx => ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun _ hx => ?_) rw [abs_eq_self.mpr (le_of_lt (by exact hx))] by_cases hf : IntegrableOn (fun x => f |x|) (Ioi 0) · have int_Iic : IntegrableOn (fun x ↦ f |x|) (Iic 0) := by @@ -106,13 +106,13 @@ theorem integral_comp_abs {f : ℝ → ℝ} : exact integrableOn_Ici_iff_integrableOn_Ioi.mpr hf calc _ = (∫ x in Iic 0, f |x|) + ∫ x in Ioi 0, f |x| := by - rw [← integral_union (Iic_disjoint_Ioi le_rfl) measurableSet_Ioi int_Iic hf, + rw [← setIntegral_union (Iic_disjoint_Ioi le_rfl) measurableSet_Ioi int_Iic hf, Iic_union_Ioi, restrict_univ] _ = 2 * ∫ x in Ioi 0, f x := by rw [two_mul, eq] congr! 1 rw [← neg_zero, ← integral_comp_neg_Iic, neg_zero] - refine setIntegral_congr measurableSet_Iic (fun _ hx => ?_) + refine setIntegral_congr_fun measurableSet_Iic (fun _ hx => ?_) rw [abs_eq_neg_self.mpr (by exact hx)] · have : ¬ Integrable (fun x => f |x|) := by contrapose! hf diff --git a/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean b/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean index a43d6a7133501..8cde3b7093566 100644 --- a/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean +++ b/Mathlib/MeasureTheory/Measure/Lebesgue/VolumeOfBalls.lean @@ -40,7 +40,7 @@ Using these formulas, we compute the volume of the unit balls in several cases. section general_case -open MeasureTheory MeasureTheory.Measure FiniteDimensional ENNReal +open MeasureTheory MeasureTheory.Measure Module ENNReal theorem MeasureTheory.measure_unitBall_eq_integral_div_gamma {E : Type*} {p : ℝ} [NormedAddCommGroup E] [NormedSpace ℝ E] [FiniteDimensional ℝ E] [MeasurableSpace E] @@ -48,10 +48,10 @@ theorem MeasureTheory.measure_unitBall_eq_integral_div_gamma {E : Type*} {p : μ (Metric.ball 0 1) = .ofReal ((∫ (x : E), Real.exp (- ‖x‖ ^ p) ∂μ) / Real.Gamma (finrank ℝ E / p + 1)) := by obtain hE | hE := subsingleton_or_nontrivial E - · rw [(Metric.nonempty_ball.mpr zero_lt_one).eq_zero, ← integral_univ, Set.univ_nonempty.eq_zero, - integral_singleton, finrank_zero_of_subsingleton, Nat.cast_zero, zero_div, zero_add, - Real.Gamma_one, div_one, norm_zero, Real.zero_rpow (ne_of_gt hp), neg_zero, Real.exp_zero, - smul_eq_mul, mul_one, ofReal_toReal (measure_ne_top μ {0})] + · rw [(Metric.nonempty_ball.mpr zero_lt_one).eq_zero, ← setIntegral_univ, + Set.univ_nonempty.eq_zero, integral_singleton, finrank_zero_of_subsingleton, Nat.cast_zero, + zero_div, zero_add, Real.Gamma_one, div_one, norm_zero, Real.zero_rpow hp.ne', neg_zero, + Real.exp_zero, smul_eq_mul, mul_one, ofReal_toReal (measure_ne_top μ {0})] · have : (0 : ℝ) < finrank ℝ E := Nat.cast_pos.mpr finrank_pos have : ((∫ y in Set.Ioi (0 : ℝ), y ^ (finrank ℝ E - 1) • Real.exp (-y ^ p)) / Real.Gamma ((finrank ℝ E) / p + 1)) * (finrank ℝ E) = 1 := by @@ -112,7 +112,7 @@ theorem MeasureTheory.measure_lt_one_eq_integral_div_gamma {p : ℝ} (hp : 0 < p -- The map `ψ` is measure preserving by construction have : @MeasurePreserving E F mE _ ψ μ ν := @Measurable.measurePreserving E F mE _ ψ (@MeasurableEquiv.measurable E F mE _ ψ) _ - erw [← this.integral_comp'] + rw [← this.integral_comp'] rfl theorem MeasureTheory.measure_le_eq_lt [Nontrivial E] (r : ℝ) : @@ -160,7 +160,7 @@ end general_case section LpSpace -open Real Fintype ENNReal FiniteDimensional MeasureTheory MeasureTheory.Measure +open Real Fintype ENNReal Module MeasureTheory MeasureTheory.Measure variable (ι : Type*) [Fintype ι] {p : ℝ} @@ -212,7 +212,7 @@ theorem MeasureTheory.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) simp_rw [← Set.preimage_smul_inv₀ (ne_of_gt hr), Set.preimage_setOf_eq, Pi.smul_apply, 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 + inv_mul_lt_iff₀ (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] @@ -284,7 +284,7 @@ theorem Complex.volume_sum_rpow_lt [Nonempty ι] {p : ℝ} (hp : 1 ≤ p) (r : convert addHaar_smul_of_nonneg volume (le_of_lt hr) {x : ι → ℂ | ∑ i, ‖x i‖ ^ p < 1} using 2 · 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 + (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 (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] @@ -350,7 +350,7 @@ end EuclideanSpace section InnerProductSpace -open MeasureTheory MeasureTheory.Measure ENNReal Real FiniteDimensional +open MeasureTheory MeasureTheory.Measure ENNReal Real Module variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] [FiniteDimensional ℝ E] [MeasurableSpace E] [BorelSpace E] [Nontrivial E] diff --git a/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean b/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean index 5b7eb39f8469e..fd684e18cafc6 100644 --- a/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean +++ b/Mathlib/MeasureTheory/Measure/LevyProkhorovMetric.lean @@ -28,10 +28,6 @@ import Mathlib.MeasureTheory.Integral.BoundedContinuousFunction probability measures on a separable space coincides with the topology of convergence in distribution, and in particular convergence in distribution is then pseudometrizable. -## TODO - -* Show that in Borel spaces, the Lévy-Prokhorov distance is a metric; not just a pseudometric. - ## Tags finite measure, probability measure, weak convergence, convergence in distribution, metrizability @@ -198,6 +194,9 @@ lemma levyProkhorovDist_triangle [OpensMeasurableSpace Ω] (μ ν κ : Measure when they are to be equipped with the Lévy-Prokhorov distance. -/ def LevyProkhorov (α : Type*) := α +/-- The "identity" equivalence between the type synonym `LevyProkhorov α` and `α`. -/ +def LevyProkhorov.equiv (α : Type*) : LevyProkhorov α ≃ α := Equiv.refl _ + variable [OpensMeasurableSpace Ω] /-- The Lévy-Prokhorov distance `levyProkhorovEDist` makes `Measure Ω` a pseudoemetric @@ -219,9 +218,43 @@ noncomputable instance levyProkhorovDist_pseudoMetricSpace_finiteMeasure : dist_triangle μ ν κ := levyProkhorovDist_triangle _ _ _ edist_dist μ ν := by simp [← ENNReal.ofReal_coe_nnreal] -/-- The Lévy-Prokhorov distance `levyProkhorovDist` makes `ProbabilityMeasure Ω` a pseudoemetric +lemma measure_le_measure_closure_of_levyProkhorovEDist_eq_zero {μ ν : Measure Ω} + (hLP : levyProkhorovEDist μ ν = 0) {s : Set Ω} (s_mble : MeasurableSet s) + (h_finite : ∃ δ > 0, ν (thickening δ s) ≠ ∞) : + μ s ≤ ν (closure s) := by + have key : Tendsto (fun ε ↦ ν (thickening ε.toReal s)) (𝓝[>] (0 : ℝ≥0∞)) (𝓝 (ν (closure s))) := by + have aux : Tendsto ENNReal.toReal (𝓝[>] 0) (𝓝[>] 0) := by + apply tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within (s := Ioi 0) ENNReal.toReal + · exact tendsto_nhdsWithin_of_tendsto_nhds (continuousAt_toReal zero_ne_top).tendsto + · filter_upwards [Ioo_mem_nhdsWithin_Ioi ⟨le_rfl, zero_lt_one⟩] with x hx + exact toReal_pos hx.1.ne.symm <| ne_top_of_lt hx.2 + exact (tendsto_measure_thickening h_finite).comp aux + have obs := Tendsto.add key (tendsto_nhdsWithin_of_tendsto_nhds tendsto_id) + simp only [id_eq, add_zero] at obs + apply ge_of_tendsto (b := μ s) obs + filter_upwards [self_mem_nhdsWithin] with ε ε_pos + exact left_measure_le_of_levyProkhorovEDist_lt (B_mble := s_mble) (hLP ▸ ε_pos) + +/-- Two measures at vanishing Lévy-Prokhorov distance from each other assign the same values to all +closed sets. -/ +lemma measure_eq_measure_of_levyProkhorovEDist_eq_zero_of_isClosed {μ ν : Measure Ω} + (hLP : levyProkhorovEDist μ ν = 0) {s : Set Ω} (s_closed : IsClosed s) + (hμs : ∃ δ > 0, μ (thickening δ s) ≠ ∞) (hνs : ∃ δ > 0, ν (thickening δ s) ≠ ∞) : + μ s = ν s := by + apply le_antisymm + · exact measure_le_measure_closure_of_levyProkhorovEDist_eq_zero + hLP s_closed.measurableSet hνs |>.trans <| + le_of_eq (congr_arg _ s_closed.closure_eq) + · exact measure_le_measure_closure_of_levyProkhorovEDist_eq_zero + (levyProkhorovEDist_comm μ ν ▸ hLP) s_closed.measurableSet hμs |>.trans <| + le_of_eq (congr_arg _ s_closed.closure_eq) + +/-- The Lévy-Prokhorov distance `levyProkhorovDist` makes `ProbabilityMeasure Ω` a pseudometric space. The instance is recorded on the type synonym -`LevyProkhorov (ProbabilityMeasure Ω) := ProbabilityMeasure Ω`. -/ +`LevyProkhorov (ProbabilityMeasure Ω) := ProbabilityMeasure Ω`. + +Note: For this pseudometric to give the topology of convergence in distribution, one must +furthermore assume that `Ω` is separable. -/ noncomputable instance levyProkhorovDist_pseudoMetricSpace_probabilityMeasure : PseudoMetricSpace (LevyProkhorov (ProbabilityMeasure Ω)) where dist μ ν := levyProkhorovDist μ.toMeasure ν.toMeasure @@ -233,6 +266,29 @@ noncomputable instance levyProkhorovDist_pseudoMetricSpace_probabilityMeasure : lemma LevyProkhorov.dist_def (μ ν : LevyProkhorov (ProbabilityMeasure Ω)) : dist μ ν = levyProkhorovDist μ.toMeasure ν.toMeasure := rfl +/-- If `Ω` is a Borel space, then the Lévy-Prokhorov distance `levyProkhorovDist` makes +`ProbabilityMeasure Ω` a metric space. The instance is recorded on the type synonym +`LevyProkhorov (ProbabilityMeasure Ω) := ProbabilityMeasure Ω`. + +Note: For this metric to give the topology of convergence in distribution, one must +furthermore assume that `Ω` is separable. -/ +noncomputable instance levyProkhorovDist_metricSpace_probabilityMeasure [BorelSpace Ω] : + MetricSpace (LevyProkhorov (ProbabilityMeasure Ω)) where + eq_of_dist_eq_zero := by + intro μ ν h + apply (LevyProkhorov.equiv _).injective + apply ProbabilityMeasure.toMeasure_injective + apply ext_of_generate_finite _ ?_ isPiSystem_isClosed ?_ (by simp) + · rw [BorelSpace.measurable_eq (α := Ω), borel_eq_generateFrom_isClosed] + · intro A A_closed + apply measure_eq_measure_of_levyProkhorovEDist_eq_zero_of_isClosed + · simpa only [levyProkhorovEDist_ne_top μ.toMeasure ν.toMeasure, mem_setOf_eq, + or_false, ne_eq, zero_ne_top, not_false_eq_true, zero_toReal] + using (toReal_eq_zero_iff _).mp h + · exact A_closed + · exact ⟨1, Real.zero_lt_one, measure_ne_top _ _⟩ + · exact ⟨1, Real.zero_lt_one, measure_ne_top _ _⟩ + /-- A simple sufficient condition for bounding `levyProkhorovEDist` between probability measures from above. The condition involves only one of two natural bounds, the other bound is for free. -/ lemma levyProkhorovEDist_le_of_forall_le @@ -279,20 +335,6 @@ open BoundedContinuousFunction variable {ι : Type*} {Ω : Type*} [MeasurableSpace Ω] -/-- Coercion from the type synonym `LevyProkhorov (ProbabilityMeasure Ω)` -to `ProbabilityMeasure Ω`. -/ -def LevyProkhorov.toProbabilityMeasure (μ : LevyProkhorov (ProbabilityMeasure Ω)) : - ProbabilityMeasure Ω := μ - -/-- Coercion to the type synonym `LevyProkhorov (ProbabilityMeasure Ω)` -from `ProbabilityMeasure Ω`. -/ -def ProbabilityMeasure.toLevyProkhorov (μ : ProbabilityMeasure Ω) : - LevyProkhorov (ProbabilityMeasure Ω) := μ - -/-- Coercion from the type synonym `LevyProkhorov (FiniteMeasure Ω)` to `FiniteMeasure Ω`. -/ -def LevyProkhorov.finiteMeasure (μ : LevyProkhorov (FiniteMeasure Ω)) : - FiniteMeasure Ω := μ - variable [PseudoMetricSpace Ω] [OpensMeasurableSpace Ω] /-- A version of the layer cake formula for bounded continuous functions which have finite integral: @@ -384,13 +426,13 @@ lemma tendsto_integral_meas_thickening_le (f : Ω →ᵇ ℝ) · exact isClosed_le continuous_const f.continuous · exact measure_ne_top _ _ -/-- The coercion `LevyProkhorov (ProbabilityMeasure Ω) → ProbabilityMeasure Ω` is continuous. -/ -lemma LevyProkhorov.continuous_toProbabilityMeasure : - Continuous (LevyProkhorov.toProbabilityMeasure (Ω := Ω)) := by +/-- The identity map `LevyProkhorov (ProbabilityMeasure Ω) → ProbabilityMeasure Ω` is continuous. -/ +lemma LevyProkhorov.continuous_equiv_probabilityMeasure : + Continuous (LevyProkhorov.equiv (α := ProbabilityMeasure Ω)) := by refine SeqContinuous.continuous ?_ intro μs ν hμs - set P := ν.toProbabilityMeasure -- more palatable notation - set Ps := fun n ↦ (μs n).toProbabilityMeasure -- more palatable notation + set P := LevyProkhorov.equiv _ ν -- more palatable notation + set Ps := fun n ↦ LevyProkhorov.equiv _ (μs n) -- more palatable notation rw [ProbabilityMeasure.tendsto_iff_forall_integral_tendsto] refine fun f ↦ tendsto_integral_of_forall_limsup_integral_le_integral ?_ f intro f f_nn @@ -433,9 +475,8 @@ lemma LevyProkhorov.continuous_toProbabilityMeasure : · rw [ENNReal.ofReal_add (by positivity) (by positivity), ← add_zero (levyProkhorovEDist _ _)] apply ENNReal.add_lt_add_of_le_of_lt (levyProkhorovEDist_ne_top _ _) (le_of_eq ?_) (ofReal_pos.mpr εs_pos) - rw [LevyProkhorov.dist_def, levyProkhorovDist, - ofReal_toReal (levyProkhorovEDist_ne_top _ _)] - simp only [Ps, P, LevyProkhorov.toProbabilityMeasure] + rw [LevyProkhorov.dist_def, levyProkhorovDist, ofReal_toReal (levyProkhorovEDist_ne_top _ _)] + rfl · exact Eventually.of_forall f_nn · simp only [IsCoboundedUnder, IsCobounded, eventually_map, eventually_atTop, forall_exists_index] @@ -444,9 +485,9 @@ lemma LevyProkhorov.continuous_toProbabilityMeasure : /-- The topology of the Lévy-Prokhorov metric is at least as fine as the topology of convergence in distribution. -/ theorem levyProkhorov_le_convergenceInDistribution : - TopologicalSpace.coinduced (LevyProkhorov.toProbabilityMeasure (Ω := Ω)) inferInstance + TopologicalSpace.coinduced (LevyProkhorov.equiv (α := ProbabilityMeasure Ω)) inferInstance ≤ (inferInstance : TopologicalSpace (ProbabilityMeasure Ω)) := - (LevyProkhorov.continuous_toProbabilityMeasure).coinduced_le + (LevyProkhorov.continuous_equiv_probabilityMeasure).coinduced_le end Levy_Prokhorov_is_finer @@ -456,13 +497,34 @@ section Levy_Prokhorov_metrizes_convergence_in_distribution open BoundedContinuousFunction TopologicalSpace -variable {ι : Type*} (Ω : Type*) [PseudoMetricSpace Ω] +variable {ι : Type*} {Ω : Type*} [PseudoMetricSpace Ω] variable [MeasurableSpace Ω] [OpensMeasurableSpace Ω] +lemma ProbabilityMeasure.toMeasure_add_pos_gt_mem_nhds (P : ProbabilityMeasure Ω) + {G : Set Ω} (G_open : IsOpen G) {ε : ℝ≥0∞} (ε_pos : 0 < ε) : + {Q | P.toMeasure G < Q.toMeasure G + ε} ∈ 𝓝 P := by + by_cases easy : P.toMeasure G < ε + · exact Eventually.of_forall (fun _ ↦ lt_of_lt_of_le easy le_add_self) + by_cases ε_top : ε = ∞ + · simp [ε_top, measure_lt_top] + simp only [not_lt] at easy + have aux : P.toMeasure G - ε < liminf (fun Q ↦ Q.toMeasure G) (𝓝 P) := by + apply lt_of_lt_of_le (ENNReal.sub_lt_self (measure_lt_top _ _).ne _ _) + <| ProbabilityMeasure.le_liminf_measure_open_of_tendsto tendsto_id G_open + · exact (lt_of_lt_of_le ε_pos easy).ne.symm + · exact ε_pos.ne.symm + filter_upwards [gt_mem_sets_of_limsInf_gt (α := ℝ≥0∞) isBounded_ge_of_bot + (show P.toMeasure G - ε < limsInf ((𝓝 P).map (fun Q ↦ Q.toMeasure G)) from aux)] with Q hQ + simp only [preimage_setOf_eq, mem_setOf_eq] at hQ + convert ENNReal.add_lt_add_right ε_top hQ + exact (tsub_add_cancel_of_le easy).symm + +variable [SeparableSpace Ω] + +variable (Ω) in /-- In a separable pseudometric space, for any ε > 0 there exists a countable collection of disjoint Borel measurable subsets of diameter at most ε that cover the whole space. -/ -lemma SeparableSpace.exists_measurable_partition_diam_le [SeparableSpace Ω] - {ε : ℝ} (ε_pos : 0 < ε) : +lemma SeparableSpace.exists_measurable_partition_diam_le {ε : ℝ} (ε_pos : 0 < ε) : ∃ (As : ℕ → Set Ω), (∀ n, MeasurableSet (As n)) ∧ (∀ n, Bornology.IsBounded (As n)) ∧ (∀ n, diam (As n) ≤ ε) ∧ (⋃ n, As n = univ) ∧ (Pairwise (fun (n m : ℕ) ↦ Disjoint (As n) (As m))) := by @@ -492,29 +554,8 @@ lemma SeparableSpace.exists_measurable_partition_diam_le [SeparableSpace Ω] simpa only [← aux] using iUnion_disjointed · exact disjoint_disjointed Bs -variable {Ω} - -lemma ProbabilityMeasure.toMeasure_add_pos_gt_mem_nhds (P : ProbabilityMeasure Ω) - {G : Set Ω} (G_open : IsOpen G) {ε : ℝ≥0∞} (ε_pos : 0 < ε) : - {Q | P.toMeasure G < Q.toMeasure G + ε} ∈ 𝓝 P := by - by_cases easy : P.toMeasure G < ε - · exact Eventually.of_forall (fun _ ↦ lt_of_lt_of_le easy le_add_self) - by_cases ε_top : ε = ∞ - · simp [ε_top, measure_lt_top] - simp only [not_lt] at easy - have aux : P.toMeasure G - ε < liminf (fun Q ↦ Q.toMeasure G) (𝓝 P) := by - apply lt_of_lt_of_le (ENNReal.sub_lt_self (measure_lt_top _ _).ne _ _) - <| ProbabilityMeasure.le_liminf_measure_open_of_tendsto tendsto_id G_open - · exact (lt_of_lt_of_le ε_pos easy).ne.symm - · exact ε_pos.ne.symm - filter_upwards [gt_mem_sets_of_limsInf_gt (α := ℝ≥0∞) isBounded_ge_of_bot - (show P.toMeasure G - ε < limsInf ((𝓝 P).map (fun Q ↦ Q.toMeasure G)) from aux)] with Q hQ - simp only [preimage_setOf_eq, mem_setOf_eq] at hQ - convert ENNReal.add_lt_add_right ε_top hQ - exact (tsub_add_cancel_of_le easy).symm - -lemma ProbabilityMeasure.continuous_toLevyProkhorov [SeparableSpace Ω] : - Continuous (ProbabilityMeasure.toLevyProkhorov (Ω := Ω)) := by +lemma LevyProkhorov.continuous_equiv_symm_probabilityMeasure : + Continuous (LevyProkhorov.equiv (α := ProbabilityMeasure Ω)).symm := by -- We check continuity of `id : ProbabilityMeasure Ω → LevyProkhorov (ProbabilityMeasure Ω)` at -- each point `P : ProbabilityMeasure Ω`. rw [continuous_iff_continuousAt] @@ -612,22 +653,22 @@ lemma ProbabilityMeasure.continuous_toLevyProkhorov [SeparableSpace Ω] : /-- The topology of the Lévy-Prokhorov metric on probability measures on a separable space coincides with the topology of convergence in distribution. -/ -theorem levyProkhorov_eq_convergenceInDistribution [SeparableSpace Ω] : +theorem levyProkhorov_eq_convergenceInDistribution : (inferInstance : TopologicalSpace (ProbabilityMeasure Ω)) - = TopologicalSpace.coinduced (LevyProkhorov.toProbabilityMeasure (Ω := Ω)) inferInstance := - le_antisymm (ProbabilityMeasure.continuous_toLevyProkhorov (Ω := Ω)).coinduced_le + = TopologicalSpace.coinduced (LevyProkhorov.equiv _) inferInstance := + le_antisymm (LevyProkhorov.continuous_equiv_symm_probabilityMeasure (Ω := Ω)).coinduced_le levyProkhorov_le_convergenceInDistribution /-- The identity map is a homeomorphism from `ProbabilityMeasure Ω` with the topology of convergence in distribution to `ProbabilityMeasure Ω` with the Lévy-Prokhorov (pseudo)metric. -/ -def homeomorph_probabilityMeasure_levyProkhorov [SeparableSpace Ω] : +def homeomorph_probabilityMeasure_levyProkhorov : ProbabilityMeasure Ω ≃ₜ LevyProkhorov (ProbabilityMeasure Ω) where - toFun := ProbabilityMeasure.toLevyProkhorov (Ω := Ω) - invFun := LevyProkhorov.toProbabilityMeasure (Ω := Ω) + toFun := LevyProkhorov.equiv _ + invFun := (LevyProkhorov.equiv _).symm left_inv := congrFun rfl right_inv := congrFun rfl - continuous_toFun := ProbabilityMeasure.continuous_toLevyProkhorov - continuous_invFun := LevyProkhorov.continuous_toProbabilityMeasure + continuous_toFun := LevyProkhorov.continuous_equiv_symm_probabilityMeasure + continuous_invFun := LevyProkhorov.continuous_equiv_probabilityMeasure /-- The topology of convergence in distribution on a separable space is pseudo-metrizable. -/ instance (X : Type*) [TopologicalSpace X] [PseudoMetrizableSpace X] [SeparableSpace X] @@ -636,6 +677,13 @@ instance (X : Type*) [TopologicalSpace X] [PseudoMetrizableSpace X] [SeparableSp letI : PseudoMetricSpace X := TopologicalSpace.pseudoMetrizableSpacePseudoMetric X (homeomorph_probabilityMeasure_levyProkhorov (Ω := X)).inducing.pseudoMetrizableSpace +/-- The topology of convergence in distribution on a separable Borel space is metrizable. -/ +instance instMetrizableSpaceProbabilityMeasure (X : Type*) [TopologicalSpace X] + [PseudoMetrizableSpace X] [SeparableSpace X] [MeasurableSpace X] [BorelSpace X] : + MetrizableSpace (ProbabilityMeasure X) := by + letI : PseudoMetricSpace X := TopologicalSpace.pseudoMetrizableSpacePseudoMetric X + exact homeomorph_probabilityMeasure_levyProkhorov.embedding.metrizableSpace + end Levy_Prokhorov_metrizes_convergence_in_distribution end MeasureTheory -- namespace diff --git a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean index 033d11b1cb4a5..2c1821c1225d6 100644 --- a/Mathlib/MeasureTheory/Measure/MeasureSpace.lean +++ b/Mathlib/MeasureTheory/Measure/MeasureSpace.lean @@ -214,7 +214,7 @@ theorem measure_add_diff (hs : NullMeasurableSet s μ) (t : Set α) : theorem measure_diff' (s : Set α) (hm : NullMeasurableSet t μ) (h_fin : μ t ≠ ∞) : μ (s \ t) = μ (s ∪ t) - μ t := - Eq.symm <| ENNReal.sub_eq_of_add_eq h_fin <| by rw [add_comm, measure_add_diff hm, union_comm] + ENNReal.eq_sub_of_add_eq h_fin <| by rw [add_comm, measure_add_diff hm, union_comm] theorem measure_diff (h : s₂ ⊆ s₁) (h₂ : NullMeasurableSet s₂ μ) (h_fin : μ s₂ ≠ ∞) : μ (s₁ \ s₂) = μ s₁ - μ s₂ := by rw [measure_diff' _ h₂ h_fin, union_eq_self_of_subset_right h] @@ -543,25 +543,27 @@ theorem measure_iInter_eq_iInf' {α ι : Type*} [MeasurableSpace α] {μ : Measu /-- Continuity from below: the measure of the union of an increasing sequence of (not necessarily measurable) sets is the limit of the measures. -/ -theorem tendsto_measure_iUnion_atTop [Preorder ι] [IsDirected ι (· ≤ ·)] - [IsCountablyGenerated (atTop : Filter ι)] {s : ι → Set α} (hm : Monotone s) : - Tendsto (μ ∘ s) atTop (𝓝 (μ (⋃ n, s n))) := by +theorem tendsto_measure_iUnion_atTop [Preorder ι] [IsCountablyGenerated (atTop : Filter ι)] + {s : ι → Set α} (hm : Monotone s) : Tendsto (μ ∘ s) atTop (𝓝 (μ (⋃ n, s n))) := by + refine .of_neBot_imp fun h ↦ ?_ + have := (atTop_neBot_iff.1 h).2 rw [hm.measure_iUnion] exact tendsto_atTop_iSup fun n m hnm => measure_mono <| hm hnm @[deprecated (since := "2024-09-01")] alias tendsto_measure_iUnion := tendsto_measure_iUnion_atTop -theorem tendsto_measure_iUnion_atBot [Preorder ι] [IsDirected ι (· ≥ ·)] - [IsCountablyGenerated (atBot : Filter ι)] {s : ι → Set α} (hm : Antitone s) : - Tendsto (μ ∘ s) atBot (𝓝 (μ (⋃ n, s n))) := +theorem tendsto_measure_iUnion_atBot [Preorder ι] [IsCountablyGenerated (atBot : Filter ι)] + {s : ι → Set α} (hm : Antitone s) : Tendsto (μ ∘ s) atBot (𝓝 (μ (⋃ n, s n))) := tendsto_measure_iUnion_atTop (ι := ιᵒᵈ) hm.dual_left /-- Continuity from below: the measure of the union of a sequence of (not necessarily measurable) sets is the limit of the measures of the partial unions. -/ theorem tendsto_measure_iUnion_accumulate {α ι : Type*} - [Preorder ι] [IsDirected ι (· ≤ ·)] [IsCountablyGenerated (atTop : Filter ι)] + [Preorder ι] [IsCountablyGenerated (atTop : Filter ι)] [MeasurableSpace α] {μ : Measure α} {f : ι → Set α} : Tendsto (fun i ↦ μ (Accumulate f i)) atTop (𝓝 (μ (⋃ i, f i))) := by + refine .of_neBot_imp fun h ↦ ?_ + have := (atTop_neBot_iff.1 h).2 rw [measure_iUnion_eq_iSup_accumulate] exact tendsto_atTop_iSup fun i j hij ↦ by gcongr @@ -570,9 +572,11 @@ alias tendsto_measure_iUnion' := tendsto_measure_iUnion_accumulate /-- Continuity from above: the measure of the intersection of a decreasing sequence of measurable sets is the limit of the measures. -/ -theorem tendsto_measure_iInter [Countable ι] [Preorder ι] [IsDirected ι (· ≤ ·)] {s : ι → Set α} +theorem tendsto_measure_iInter [Countable ι] [Preorder ι] {s : ι → Set α} (hs : ∀ n, NullMeasurableSet (s n) μ) (hm : Antitone s) (hf : ∃ i, μ (s i) ≠ ∞) : Tendsto (μ ∘ s) atTop (𝓝 (μ (⋂ n, s n))) := by + refine .of_neBot_imp fun h ↦ ?_ + have := (atTop_neBot_iff.1 h).2 rw [measure_iInter_eq_iInf hs hm.directed_ge hf] exact tendsto_atTop_iInf fun n m hnm => measure_mono <| hm hnm @@ -1830,27 +1834,25 @@ theorem biSup_measure_Iic [Preorder α] {s : Set α} (hsc : s.Countable) exact iUnion₂_eq_univ_iff.2 hst · exact directedOn_iff_directed.2 (hdir.directed_val.mono_comp _ fun x y => Iic_subset_Iic.2) -theorem tendsto_measure_Ico_atTop [Preorder α] [IsDirected α (· ≤ ·)] [NoMaxOrder α] +theorem tendsto_measure_Ico_atTop [Preorder α] [NoMaxOrder α] [(atTop : Filter α).IsCountablyGenerated] (μ : Measure α) (a : α) : Tendsto (fun x => μ (Ico a x)) atTop (𝓝 (μ (Ici a))) := by rw [← iUnion_Ico_right] exact tendsto_measure_iUnion_atTop (antitone_const.Ico monotone_id) -theorem tendsto_measure_Ioc_atBot [Preorder α] [IsDirected α (· ≥ ·)] [NoMinOrder α] +theorem tendsto_measure_Ioc_atBot [Preorder α] [NoMinOrder α] [(atBot : Filter α).IsCountablyGenerated] (μ : Measure α) (a : α) : Tendsto (fun x => μ (Ioc x a)) atBot (𝓝 (μ (Iic a))) := by rw [← iUnion_Ioc_left] exact tendsto_measure_iUnion_atBot (monotone_id.Ioc antitone_const) -theorem tendsto_measure_Iic_atTop [Preorder α] [IsDirected α (· ≤ ·)] - [(atTop : Filter α).IsCountablyGenerated] (μ : Measure α) : - Tendsto (fun x => μ (Iic x)) atTop (𝓝 (μ univ)) := by +theorem tendsto_measure_Iic_atTop [Preorder α] [(atTop : Filter α).IsCountablyGenerated] + (μ : Measure α) : Tendsto (fun x => μ (Iic x)) atTop (𝓝 (μ univ)) := by rw [← iUnion_Iic] exact tendsto_measure_iUnion_atTop monotone_Iic -theorem tendsto_measure_Ici_atBot [Preorder α] [IsDirected α (· ≥ ·)] - [(atBot : Filter α).IsCountablyGenerated] (μ : Measure α) : - Tendsto (fun x => μ (Ici x)) atBot (𝓝 (μ univ)) := +theorem tendsto_measure_Ici_atBot [Preorder α] [(atBot : Filter α).IsCountablyGenerated] + (μ : Measure α) : Tendsto (fun x => μ (Ici x)) atBot (𝓝 (μ univ)) := tendsto_measure_Iic_atTop (α := αᵒᵈ) μ variable [PartialOrder α] {a b : α} diff --git a/Mathlib/MeasureTheory/Measure/NullMeasurable.lean b/Mathlib/MeasureTheory/Measure/NullMeasurable.lean index 09e4f3a49eccb..3f2767ff07960 100644 --- a/Mathlib/MeasureTheory/Measure/NullMeasurable.lean +++ b/Mathlib/MeasureTheory/Measure/NullMeasurable.lean @@ -280,6 +280,9 @@ theorem measure_union₀' (hs : NullMeasurableSet s μ) (hd : AEDisjoint μ s t) theorem measure_add_measure_compl₀ {s : Set α} (hs : NullMeasurableSet s μ) : μ s + μ sᶜ = μ univ := by rw [← measure_union₀' hs aedisjoint_compl_right, union_compl_self] +lemma measure_of_measure_compl_eq_zero (hs : μ sᶜ = 0) : μ s = μ Set.univ := by + simpa [hs] using measure_add_measure_compl₀ <| .of_compl <| .of_null hs + section MeasurableSingletonClass variable [MeasurableSingletonClass (NullMeasurableSpace α μ)] diff --git a/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean b/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean index a475581af381f..167c0d5bdfb53 100644 --- a/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean +++ b/Mathlib/MeasureTheory/Measure/SeparableMeasure.lean @@ -32,7 +32,7 @@ of separability in the metric space made by constant indicators equipped with th ## Main definitions -* `MeasureTheory.Measure.μ.MeasureDense 𝒜`: `𝒜` is a measure-dense family if it only contains +* `MeasureTheory.Measure.MeasureDense μ 𝒜`: `𝒜` is a measure-dense family if it only contains measurable sets and if the following condition is satisfied: if `s` is measurable with finite measure, then for any `ε > 0` there exists `t ∈ 𝒜` such that `μ (s ∆ t) < ε `. * `MeasureTheory.IsSeparable`: A measure is separable if there exists a countable and @@ -83,12 +83,11 @@ sets with finite measures. The term "measure-dense" is justified by the fact that the approximating condition translates to the usual notion of density in the metric space made by constant indicators of measurable sets equipped with the `Lᵖ` norm. -/ -structure Measure.MeasureDense (μ : Measure X) (𝒜 : Set (Set X)) : Prop := +structure Measure.MeasureDense (μ : Measure X) (𝒜 : Set (Set X)) : Prop where /-- Each set has to be measurable. -/ measurable : ∀ s ∈ 𝒜, MeasurableSet s /-- Any measurable set can be approximated by sets in the family. -/ - approx : ∀ s, MeasurableSet s → μ s ≠ ∞ → ∀ (ε : ℝ), - 0 < ε → ∃ t ∈ 𝒜, μ (s ∆ t) < ENNReal.ofReal ε + approx : ∀ s, MeasurableSet s → μ s ≠ ∞ → ∀ ε : ℝ, 0 < ε → ∃ t ∈ 𝒜, μ (s ∆ t) < ENNReal.ofReal ε theorem Measure.MeasureDense.nonempty (h𝒜 : μ.MeasureDense 𝒜) : 𝒜.Nonempty := by rcases h𝒜.approx ∅ MeasurableSet.empty (by simp) 1 (by norm_num) with ⟨t, ht, -⟩ @@ -103,8 +102,8 @@ theorem Measure.MeasureDense.nonempty' (h𝒜 : μ.MeasureDense 𝒜) : /-- The set of measurable sets is measure-dense. -/ theorem measureDense_measurableSet : μ.MeasureDense {s | MeasurableSet s} where - measurable := fun _ h ↦ h - approx := fun s hs _ ε ε_pos ↦ ⟨s, hs, by simpa⟩ + measurable _ h := h + approx s hs _ ε ε_pos := ⟨s, hs, by simpa⟩ /-- If a family of sets `𝒜` is measure-dense in `X`, then any measurable set with finite measure can be approximated by sets in `𝒜` with finite measure. -/ @@ -155,9 +154,8 @@ theorem Measure.MeasureDense.indicatorConstLp_subset_closure (h𝒜 : μ.Measure with finite measure. -/ theorem Measure.MeasureDense.fin_meas (h𝒜 : μ.MeasureDense 𝒜) : μ.MeasureDense {s | s ∈ 𝒜 ∧ μ s ≠ ∞} where - measurable := fun s h ↦ h𝒜.measurable s h.1 - approx := by - intro s ms hμs ε ε_pos + measurable s h := h𝒜.measurable s h.1 + approx s ms hμs ε ε_pos := by rcases Measure.MeasureDense.fin_meas_approx h𝒜 ms hμs ε ε_pos with ⟨t, t_mem, hμt, hμst⟩ exact ⟨t, ⟨t_mem, hμt⟩, hμst⟩ @@ -165,12 +163,11 @@ theorem Measure.MeasureDense.fin_meas (h𝒜 : μ.MeasureDense 𝒜) : this algebra of sets is measure-dense. -/ theorem Measure.MeasureDense.of_generateFrom_isSetAlgebra_finite [IsFiniteMeasure μ] (h𝒜 : IsSetAlgebra 𝒜) (hgen : m = MeasurableSpace.generateFrom 𝒜) : μ.MeasureDense 𝒜 where - measurable := fun s hs ↦ hgen ▸ measurableSet_generateFrom hs - approx := by + measurable s hs := hgen ▸ measurableSet_generateFrom hs + approx s ms := by -- We want to show that any measurable set can be approximated by sets in `𝒜`. To do so, it is -- enough to show that such sets constitute a `σ`-algebra containing `𝒜`. This is contained in -- the theorem `generateFrom_induction`. - intro s ms have : MeasurableSet s ∧ ∀ (ε : ℝ), 0 < ε → ∃ t ∈ 𝒜, (μ (s ∆ t)).toReal < ε := by apply generateFrom_induction (p := fun s ↦ MeasurableSet s ∧ ∀ (ε : ℝ), 0 < ε → ∃ t ∈ 𝒜, (μ (s ∆ t)).toReal < ε) @@ -220,14 +217,14 @@ theorem Measure.MeasureDense.of_generateFrom_isSetAlgebra_finite [IsFiniteMeasur apply _root_.add_lt_add · rw [measure_diff (h_fin := measure_ne_top _ _), toReal_sub_of_le (ha := measure_ne_top _ _)] - apply lt_of_le_of_lt (sub_le_dist ..) - simp only [Finset.mem_range, Nat.lt_add_one_iff] - exact (dist_comm (α := ℝ) .. ▸ hN N (le_refl N)) - exact (measure_mono <| iUnion_subset <| - fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i)) - exact iUnion_subset <| fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i) - exact MeasurableSet.biUnion (countable_coe_iff.1 inferInstance) - (fun n _ ↦ (hf n).1.nullMeasurableSet) + · apply lt_of_le_of_lt (sub_le_dist ..) + simp only [Finset.mem_range, Nat.lt_add_one_iff] + exact (dist_comm (α := ℝ) .. ▸ hN N (le_refl N)) + · exact measure_mono <| iUnion_subset <| + fun i ↦ iUnion_subset fun _ ↦ subset_iUnion f i + · exact iUnion_subset <| fun i ↦ iUnion_subset (fun _ ↦ subset_iUnion f i) + · exact MeasurableSet.biUnion (countable_coe_iff.1 inferInstance) + (fun n _ ↦ (hf n).1.nullMeasurableSet) · calc (μ ((⋃ n ∈ (Finset.range (N + 1)), f n) ∆ (⋃ n ∈ (Finset.range (N + 1)), g ↑n))).toReal @@ -257,18 +254,17 @@ theorem Measure.MeasureDense.of_generateFrom_isSetAlgebra_sigmaFinite (h𝒜 : I (S : μ.FiniteSpanningSetsIn 𝒜) (hgen : m = MeasurableSpace.generateFrom 𝒜) : μ.MeasureDense 𝒜 where measurable s hs := hgen ▸ measurableSet_generateFrom hs - approx := by + approx s ms hμs ε ε_pos := by -- We use partial unions of (Sₙ) to get a monotone family spanning `X`. let T := Accumulate S.set - have T_mem : ∀ n, T n ∈ 𝒜 := fun n ↦ by + have T_mem (n) : T n ∈ 𝒜 := by simpa using h𝒜.biUnion_mem {k | k ≤ n}.toFinset (fun k _ ↦ S.set_mem k) - have T_finite : ∀ n, μ (T n) < ∞ := fun n ↦ by + have T_finite (n) : μ (T n) < ∞ := by simpa using measure_biUnion_lt_top {k | k ≤ n}.toFinset.finite_toSet (fun k _ ↦ S.finite k) have T_spanning : ⋃ n, T n = univ := S.spanning ▸ iUnion_accumulate -- We use the fact that we already know this is true for finite measures. As `⋃ n, T n = X`, -- we have that `μ ((T n) ∩ s) ⟶ μ s`. - intro s ms hμs ε ε_pos have mono : Monotone (fun n ↦ (T n) ∩ s) := fun m n hmn ↦ inter_subset_inter_left s (biUnion_subset_biUnion_left fun k hkm ↦ Nat.le_trans hkm hmn) have := tendsto_measure_iUnion_atTop (μ := μ) mono @@ -323,7 +319,7 @@ section IsSeparable The term "separable" is justified by the fact that the definition translates to the usual notion of separability in the metric space made by constant indicators equipped with the `Lᵖ` norm. -/ -class IsSeparable (μ : Measure X) : Prop := +class IsSeparable (μ : Measure X) : Prop where exists_countable_measureDense : ∃ 𝒜, 𝒜.Countable ∧ μ.MeasureDense 𝒜 /-- By definition, a separable measure admits a countable and measure-dense family of sets. -/ @@ -378,7 +374,6 @@ instance [CountablyGenerated X] [SFinite μ] : IsSeparable μ where ne_top_of_le_ne_top hμs <| μ.restrict_le_self _ rcases h𝒜.approx s ms this ε ε_pos with ⟨t, t_mem, ht⟩ refine ⟨t ∩ μ.sigmaFiniteSet, ⟨t, t_mem, rfl⟩, ?_⟩ - rw [← measure_inter_add_diff _ measurableSet_sigmaFiniteSet] have : μ (s ∆ (t ∩ μ.sigmaFiniteSet) \ μ.sigmaFiniteSet) = 0 := by rw [diff_eq_compl_inter, inter_symmDiff_distrib_left, ← ENNReal.bot_eq_zero, eq_bot_iff] calc @@ -388,10 +383,11 @@ instance [CountablyGenerated X] [SFinite μ] : IsSeparable μ where _ ≤ μ (μ.sigmaFiniteSetᶜ ∩ s) + μ (μ.sigmaFiniteSetᶜ ∩ (t ∩ μ.sigmaFiniteSet)) := measure_union_le _ _ _ = 0 := by - rw [inter_comm, ← μ.restrict_apply ms, hs, ← inter_assoc, inter_comm, ← inter_assoc, - inter_compl_self, empty_inter, measure_empty, zero_add] - rwa [this, add_zero, inter_symmDiff_distrib_right, inter_assoc, inter_self, - ← inter_symmDiff_distrib_right, ← μ.restrict_apply' measurableSet_sigmaFiniteSet] + rw [inter_comm, ← μ.restrict_apply ms, hs, ← inter_assoc, inter_comm, + ← inter_assoc, inter_compl_self, empty_inter, measure_empty, zero_add] + rwa [← measure_inter_add_diff _ measurableSet_sigmaFiniteSet, this, add_zero, + inter_symmDiff_distrib_right, inter_assoc, inter_self, ← inter_symmDiff_distrib_right, + ← μ.restrict_apply' measurableSet_sigmaFiniteSet] · refine False.elim <| hμs ?_ rw [eq_top_iff, ← hs] exact μ.restrict_le_self _ @@ -423,15 +419,14 @@ instance Lp.SecondCountableTopology [IsSeparable μ] [TopologicalSpace.Separable -- constant indicators with support in `𝒜₀`, and is denoted `D`. To make manipulations easier, -- we define the function `key` which given an integer `n` and two families of `n` elements -- in `u` and `𝒜₀` associates the corresponding sum. - let key : (n : ℕ) → (Fin n → u) → (Fin n → 𝒜₀) → (Lp E p μ) := - fun n d s ↦ ∑ i, indicatorConstLp p (h𝒜₀.measurable (s i) (Subtype.mem (s i))) - (s i).2.2 (d i : E) + let key (n : ℕ) (d : Fin n → u) (s : Fin n → 𝒜₀) : (Lp E p μ) := + ∑ i, indicatorConstLp p (h𝒜₀.measurable (s i) (Subtype.mem (s i))) (s i).2.2 (d i : E) let D := {s : Lp E p μ | ∃ n d t, s = key n d t} refine ⟨D, ?_, ?_⟩ · -- Countability directly follows from countability of `u` and `𝒜₀`. The function `f` below -- is the uncurryfied version of `key`, which is easier to manipulate as countability of the - -- domain is automatically infered. - let f : (Σ n : ℕ, (Fin n → u) × (Fin n → 𝒜₀)) → Lp E p μ := fun nds ↦ key nds.1 nds.2.1 nds.2.2 + -- domain is automatically inferred. + let f (nds : Σ n : ℕ, (Fin n → u) × (Fin n → 𝒜₀)) : Lp E p μ := key nds.1 nds.2.1 nds.2.2 have := count_𝒜₀.to_subtype have := countable_u.to_subtype have : D ⊆ range f := by diff --git a/Mathlib/MeasureTheory/Measure/Tilted.lean b/Mathlib/MeasureTheory/Measure/Tilted.lean index 0dcb5897a5937..78793a1d88732 100644 --- a/Mathlib/MeasureTheory/Measure/Tilted.lean +++ b/Mathlib/MeasureTheory/Measure/Tilted.lean @@ -235,7 +235,7 @@ alias set_integral_tilted := setIntegral_tilted lemma integral_tilted (f : α → ℝ) (g : α → E) : ∫ x, g x ∂(μ.tilted f) = ∫ x, (exp (f x) / ∫ x, exp (f x) ∂μ) • (g x) ∂μ := by - rw [← integral_univ, setIntegral_tilted' f g MeasurableSet.univ, integral_univ] + rw [← setIntegral_univ, setIntegral_tilted' f g MeasurableSet.univ, setIntegral_univ] end integral diff --git a/Mathlib/MeasureTheory/Measure/Typeclasses.lean b/Mathlib/MeasureTheory/Measure/Typeclasses.lean index 21a35d7e02dd3..9268fb8418824 100644 --- a/Mathlib/MeasureTheory/Measure/Typeclasses.lean +++ b/Mathlib/MeasureTheory/Measure/Typeclasses.lean @@ -558,15 +558,14 @@ instance isFiniteMeasure_sFiniteSeq [h : SFinite μ] (n : ℕ) : IsFiniteMeasure lemma sum_sFiniteSeq (μ : Measure α) [h : SFinite μ] : sum (sFiniteSeq μ) = μ := h.1.choose_spec.2.symm +lemma sFiniteSeq_le (μ : Measure α) [SFinite μ] (n : ℕ) : sFiniteSeq μ n ≤ μ := + (le_sum _ n).trans (sum_sFiniteSeq μ).le + instance : SFinite (0 : Measure α) := ⟨fun _ ↦ 0, inferInstance, by rw [Measure.sum_zero]⟩ @[simp] -lemma sFiniteSeq_zero (n : ℕ) : sFiniteSeq (0 : Measure α) n = 0 := by - ext s hs - have h : ∑' n, sFiniteSeq (0 : Measure α) n s = 0 := by - simp [← Measure.sum_apply _ hs, sum_sFiniteSeq] - simp only [ENNReal.tsum_eq_zero] at h - exact h n +lemma sFiniteSeq_zero (n : ℕ) : sFiniteSeq (0 : Measure α) n = 0 := + bot_unique <| sFiniteSeq_le _ _ /-- A countable sum of finite measures is s-finite. This lemma is superseded by the instance below. -/ diff --git a/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean b/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean index 955c03a3c1454..5b496cf711c4d 100644 --- a/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean +++ b/Mathlib/MeasureTheory/Measure/WithDensityFinite.lean @@ -9,16 +9,16 @@ import Mathlib.Probability.ConditionalProbability /-! # s-finite measures can be written as `withDensity` of a finite measure -If `μ` is an s-finite measure, then there exists a finite measure `μ.toFinite` and a measurable -function `densityToFinite μ` such that `μ = μ.toFinite.withDensity μ.densityToFinite`. If `μ` is -zero this is the zero measure, and otherwise we can choose a probability measure for `μ.toFinite`. +If `μ` is an s-finite measure, then there exists a finite measure `μ.toFinite` +such that a set is `μ`-null iff it is `μ.toFinite`-null. +In particular, `MeasureTheory.ae μ.toFinite = MeasureTheory.ae μ` and `μ.toFinite = 0` iff `μ = 0`. +As a corollary, `μ` can be represented as `μ.toFinite.withDensity (μ.rnDeriv μ.toFinite)`. -That measure is not unique, and in particular our implementation leads to `μ.toFinite ≠ μ` even if -`μ` is a probability measure. +Our definition of `MeasureTheory.Measure.toFinite` ensures some extra properties: -We use this construction to define a set `μ.sigmaFiniteSet`, such that `μ.restrict μ.sigmaFiniteSet` -is sigma-finite, and for all measurable sets `s ⊆ μ.sigmaFiniteSetᶜ`, either `μ s = 0` -or `μ s = ∞`. +- if `μ` is a finite measure, then `μ.toFinite = μ[|univ] = (μ univ)⁻¹ • μ`; +- in particular, `μ.toFinite = μ` for a probability measure; +- if `μ ≠ 0`, then `μ.toFinite` is a probability measure. ## Main definitions @@ -26,18 +26,19 @@ In these definitions and the results below, `μ` is an s-finite measure (`SFinit * `MeasureTheory.Measure.toFinite`: a finite measure with `μ ≪ μ.toFinite` and `μ.toFinite ≪ μ`. If `μ ≠ 0`, this is a probability measure. -* `MeasureTheory.Measure.densityToFinite`: a measurable function such that - `μ = μ.toFinite.withDensity μ.densityToFinite`. +* `MeasureTheory.Measure.densityToFinite` (deprecated, use `MeasureTheory.Measure.rnDeriv`): + the Radon-Nikodym derivative of `μ.toFinite` with respect to `μ`. ## Main statements * `absolutelyContinuous_toFinite`: `μ ≪ μ.toFinite`. * `toFinite_absolutelyContinuous`: `μ.toFinite ≪ μ`. -* `withDensity_densitytoFinite`: `μ.toFinite.withDensity μ.densityToFinite = μ`. +* `ae_toFinite`: `ae μ.toFinite = ae μ`. -/ -open scoped ENNReal +open Set +open scoped ENNReal ProbabilityTheory namespace MeasureTheory @@ -45,129 +46,98 @@ variable {α : Type*} {mα : MeasurableSpace α} {μ : Measure α} /-- Auxiliary definition for `MeasureTheory.Measure.toFinite`. -/ noncomputable def Measure.toFiniteAux (μ : Measure α) [SFinite μ] : Measure α := - Measure.sum (fun n ↦ (2 ^ (n + 1) * sFiniteSeq μ n Set.univ)⁻¹ • sFiniteSeq μ n) + letI := Classical.dec + if IsFiniteMeasure μ then μ else (exists_isFiniteMeasure_absolutelyContinuous μ).choose /-- A finite measure obtained from an s-finite measure `μ`, such that `μ = μ.toFinite.withDensity μ.densityToFinite` (see `withDensity_densitytoFinite`). If `μ` is non-zero, this is a probability measure. -/ noncomputable def Measure.toFinite (μ : Measure α) [SFinite μ] : Measure α := - ProbabilityTheory.cond μ.toFiniteAux Set.univ + μ.toFiniteAux[|univ] + +@[local simp] +lemma ae_toFiniteAux [SFinite μ] : ae μ.toFiniteAux = ae μ := by + rw [Measure.toFiniteAux] + split_ifs + · simp + · obtain ⟨_, h₁, h₂⟩ := (exists_isFiniteMeasure_absolutelyContinuous μ).choose_spec + exact h₂.ae_le.antisymm h₁.ae_le + +@[local instance] +theorem isFiniteMeasure_toFiniteAux [SFinite μ] : IsFiniteMeasure μ.toFiniteAux := by + rw [Measure.toFiniteAux] + split_ifs + · assumption + · exact (exists_isFiniteMeasure_absolutelyContinuous μ).choose_spec.1 -lemma toFiniteAux_apply (μ : Measure α) [SFinite μ] (s : Set α) : - μ.toFiniteAux s = ∑' n, (2 ^ (n + 1) * sFiniteSeq μ n Set.univ)⁻¹ * sFiniteSeq μ n s := by - rw [Measure.toFiniteAux, Measure.sum_apply_of_countable]; rfl - -lemma toFinite_apply (μ : Measure α) [SFinite μ] (s : Set α) : - μ.toFinite s = (μ.toFiniteAux Set.univ)⁻¹ * μ.toFiniteAux s := by - rw [Measure.toFinite, ProbabilityTheory.cond_apply _ MeasurableSet.univ, Set.univ_inter] - -lemma toFiniteAux_zero : Measure.toFiniteAux (0 : Measure α) = 0 := by - ext s - simp [toFiniteAux_apply] +@[simp] +lemma ae_toFinite [SFinite μ] : ae μ.toFinite = ae μ := by + simp [Measure.toFinite, ProbabilityTheory.cond] @[simp] -lemma toFinite_zero : Measure.toFinite (0 : Measure α) = 0 := by - simp [Measure.toFinite, toFiniteAux_zero] - -lemma toFiniteAux_eq_zero_iff [SFinite μ] : μ.toFiniteAux = 0 ↔ μ = 0 := by - refine ⟨fun h ↦ ?_, fun h ↦ by simp [h, toFiniteAux_zero]⟩ - ext s hs - rw [Measure.ext_iff] at h - specialize h s hs - simp only [toFiniteAux_apply, Measure.coe_zero, Pi.zero_apply, - ENNReal.tsum_eq_zero, mul_eq_zero, ENNReal.inv_eq_zero] at h - rw [← sum_sFiniteSeq μ, Measure.sum_apply _ hs] - simp only [Measure.coe_zero, Pi.zero_apply, ENNReal.tsum_eq_zero] - intro n - specialize h n - simpa [ENNReal.mul_eq_top, measure_ne_top] using h - -lemma toFiniteAux_univ_le_one (μ : Measure α) [SFinite μ] : μ.toFiniteAux Set.univ ≤ 1 := by - rw [toFiniteAux_apply] - have h_le_pow : ∀ n, (2 ^ (n + 1) * sFiniteSeq μ n Set.univ)⁻¹ * sFiniteSeq μ n Set.univ - ≤ (2 ^ (n + 1))⁻¹ := by - intro n - by_cases h_zero : sFiniteSeq μ n = 0 - · simp [h_zero] - · rw [ENNReal.le_inv_iff_mul_le, mul_assoc, mul_comm (sFiniteSeq μ n Set.univ), - ENNReal.inv_mul_cancel] - · simp [h_zero] - · exact ENNReal.mul_ne_top (by simp) (measure_ne_top _ _) - refine (tsum_le_tsum h_le_pow ENNReal.summable ENNReal.summable).trans ?_ - simp [ENNReal.inv_pow, ENNReal.tsum_geometric_add_one, ENNReal.inv_mul_cancel] - -instance [SFinite μ] : IsFiniteMeasure μ.toFiniteAux := - ⟨(toFiniteAux_univ_le_one μ).trans_lt ENNReal.one_lt_top⟩ +lemma toFinite_apply_eq_zero_iff [SFinite μ] {s : Set α} : μ.toFinite s = 0 ↔ μ s = 0 := by + simp only [← compl_mem_ae_iff, ae_toFinite] @[simp] lemma toFinite_eq_zero_iff [SFinite μ] : μ.toFinite = 0 ↔ μ = 0 := by - simp [Measure.toFinite, measure_ne_top μ.toFiniteAux Set.univ, toFiniteAux_eq_zero_iff] + simp_rw [← Measure.measure_univ_eq_zero, toFinite_apply_eq_zero_iff] + +@[simp] +lemma toFinite_zero : Measure.toFinite (0 : Measure α) = 0 := by simp + +lemma toFinite_eq_self [IsProbabilityMeasure μ] : μ.toFinite = μ := by + rw [Measure.toFinite, Measure.toFiniteAux, if_pos, ProbabilityTheory.cond_univ] + infer_instance instance [SFinite μ] : IsFiniteMeasure μ.toFinite := by rw [Measure.toFinite] infer_instance -instance [SFinite μ] [h_zero : NeZero μ] : IsProbabilityMeasure μ.toFinite := by - refine ProbabilityTheory.cond_isProbabilityMeasure μ.toFiniteAux ?_ - simp [toFiniteAux_eq_zero_iff, h_zero.out] +instance [SFinite μ] [NeZero μ] : IsProbabilityMeasure μ.toFinite := by + apply ProbabilityTheory.cond_isProbabilityMeasure + simp [ne_eq, ← compl_mem_ae_iff, ae_toFiniteAux] -lemma sFiniteSeq_absolutelyContinuous_toFiniteAux (μ : Measure α) [SFinite μ] (n : ℕ) : - sFiniteSeq μ n ≪ μ.toFiniteAux := by - refine Measure.absolutelyContinuous_sum_right n (Measure.absolutelyContinuous_smul ?_) - simp only [ne_eq, ENNReal.inv_eq_zero] - exact ENNReal.mul_ne_top (by simp) (measure_ne_top _ _) - -lemma toFiniteAux_absolutelyContinuous_toFinite (μ : Measure α) [SFinite μ] : - μ.toFiniteAux ≪ μ.toFinite := ProbabilityTheory.absolutelyContinuous_cond_univ +lemma absolutelyContinuous_toFinite (μ : Measure α) [SFinite μ] : μ ≪ μ.toFinite := + Measure.ae_le_iff_absolutelyContinuous.mp ae_toFinite.ge lemma sFiniteSeq_absolutelyContinuous_toFinite (μ : Measure α) [SFinite μ] (n : ℕ) : sFiniteSeq μ n ≪ μ.toFinite := - (sFiniteSeq_absolutelyContinuous_toFiniteAux μ n).trans - (toFiniteAux_absolutelyContinuous_toFinite μ) - -lemma absolutelyContinuous_toFinite (μ : Measure α) [SFinite μ] : μ ≪ μ.toFinite := by - conv_lhs => rw [← sum_sFiniteSeq μ] - exact Measure.absolutelyContinuous_sum_left (sFiniteSeq_absolutelyContinuous_toFinite μ) + (sFiniteSeq_le μ n).absolutelyContinuous.trans (absolutelyContinuous_toFinite μ) -lemma toFinite_absolutelyContinuous (μ : Measure α) [SFinite μ] : μ.toFinite ≪ μ := by - conv_rhs => rw [← sum_sFiniteSeq μ] - refine Measure.AbsolutelyContinuous.mk (fun s hs hs0 ↦ ?_) - simp only [Measure.sum_apply _ hs, ENNReal.tsum_eq_zero] at hs0 - simp [toFinite_apply, toFiniteAux_apply, hs0] +lemma toFinite_absolutelyContinuous (μ : Measure α) [SFinite μ] : μ.toFinite ≪ μ := + Measure.ae_le_iff_absolutelyContinuous.mp ae_toFinite.le /-- A measurable function such that `μ.toFinite.withDensity μ.densityToFinite = μ`. See `withDensity_densitytoFinite`. -/ -noncomputable -def Measure.densityToFinite (μ : Measure α) [SFinite μ] (a : α) : ℝ≥0∞ := - ∑' n, (sFiniteSeq μ n).rnDeriv μ.toFinite a +@[deprecated rnDeriv (since := "2024-10-04")] +noncomputable def Measure.densityToFinite (μ : Measure α) [SFinite μ] (a : α) : ℝ≥0∞ := + μ.rnDeriv μ.toFinite a +set_option linter.deprecated false in +@[deprecated (since := "2024-10-04")] lemma densityToFinite_def (μ : Measure α) [SFinite μ] : - μ.densityToFinite = fun a ↦ ∑' n, (sFiniteSeq μ n).rnDeriv μ.toFinite a := rfl + μ.densityToFinite = μ.rnDeriv μ.toFinite := + rfl +set_option linter.deprecated false in +@[deprecated Measure.measurable_rnDeriv (since := "2024-10-04")] lemma measurable_densityToFinite (μ : Measure α) [SFinite μ] : Measurable μ.densityToFinite := - Measurable.ennreal_tsum fun _ ↦ Measure.measurable_rnDeriv _ _ + Measure.measurable_rnDeriv _ _ +set_option linter.deprecated false in +@[deprecated Measure.withDensity_rnDeriv_eq (since := "2024-10-04")] theorem withDensity_densitytoFinite (μ : Measure α) [SFinite μ] : - μ.toFinite.withDensity μ.densityToFinite = μ := by - have : (μ.toFinite.withDensity fun a ↦ ∑' n, (sFiniteSeq μ n).rnDeriv μ.toFinite a) - = μ.toFinite.withDensity (∑' n, (sFiniteSeq μ n).rnDeriv μ.toFinite) := by - congr with a - rw [ENNReal.tsum_apply] - rw [densityToFinite_def, this, withDensity_tsum (fun i ↦ Measure.measurable_rnDeriv _ _)] - conv_rhs => rw [← sum_sFiniteSeq μ] - congr with n - rw [Measure.withDensity_rnDeriv_eq] - exact sFiniteSeq_absolutelyContinuous_toFinite μ n + μ.toFinite.withDensity μ.densityToFinite = μ := + Measure.withDensity_rnDeriv_eq _ _ (absolutelyContinuous_toFinite _) +set_option linter.deprecated false in +@[deprecated Measure.rnDeriv_lt_top (since := "2024-10-04")] lemma densityToFinite_ae_lt_top (μ : Measure α) [SigmaFinite μ] : - ∀ᵐ x ∂μ, μ.densityToFinite x < ∞ := by - refine ae_of_forall_measure_lt_top_ae_restrict _ (fun s _ hμs ↦ ?_) - suffices ∀ᵐ x ∂μ.toFinite.restrict s, μ.densityToFinite x < ∞ from - (absolutelyContinuous_toFinite μ).restrict _ this - refine ae_lt_top (measurable_densityToFinite μ) ?_ - rw [← withDensity_apply', withDensity_densitytoFinite] - exact hμs.ne + ∀ᵐ x ∂μ, μ.densityToFinite x < ∞ := + (absolutelyContinuous_toFinite μ).ae_le <| Measure.rnDeriv_lt_top _ _ +set_option linter.deprecated false in +@[deprecated Measure.rnDeriv_ne_top (since := "2024-10-04")] lemma densityToFinite_ae_ne_top (μ : Measure α) [SigmaFinite μ] : ∀ᵐ x ∂μ, μ.densityToFinite x ≠ ∞ := (densityToFinite_ae_lt_top μ).mono (fun _ hx ↦ hx.ne) diff --git a/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean b/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean index a6c90472f6f46..7e859de1147fc 100644 --- a/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean +++ b/Mathlib/MeasureTheory/OuterMeasure/OfFunction.lean @@ -232,7 +232,7 @@ theorem smul_ofFunction {c : ℝ≥0∞} (hc : c ≠ ∞) : c • OuterMeasure.o haveI : Nonempty { t : ℕ → Set α // s ⊆ ⋃ i, t i } := ⟨⟨fun _ => s, subset_iUnion (fun _ => s) 0⟩⟩ simp only [smul_apply, ofFunction_apply, ENNReal.tsum_mul_left, Pi.smul_apply, smul_eq_mul, iInf_subtype'] - rw [ENNReal.iInf_mul_left fun h => (hc h).elim] + rw [ENNReal.mul_iInf fun h => (hc h).elim] end OfFunction diff --git a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean index 2a839ffd63d95..c2c75e666e4b2 100644 --- a/Mathlib/ModelTheory/Algebra/Ring/Basic.lean +++ b/Mathlib/ModelTheory/Algebra/Ring/Basic.lean @@ -140,7 +140,7 @@ theorem card_ring : card Language.ring = 5 := by have : Fintype.card Language.ring.Symbols = 5 := rfl simp [Language.card, this] -open Language ring Structure +open Language Structure /-- A Type `R` is a `CompatibleRing` if it is a structure for the language of rings and this structure is the same as the structure already given on `R` by the classes `Add`, `Mul` etc. diff --git a/Mathlib/ModelTheory/Basic.lean b/Mathlib/ModelTheory/Basic.lean index e19707451b558..baa0ada8d4271 100644 --- a/Mathlib/ModelTheory/Basic.lean +++ b/Mathlib/ModelTheory/Basic.lean @@ -247,14 +247,14 @@ theorem nonempty_of_nonempty_constants [h : Nonempty L.Constants] : Nonempty M : /-- `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 M N : Type*) +class HomClass (L : outParam Language) (F : Type*) (M N : outParam Type*) [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) /-- `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 M N : Type*) +class StrongHomClass (L : outParam Language) (F : Type*) (M N : outParam Type*) [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 diff --git a/Mathlib/ModelTheory/Complexity.lean b/Mathlib/ModelTheory/Complexity.lean index f6af8bfbb9ccb..e4d9bfc7ef31f 100644 --- a/Mathlib/ModelTheory/Complexity.lean +++ b/Mathlib/ModelTheory/Complexity.lean @@ -291,7 +291,7 @@ theorem IsQF.induction_on_sup_not {P : L.BoundedFormula α n → Prop} {φ : L.B ∀ {φ₁ φ₂ : L.BoundedFormula α n}, (φ₁ ⇔[∅] φ₂) → (P φ₁ ↔ P φ₂)) : P φ := IsQF.recOn h hf @(ha) fun {φ₁ φ₂} _ _ h1 h2 => - (hse (φ₁.imp_semanticallyEquivalent_not_sup φ₂)).2 (hsup (hnot h1) h2) + (hse (φ₁.imp_iff_not_sup φ₂)).2 (hsup (hnot h1) h2) theorem IsQF.induction_on_inf_not {P : L.BoundedFormula α n → Prop} {φ : L.BoundedFormula α n} (h : IsQF φ) (hf : P (⊥ : L.BoundedFormula α n)) @@ -302,10 +302,10 @@ theorem IsQF.induction_on_inf_not {P : L.BoundedFormula α n → Prop} {φ : L.B P φ := h.induction_on_sup_not hf ha (fun {φ₁ φ₂} h1 h2 => - (hse (φ₁.sup_semanticallyEquivalent_not_inf_not φ₂)).2 (hnot (hinf (hnot h1) (hnot h2)))) + (hse (φ₁.sup_iff_not_inf_not φ₂)).2 (hnot (hinf (hnot h1) (hnot h2)))) (fun {_} => hnot) fun {_ _} => hse -theorem semanticallyEquivalent_toPrenex (φ : L.BoundedFormula α n) : +theorem iff_toPrenex (φ : L.BoundedFormula α n) : φ ⇔[∅] φ.toPrenex := fun M v xs => by rw [realize_iff, realize_toPrenex] @@ -317,7 +317,7 @@ theorem induction_on_all_ex {P : ∀ {m}, L.BoundedFormula α m → Prop} (φ : (φ₁ ⇔[∅] φ₂) → (P φ₁ ↔ P φ₂)) : P φ := by suffices h' : ∀ {m} {φ : L.BoundedFormula α m}, φ.IsPrenex → P φ from - (hse φ.semanticallyEquivalent_toPrenex).2 (h' φ.toPrenex_isPrenex) + (hse φ.iff_toPrenex).2 (h' φ.toPrenex_isPrenex) intro m φ hφ induction hφ with | of_isQF hφ => exact hqf hφ @@ -332,7 +332,7 @@ theorem induction_on_exists_not {P : ∀ {m}, L.BoundedFormula α m → Prop} ( (φ₁ ⇔[∅] φ₂) → (P φ₁ ↔ P φ₂)) : P φ := φ.induction_on_all_ex (fun {_ _} => hqf) - (fun {_ φ} hφ => (hse φ.all_semanticallyEquivalent_not_ex_not).2 (hnot (hex (hnot hφ)))) + (fun {_ φ} hφ => (hse φ.all_iff_not_ex_not).2 (hnot (hex (hnot hφ)))) (fun {_ _} => hex) fun {_ _ _} => hse /-- A universal formula is a formula defined by applying only universal quantifiers to a diff --git a/Mathlib/ModelTheory/Encoding.lean b/Mathlib/ModelTheory/Encoding.lean index fab8363491989..b8219e55752e1 100644 --- a/Mathlib/ModelTheory/Encoding.lean +++ b/Mathlib/ModelTheory/Encoding.lean @@ -6,7 +6,7 @@ Authors: Aaron Anderson import Mathlib.Computability.Encoding import Mathlib.Logic.Small.List import Mathlib.ModelTheory.Syntax -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic /-! # Encodings and Cardinality of First-Order Syntax @@ -83,7 +83,7 @@ theorem listDecode_encode_list (l : List (L.Term α)) : simp only [h, length_append, length_map, length_finRange, le_add_iff_nonneg_right, _root_.zero_le, ↓reduceDIte, getElem_fin, cons.injEq, func.injEq, heq_eq_eq, true_and] refine ⟨funext (fun i => ?_), ?_⟩ - · rw [List.getElem_append, List.getElem_map, List.getElem_finRange] + · rw [List.getElem_append_left, List.getElem_map, List.getElem_finRange] simp only [length_map, length_finRange, i.2] · simp only [length_map, length_finRange, drop_left'] @@ -244,7 +244,7 @@ theorem listDecode_encode_list (l : List (Σn, L.BoundedFormula α n)) : simp only [Option.join, map_append, map_map, Option.bind_eq_some, id, exists_eq_right, get?_eq_some, length_append, length_map, length_finRange] refine ⟨lt_of_lt_of_le i.2 le_self_add, ?_⟩ - rw [get_eq_getElem, getElem_append, getElem_map] + rw [get_eq_getElem, getElem_append_left, getElem_map] · simp only [getElem_finRange, Fin.eta, Function.comp_apply, Sum.getLeft?] · simp only [length_map, length_finRange, is_lt] rw [dif_pos] diff --git a/Mathlib/ModelTheory/Equivalence.lean b/Mathlib/ModelTheory/Equivalence.lean index e824467c1e629..42f8aff5f8d70 100644 --- a/Mathlib/ModelTheory/Equivalence.lean +++ b/Mathlib/ModelTheory/Equivalence.lean @@ -9,13 +9,12 @@ import Mathlib.ModelTheory.Satisfiability # Equivalence of Formulas ## Main Definitions -- `FirstOrder.Language.Theory.SemanticallyEquivalent`: `φ ⇔[T] ψ` indicates that `φ` and `ψ` are - equivalent formulas or sentences in models of `T`. +- `FirstOrder.Language.Theory.Imp`: `φ ⟹[T] ψ` indicates that `φ` implies `ψ` in models of `T`. +- `FirstOrder.Language.Theory.Iff`: `φ ⇔[T] ψ` indicates that `φ` and `ψ` are equivalent formulas or + sentences in models of `T`. ## TODO -- Add a definition of implication modulo a theory `T`, with `φ ⇒[T] ψ` defined analogously to - `φ ⇔[T] ψ`. -- Construct the quotient of `L.Formula α` modulo `⇔[T]` and its Boolean Algebra structure. +- Define the quotient of `L.Formula α` modulo `⇔[T]` and its Boolean Algebra structure. -/ @@ -34,24 +33,107 @@ variable {M : Type*} [Nonempty M] [L.Structure M] [M ⊨ T] namespace Theory +/-- `φ ⟹[T] ψ` indicates that `φ` implies `ψ` in models of `T`. -/ +protected def Imp (T : L.Theory) (φ ψ : L.BoundedFormula α n) : Prop := + T ⊨ᵇ φ.imp ψ + +@[inherit_doc FirstOrder.Language.Theory.Imp] +scoped[FirstOrder] notation:51 φ:50 " ⟹[" T "] " ψ:51 => Language.Theory.Imp T φ ψ + +namespace Imp + +@[refl] +protected theorem refl (φ : L.BoundedFormula α n) : φ ⟹[T] φ := fun _ _ _ => id + +instance : IsRefl (L.BoundedFormula α n) T.Imp := ⟨Imp.refl⟩ + +@[trans] +protected theorem trans {φ ψ θ : L.BoundedFormula α n} (h1 : φ ⟹[T] ψ) (h2 : ψ ⟹[T] θ) : + φ ⟹[T] θ := fun M v xs => (h2 M v xs) ∘ (h1 M v xs) + +instance : IsTrans (L.BoundedFormula α n) T.Imp := ⟨fun _ _ _ => Imp.trans⟩ + +end Imp + +section Imp + +lemma bot_imp (φ : L.BoundedFormula α n) : ⊥ ⟹[T] φ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_bot, false_implies] + +lemma imp_top (φ : L.BoundedFormula α n) : φ ⟹[T] ⊤ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_top, implies_true] + +lemma imp_sup_left (φ ψ : L.BoundedFormula α n) : φ ⟹[T] φ ⊔ ψ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_sup] + exact Or.inl + +lemma imp_sup_right (φ ψ : L.BoundedFormula α n) : ψ ⟹[T] φ ⊔ ψ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_sup] + exact Or.inr + +lemma sup_imp {φ ψ θ : L.BoundedFormula α n} (h₁ : φ ⟹[T] θ) (h₂ : ψ ⟹[T] θ) : + φ ⊔ ψ ⟹[T] θ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_sup] + exact fun h => h.elim (h₁ M v xs) (h₂ M v xs) + +lemma sup_imp_iff {φ ψ θ : L.BoundedFormula α n} : + (φ ⊔ ψ ⟹[T] θ) ↔ (φ ⟹[T] θ) ∧ (ψ ⟹[T] θ) := + ⟨fun h => ⟨(imp_sup_left _ _).trans h, (imp_sup_right _ _).trans h⟩, + fun ⟨h₁, h₂⟩ => sup_imp h₁ h₂⟩ + +lemma inf_imp_left (φ ψ : L.BoundedFormula α n) : φ ⊓ ψ ⟹[T] φ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_inf] + exact And.left + +lemma inf_imp_right (φ ψ : L.BoundedFormula α n) : φ ⊓ ψ ⟹[T] ψ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_inf] + exact And.right + +lemma imp_inf {φ ψ θ : L.BoundedFormula α n} (h₁ : φ ⟹[T] ψ) (h₂ : φ ⟹[T] θ) : + φ ⟹[T] ψ ⊓ θ := fun M v xs => by + simp only [BoundedFormula.realize_imp, BoundedFormula.realize_inf] + exact fun h => ⟨h₁ M v xs h, h₂ M v xs h⟩ + +lemma imp_inf_iff {φ ψ θ : L.BoundedFormula α n} : + (φ ⟹[T] ψ ⊓ θ) ↔ (φ ⟹[T] ψ) ∧ (φ ⟹[T] θ) := + ⟨fun h => ⟨h.trans (inf_imp_left _ _), h.trans (inf_imp_right _ _)⟩, + fun ⟨h₁, h₂⟩ => imp_inf h₁ h₂⟩ + +end Imp + /-- Two (bounded) formulas are semantically equivalent over a theory `T` when they have the same interpretation in every model of `T`. (This is also known as logical equivalence, which also has a proof-theoretic definition.) -/ -def SemanticallyEquivalent (T : L.Theory) (φ ψ : L.BoundedFormula α n) : Prop := +protected def Iff (T : L.Theory) (φ ψ : L.BoundedFormula α n) : Prop := T ⊨ᵇ φ.iff ψ -@[inherit_doc FirstOrder.Language.Theory.SemanticallyEquivalent] -scoped[FirstOrder] notation:25 φ " ⇔[" T "] " ψ => Language.Theory.SemanticallyEquivalent T φ ψ +@[inherit_doc FirstOrder.Language.Theory.Iff] +scoped[FirstOrder] +notation:51 φ:50 " ⇔[" T "] " ψ:51 => Language.Theory.Iff T φ ψ +theorem iff_iff_imp_and_imp {φ ψ : L.BoundedFormula α n} : + (φ ⇔[T] ψ) ↔ (φ ⟹[T] ψ) ∧ (ψ ⟹[T] φ) := by + simp only [Theory.Imp, ModelsBoundedFormula, BoundedFormula.realize_imp, ← forall_and, + Theory.Iff, BoundedFormula.realize_iff, iff_iff_implies_and_implies] -namespace SemanticallyEquivalent +theorem imp_antisymm {φ ψ : L.BoundedFormula α n} (h₁ : φ ⟹[T] ψ) (h₂ : ψ ⟹[T] φ) : + φ ⇔[T] ψ := + iff_iff_imp_and_imp.2 ⟨h₁, h₂⟩ + +namespace Iff + +protected theorem mp {φ ψ : L.BoundedFormula α n} (h : φ ⇔[T] ψ) : + φ ⟹[T] ψ := (iff_iff_imp_and_imp.1 h).1 + +protected theorem mpr {φ ψ : L.BoundedFormula α n} (h : φ ⇔[T] ψ) : + ψ ⟹[T] φ := (iff_iff_imp_and_imp.1 h).2 @[refl] protected theorem refl (φ : L.BoundedFormula α n) : φ ⇔[T] φ := fun M v xs => by rw [BoundedFormula.realize_iff] -instance : IsRefl (L.BoundedFormula α n) T.SemanticallyEquivalent := - ⟨SemanticallyEquivalent.refl⟩ +instance : IsRefl (L.BoundedFormula α n) T.Iff := + ⟨Iff.refl⟩ @[symm] protected theorem symm {φ ψ : L.BoundedFormula α n} @@ -59,6 +141,9 @@ protected theorem symm {φ ψ : L.BoundedFormula α n} rw [BoundedFormula.realize_iff, Iff.comm, ← BoundedFormula.realize_iff] exact h M v xs +instance : IsSymm (L.BoundedFormula α n) T.Iff := + ⟨fun _ _ => Iff.symm⟩ + @[trans] protected theorem trans {φ ψ θ : L.BoundedFormula α n} (h1 : φ ⇔[T] ψ) (h2 : ψ ⇔[T] θ) : @@ -68,6 +153,9 @@ protected theorem trans {φ ψ θ : L.BoundedFormula α n} rw [BoundedFormula.realize_iff] at * exact ⟨h2'.1 ∘ h1'.1, h1'.2 ∘ h2'.2⟩ +instance : IsTrans (L.BoundedFormula α n) T.Iff := + ⟨fun _ _ _ => Iff.trans⟩ + theorem realize_bd_iff {φ ψ : L.BoundedFormula α n} (h : φ ⇔[T] ψ) {v : α → M} {xs : Fin n → M} : φ.Realize v xs ↔ ψ.Realize v xs := BoundedFormula.realize_iff.1 (h.realize_boundedFormula M) @@ -84,33 +172,33 @@ theorem models_sentence_iff {φ ψ : L.Sentence} {M : Type*} [Nonempty M] protected theorem all {φ ψ : L.BoundedFormula α (n + 1)} (h : φ ⇔[T] ψ) : φ.all ⇔[T] ψ.all := by - simp_rw [SemanticallyEquivalent, ModelsBoundedFormula, BoundedFormula.realize_iff, + simp_rw [Theory.Iff, ModelsBoundedFormula, BoundedFormula.realize_iff, BoundedFormula.realize_all] exact fun M v xs => forall_congr' fun a => h.realize_bd_iff protected theorem ex {φ ψ : L.BoundedFormula α (n + 1)} (h : φ ⇔[T] ψ) : φ.ex ⇔[T] ψ.ex := by - simp_rw [SemanticallyEquivalent, ModelsBoundedFormula, BoundedFormula.realize_iff, + simp_rw [Theory.Iff, ModelsBoundedFormula, BoundedFormula.realize_iff, BoundedFormula.realize_ex] exact fun M v xs => exists_congr fun a => h.realize_bd_iff protected theorem not {φ ψ : L.BoundedFormula α n} (h : φ ⇔[T] ψ) : φ.not ⇔[T] ψ.not := by - simp_rw [SemanticallyEquivalent, ModelsBoundedFormula, BoundedFormula.realize_iff, + simp_rw [Theory.Iff, ModelsBoundedFormula, BoundedFormula.realize_iff, BoundedFormula.realize_not] exact fun M v xs => not_congr h.realize_bd_iff protected theorem imp {φ ψ φ' ψ' : L.BoundedFormula α n} (h : φ ⇔[T] ψ) (h' : φ' ⇔[T] ψ') : (φ.imp φ') ⇔[T] (ψ.imp ψ') := by - simp_rw [SemanticallyEquivalent, ModelsBoundedFormula, BoundedFormula.realize_iff, + simp_rw [Theory.Iff, ModelsBoundedFormula, BoundedFormula.realize_iff, BoundedFormula.realize_imp] exact fun M v xs => imp_congr h.realize_bd_iff h'.realize_bd_iff -end SemanticallyEquivalent +end Iff /-- Semantic equivalence forms an equivalence relation on formulas. -/ -def semanticallyEquivalentSetoid (T : L.Theory) : Setoid (L.BoundedFormula α n) where - r := SemanticallyEquivalent T +def iffSetoid (T : L.Theory) : Setoid (L.BoundedFormula α n) where + r := T.Iff iseqv := ⟨fun _ => refl _, fun {_ _} h => h.symm, fun {_ _ _} h1 h2 => h1.trans h2⟩ end Theory @@ -119,45 +207,53 @@ namespace BoundedFormula variable (φ ψ : L.BoundedFormula α n) -theorem semanticallyEquivalent_not_not : φ ⇔[T] φ.not.not := fun M v xs => by +theorem iff_not_not : φ ⇔[T] φ.not.not := fun M v xs => by simp -theorem imp_semanticallyEquivalent_not_sup : (φ.imp ψ) ⇔[T] (φ.not ⊔ ψ) := +theorem imp_iff_not_sup : (φ.imp ψ) ⇔[T] (φ.not ⊔ ψ) := fun M v xs => by simp [imp_iff_not_or] -theorem sup_semanticallyEquivalent_not_inf_not : (φ ⊔ ψ) ⇔[T] (φ.not ⊓ ψ.not).not := +theorem sup_iff_not_inf_not : (φ ⊔ ψ) ⇔[T] (φ.not ⊓ ψ.not).not := fun M v xs => by simp [imp_iff_not_or] -theorem inf_semanticallyEquivalent_not_sup_not : (φ ⊓ ψ) ⇔[T] (φ.not ⊔ ψ.not).not := +theorem inf_iff_not_sup_not : (φ ⊓ ψ) ⇔[T] (φ.not ⊔ ψ.not).not := fun M v xs => by simp -theorem all_semanticallyEquivalent_not_ex_not (φ : L.BoundedFormula α (n + 1)) : +theorem all_iff_not_ex_not (φ : L.BoundedFormula α (n + 1)) : φ.all ⇔[T] φ.not.ex.not := fun M v xs => by simp -theorem ex_semanticallyEquivalent_not_all_not (φ : L.BoundedFormula α (n + 1)) : +theorem ex_iff_not_all_not (φ : L.BoundedFormula α (n + 1)) : φ.ex ⇔[T] φ.not.all.not := fun M v xs => by simp -theorem semanticallyEquivalent_all_liftAt : φ ⇔[T] (φ.liftAt 1 n).all := +theorem iff_all_liftAt : φ ⇔[T] (φ.liftAt 1 n).all := fun M v xs => by rw [realize_iff, realize_all_liftAt_one_self] +lemma inf_not_iff_bot : + φ ⊓ ∼φ ⇔[T] ⊥ := fun M v xs => by + simp only [realize_iff, realize_inf, realize_not, and_not_self, realize_bot] + +lemma sup_not_iff_top : + φ ⊔ ∼φ ⇔[T] ⊤ := fun M v xs => by + simp only [realize_iff, realize_sup, realize_not, realize_top, iff_true, or_not] + end BoundedFormula namespace Formula variable (φ ψ : L.Formula α) -theorem semanticallyEquivalent_not_not : φ ⇔[T] φ.not.not := - BoundedFormula.semanticallyEquivalent_not_not φ +theorem iff_not_not : φ ⇔[T] φ.not.not := + BoundedFormula.iff_not_not φ -theorem imp_semanticallyEquivalent_not_sup : (φ.imp ψ) ⇔[T] (φ.not ⊔ ψ) := - BoundedFormula.imp_semanticallyEquivalent_not_sup φ ψ +theorem imp_iff_not_sup : (φ.imp ψ) ⇔[T] (φ.not ⊔ ψ) := + BoundedFormula.imp_iff_not_sup φ ψ -theorem sup_semanticallyEquivalent_not_inf_not : (φ ⊔ ψ) ⇔[T] (φ.not ⊓ ψ.not).not := - BoundedFormula.sup_semanticallyEquivalent_not_inf_not φ ψ +theorem sup_iff_not_inf_not : (φ ⊔ ψ) ⇔[T] (φ.not ⊓ ψ.not).not := + BoundedFormula.sup_iff_not_inf_not φ ψ -theorem inf_semanticallyEquivalent_not_sup_not : (φ ⊓ ψ) ⇔[T] (φ.not ⊔ ψ.not).not := - BoundedFormula.inf_semanticallyEquivalent_not_sup_not φ ψ +theorem inf_iff_not_sup_not : (φ ⊓ ψ) ⇔[T] (φ.not ⊔ ψ.not).not := + BoundedFormula.inf_iff_not_sup_not φ ψ end Formula diff --git a/Mathlib/ModelTheory/Order.lean b/Mathlib/ModelTheory/Order.lean index ac41879019da5..af11c905aa569 100644 --- a/Mathlib/ModelTheory/Order.lean +++ b/Mathlib/ModelTheory/Order.lean @@ -358,10 +358,14 @@ instance : @OrderedStructure L M _ (L.leOfStructure M) _ := by intros rfl -instance [h : DecidableRel (fun (a b : M) => Structure.RelMap (leSymb : L.Relations 2) ![a,b])] : - DecidableRel (@LE.le M (L.leOfStructure M)) := by - letI := L.leOfStructure M - exact h +/-- The order structure on an ordered language is decidable. -/ +-- This should not be a global instance, +-- because it will match with any `LE` typeclass search +@[local instance] +def decidableLEOfStructure + [h : DecidableRel (fun (a b : M) => Structure.RelMap (leSymb : L.Relations 2) ![a,b])] : + letI := L.leOfStructure M + DecidableRel ((· : M) ≤ ·) := h /-- Any model of a theory of preorders is a preorder. -/ def preorderOfModels [h : M ⊨ L.preorderTheory] : Preorder M where diff --git a/Mathlib/ModelTheory/Syntax.lean b/Mathlib/ModelTheory/Syntax.lean index fb5f3691aab1a..7fa52ce76edb5 100644 --- a/Mathlib/ModelTheory/Syntax.lean +++ b/Mathlib/ModelTheory/Syntax.lean @@ -576,8 +576,8 @@ theorem relabel_sum_inl (φ : L.BoundedFormula α n) : | falsum => rfl | equal => simp [Fin.natAdd_zero, castLE_of_eq, mapTermRel] | rel => simp [Fin.natAdd_zero, castLE_of_eq, mapTermRel]; rfl - | imp _ _ ih1 ih2 => simp [mapTermRel, ih1, ih2] - | all _ ih3 => simp [mapTermRel, ih3, castLE] + | imp _ _ ih1 ih2 => simp_all [mapTermRel] + | all _ ih3 => simp_all [mapTermRel] /-- Substitutes the variables in a given formula with terms. -/ def subst {n : ℕ} (φ : L.BoundedFormula α n) (f : α → L.Term β) : L.BoundedFormula β n := diff --git a/Mathlib/ModelTheory/Ultraproducts.lean b/Mathlib/ModelTheory/Ultraproducts.lean index c7c3922d198a4..63dbaa42f715d 100644 --- a/Mathlib/ModelTheory/Ultraproducts.lean +++ b/Mathlib/ModelTheory/Ultraproducts.lean @@ -153,7 +153,7 @@ it is true in is in the ultrafilter. -/ theorem sentence_realize (φ : L.Sentence) : (u : Filter α).Product M ⊨ φ ↔ ∀ᶠ a : α in u, M a ⊨ φ := by simp_rw [Sentence.Realize] - erw [← realize_formula_cast φ, iff_eq_eq] + rw [← realize_formula_cast φ, iff_eq_eq] exact congr rfl (Subsingleton.elim _ _) nonrec instance Product.instNonempty : Nonempty ((u : Filter α).Product M) := diff --git a/Mathlib/NumberTheory/ADEInequality.lean b/Mathlib/NumberTheory/ADEInequality.lean index 4c41bee0d6a33..f6cf4a0e5c35e 100644 --- a/Mathlib/NumberTheory/ADEInequality.lean +++ b/Mathlib/NumberTheory/ADEInequality.lean @@ -3,7 +3,6 @@ Copyright (c) 2021 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Johan Commelin -/ -import Mathlib.Algebra.Order.Field.Basic import Mathlib.Algebra.Order.Ring.Rat import Mathlib.Data.Multiset.Sort import Mathlib.Data.PNat.Basic @@ -148,7 +147,7 @@ theorem Admissible.one_lt_sumInv {pqr : Multiset ℕ+} : Admissible pqr → 1 < all_goals rw [← H, E', sumInv_pqr] conv_rhs => simp only [OfNat.ofNat, PNat.mk_coe] - rfl + norm_num theorem lt_three {p q r : ℕ+} (hpq : p ≤ q) (hqr : q ≤ r) (H : 1 < sumInv {p, q, r}) : p < 3 := by have h3 : (0 : ℚ) < 3 := by norm_num @@ -157,15 +156,15 @@ theorem lt_three {p q r : ℕ+} (hpq : p ≤ q) (hqr : q ≤ r) (H : 1 < sumInv have h3q := H.trans hpq have h3r := h3q.trans hqr have hp : (p : ℚ)⁻¹ ≤ 3⁻¹ := by - rw [inv_le_inv _ h3] + rw [inv_le_inv₀ _ h3] · assumption_mod_cast · norm_num have hq : (q : ℚ)⁻¹ ≤ 3⁻¹ := by - rw [inv_le_inv _ h3] + rw [inv_le_inv₀ _ h3] · assumption_mod_cast · norm_num have hr : (r : ℚ)⁻¹ ≤ 3⁻¹ := by - rw [inv_le_inv _ h3] + rw [inv_le_inv₀ _ h3] · assumption_mod_cast · norm_num calc @@ -178,11 +177,11 @@ theorem lt_four {q r : ℕ+} (hqr : q ≤ r) (H : 1 < sumInv {2, q, r}) : q < 4 rw [sumInv_pqr] have h4r := H.trans hqr have hq : (q : ℚ)⁻¹ ≤ 4⁻¹ := by - rw [inv_le_inv _ h4] + rw [inv_le_inv₀ _ h4] · assumption_mod_cast · norm_num have hr : (r : ℚ)⁻¹ ≤ 4⁻¹ := by - rw [inv_le_inv _ h4] + rw [inv_le_inv₀ _ h4] · assumption_mod_cast · norm_num calc @@ -194,7 +193,7 @@ theorem lt_six {r : ℕ+} (H : 1 < sumInv {2, 3, r}) : r < 6 := by contrapose! H rw [sumInv_pqr] have hr : (r : ℚ)⁻¹ ≤ 6⁻¹ := by - rw [inv_le_inv _ h6] + rw [inv_le_inv₀ _ h6] · assumption_mod_cast · norm_num calc diff --git a/Mathlib/NumberTheory/Bertrand.lean b/Mathlib/NumberTheory/Bertrand.lean index 772c5d12f2dff..f35408c70ebe0 100644 --- a/Mathlib/NumberTheory/Bertrand.lean +++ b/Mathlib/NumberTheory/Bertrand.lean @@ -165,13 +165,13 @@ theorem centralBinom_le_of_no_bertrand_prime (n : ℕ) (n_large : 2 < n) · exact pow_factorization_choose_le (mul_pos two_pos n_pos) have : (Finset.Icc 1 (sqrt (2 * n))).card = sqrt (2 * n) := by rw [card_Icc, Nat.add_sub_cancel] rw [Finset.prod_const] - refine pow_le_pow_right n2_pos ((Finset.card_le_card fun x hx => ?_).trans this.le) + refine pow_right_mono₀ n2_pos ((Finset.card_le_card fun x hx => ?_).trans this.le) obtain ⟨h1, h2⟩ := Finset.mem_filter.1 hx exact Finset.mem_Icc.mpr ⟨(Finset.mem_filter.1 h1).2.one_lt.le, h2⟩ · refine le_trans ?_ (primorial_le_4_pow (2 * n / 3)) refine (Finset.prod_le_prod' fun p hp => (?_ : f p ≤ p)).trans ?_ · obtain ⟨h1, h2⟩ := Finset.mem_filter.1 hp - refine (pow_le_pow_right (Finset.mem_filter.1 h1).2.one_lt.le ?_).trans (pow_one p).le + refine (pow_right_mono₀ (Finset.mem_filter.1 h1).2.one_lt.le ?_).trans (pow_one p).le exact Nat.factorization_choose_le_one (sqrt_lt'.mp <| not_le.1 h2) refine Finset.prod_le_prod_of_subset_of_one_le' (Finset.filter_subset _ _) ?_ exact fun p hp _ => (Finset.mem_filter.1 hp).2.one_lt.le diff --git a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbs.lean b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbs.lean index dd9d6a2408815..694594f1a0e40 100644 --- a/Mathlib/NumberTheory/ClassNumber/AdmissibleAbs.lean +++ b/Mathlib/NumberTheory/ClassNumber/AdmissibleAbs.lean @@ -38,7 +38,7 @@ theorem exists_partition_int (n : ℕ) {ε : ℝ} (hε : 0 < ε) {b : ℤ} (hb : refine ⟨fun i ↦ ⟨natAbs (floor ((A i % b : ℤ) / abs b • ε : ℝ)), ?_⟩, ?_⟩ · rw [← ofNat_lt, natAbs_of_nonneg (hfloor i), floor_lt] apply lt_of_lt_of_le _ (Nat.le_ceil _) - rw [Algebra.smul_def, eq_intCast, ← div_div, div_lt_div_right hε, div_lt_iff hb', one_mul, + rw [Algebra.smul_def, eq_intCast, ← div_div, div_lt_div_right hε, div_lt_iff₀ hb', one_mul, cast_lt] exact Int.emod_lt _ hb intro i₀ i₁ hi @@ -46,7 +46,7 @@ theorem exists_partition_int (n : ℕ) {ε : ℝ} (hε : 0 < ε) {b : ℤ} (hb : congr_arg ((↑) : ℕ → ℤ) (Fin.mk_eq_mk.mp hi) rw [natAbs_of_nonneg (hfloor i₀), natAbs_of_nonneg (hfloor i₁)] at hi have hi := abs_sub_lt_one_of_floor_eq_floor hi - rw [abs_sub_comm, ← sub_div, abs_div, abs_of_nonneg hbε.le, div_lt_iff hbε, one_mul] at hi + rw [abs_sub_comm, ← sub_div, abs_div, abs_of_nonneg hbε.le, div_lt_iff₀ hbε, one_mul] at hi rwa [Int.cast_abs, Int.cast_sub] /-- `abs : ℤ → ℤ` is an admissible absolute value. -/ diff --git a/Mathlib/NumberTheory/ClassNumber/AdmissibleCardPowDegree.lean b/Mathlib/NumberTheory/ClassNumber/AdmissibleCardPowDegree.lean index 7b6a30b0c651c..fabb26655f44b 100644 --- a/Mathlib/NumberTheory/ClassNumber/AdmissibleCardPowDegree.lean +++ b/Mathlib/NumberTheory/ClassNumber/AdmissibleCardPowDegree.lean @@ -131,7 +131,7 @@ theorem exists_approx_polynomial {b : Fq[X]} (hb : b ≠ 0) {ε : ℝ} (hε : 0 cardPowDegree_nonzero _ h', cardPowDegree_nonzero _ hb, Algebra.smul_def, eq_intCast, Int.cast_pow, Int.cast_natCast, Int.cast_pow, Int.cast_natCast, log_mul (pow_ne_zero _ q_pos'.ne') hε.ne', ← rpow_natCast, ← rpow_natCast, log_rpow q_pos', - log_rpow q_pos', ← lt_div_iff (log_pos one_lt_q'), add_div, + log_rpow q_pos', ← lt_div_iff₀ (log_pos one_lt_q'), add_div, mul_div_cancel_right₀ _ (log_pos one_lt_q').ne'] -- And that result follows from manipulating the result from `exists_approx_polynomial_aux` -- to turn the `-⌈-stuff⌉₊` into `+ stuff`. @@ -160,7 +160,7 @@ theorem cardPowDegree_anti_archimedean {x y z : Fq[X]} {a : ℤ} (hxy : cardPowD cardPowDegree_nonzero _ hyz'] have : (1 : ℤ) ≤ Fintype.card Fq := mod_cast (@Fintype.one_lt_card Fq _ _).le simp only [Int.cast_pow, Int.cast_natCast, le_max_iff] - refine Or.imp (pow_le_pow_right this) (pow_le_pow_right this) ?_ + refine Or.imp (pow_le_pow_right₀ this) (pow_le_pow_right₀ this) ?_ rw [natDegree_le_iff_degree_le, natDegree_le_iff_degree_le, ← le_max_iff, ← degree_eq_natDegree hxy', ← degree_eq_natDegree hyz'] convert degree_add_le (x - y) (y - z) using 2 diff --git a/Mathlib/NumberTheory/ClassNumber/FunctionField.lean b/Mathlib/NumberTheory/ClassNumber/FunctionField.lean index e45f913fd3b2e..04ead5e691263 100644 --- a/Mathlib/NumberTheory/ClassNumber/FunctionField.lean +++ b/Mathlib/NumberTheory/ClassNumber/FunctionField.lean @@ -24,7 +24,7 @@ namespace FunctionField open scoped Polynomial -variable (Fq F : Type) [Field Fq] [Fintype Fq] [Field F] +variable (Fq F : Type*) [Field Fq] [Fintype Fq] [Field F] variable [Algebra Fq[X] F] [Algebra (RatFunc Fq) F] variable [IsScalarTower Fq[X] (RatFunc Fq) F] variable [FunctionField Fq F] [Algebra.IsSeparable (RatFunc Fq) F] diff --git a/Mathlib/NumberTheory/Cyclotomic/Basic.lean b/Mathlib/NumberTheory/Cyclotomic/Basic.lean index 891a8f3be52b6..3c95d15cc13ee 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Basic.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Basic.lean @@ -5,7 +5,7 @@ Authors: Riccardo Brasca -/ import Mathlib.RingTheory.Polynomial.Cyclotomic.Roots import Mathlib.NumberTheory.NumberField.Basic -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic /-! # Cyclotomic extensions @@ -58,7 +58,7 @@ included in the `Cyclotomic` locale. -/ -open Polynomial Algebra FiniteDimensional Set +open Polynomial Algebra Module Set universe u v w z diff --git a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean index e526d1422118e..c4b31c98a929a 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Discriminant.lean @@ -168,7 +168,7 @@ theorem discr_prime_pow [hcycl : IsCyclotomicExtension {p ^ k} K L] [hp : Fact ( 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] + simp only [map_neg, map_one, Function.comp_apply, Fin.val_eq_zero, _root_.pow_zero] suffices (e.symm i : ℕ) = 0 by simp [this] rw [← Nat.lt_one_iff] convert (e.symm i).2 diff --git a/Mathlib/NumberTheory/Cyclotomic/Embeddings.lean b/Mathlib/NumberTheory/Cyclotomic/Embeddings.lean index b3d2a56cf11a2..642d6933fad59 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Embeddings.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Embeddings.lean @@ -21,7 +21,7 @@ universe u namespace IsCyclotomicExtension.Rat -open NumberField InfinitePlace FiniteDimensional Complex Nat Polynomial +open NumberField InfinitePlace Module Complex Nat Polynomial variable {n : ℕ+} (K : Type u) [Field K] [CharZero K] diff --git a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean index e8b1549b25e66..e4a82b6a04edb 100644 --- a/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean +++ b/Mathlib/NumberTheory/Cyclotomic/PrimitiveRoots.lean @@ -61,7 +61,7 @@ and only at the "final step", when we need to provide an "explicit" primitive ro -/ -open Polynomial Algebra Finset FiniteDimensional IsCyclotomicExtension Nat PNat Set +open Polynomial Algebra Finset Module IsCyclotomicExtension Nat PNat Set open scoped IntermediateField universe u v w z @@ -113,9 +113,10 @@ variable {C} /-- The `PowerBasis` given by a primitive root `η`. -/ @[simps!] protected noncomputable def powerBasis : PowerBasis K L := - PowerBasis.map (Algebra.adjoin.powerBasis <| (integral {n} K L).isIntegral ζ) <| - (Subalgebra.equivOfEq _ _ (IsCyclotomicExtension.adjoin_primitive_root_eq_top hζ)).trans - Subalgebra.topEquiv + -- this is purely an optimization + letI pb := Algebra.adjoin.powerBasis <| (integral {n} K L).isIntegral ζ + pb.map <| (Subalgebra.equivOfEq _ _ (IsCyclotomicExtension.adjoin_primitive_root_eq_top hζ)).trans + Subalgebra.topEquiv theorem powerBasis_gen_mem_adjoin_zeta_sub_one : (hζ.powerBasis K).gen ∈ adjoin K ({ζ - 1} : Set L) := by @@ -182,7 +183,7 @@ least `(lcm p q).totient`. -/ theorem _root_.IsPrimitiveRoot.lcm_totient_le_finrank [FiniteDimensional K L] {p q : ℕ} {x y : L} (hx : IsPrimitiveRoot x p) (hy : IsPrimitiveRoot y q) (hirr : Irreducible (cyclotomic (Nat.lcm p q) K)) : - (Nat.lcm p q).totient ≤ FiniteDimensional.finrank K L := by + (Nat.lcm p q).totient ≤ Module.finrank K L := by rcases Nat.eq_zero_or_pos p with (rfl | hppos) · simp rcases Nat.eq_zero_or_pos q with (rfl | hqpos) @@ -379,7 +380,7 @@ theorem minpoly_sub_one_eq_cyclotomic_comp [Algebra K A] [IsDomain A] {ζ : A} minpoly K (ζ - 1) = (cyclotomic n K).comp (X + 1) := by haveI := IsCyclotomicExtension.neZero' n K A rw [show ζ - 1 = ζ + algebraMap K A (-1) by simp [sub_eq_add_neg], - minpoly.add_algebraMap ((integral {n} K A).isIntegral ζ), + minpoly.add_algebraMap ζ, hζ.minpoly_eq_cyclotomic_of_irreducible h] simp @@ -392,9 +393,8 @@ theorem norm_pow_sub_one_of_prime_pow_ne_two {k s : ℕ} (hζ : IsPrimitiveRoot [hpri : Fact (p : ℕ).Prime] [IsCyclotomicExtension {p ^ (k + 1)} K L] (hirr : Irreducible (cyclotomic (↑(p ^ (k + 1)) : ℕ) K)) (hs : s ≤ k) (htwo : p ^ (k - s + 1) ≠ 2) : norm K (ζ ^ (p : ℕ) ^ s - 1) = (p : K) ^ (p : ℕ) ^ s := by --- Porting note: `by simp` was `by linarith` that now fails. have hirr₁ : Irreducible (cyclotomic ((p : ℕ) ^ (k - s + 1)) K) := - cyclotomic_irreducible_pow_of_irreducible_pow hpri.1 (by simp) hirr + cyclotomic_irreducible_pow_of_irreducible_pow hpri.1 (by omega) hirr rw [← PNat.pow_coe] at hirr₁ set η := ζ ^ (p : ℕ) ^ s - 1 let η₁ : K⟮η⟯ := IntermediateField.AdjoinSimple.gen K η @@ -403,22 +403,17 @@ theorem norm_pow_sub_one_of_prime_pow_ne_two {k s : ℕ} (hζ : IsPrimitiveRoot refine IsPrimitiveRoot.pow (p ^ (k + 1)).pos hζ ?_ rw [PNat.pow_coe, ← pow_add, add_comm s, Nat.sub_add_cancel (le_trans hs (Nat.le_succ k))] have : IsCyclotomicExtension {p ^ (k - s + 1)} K K⟮η⟯ := by - suffices IsCyclotomicExtension {p ^ (k - s + 1)} K K⟮η + 1⟯.toSubalgebra by - have H : K⟮η + 1⟯.toSubalgebra = K⟮η⟯.toSubalgebra := by - simp only [IntermediateField.adjoin_simple_toSubalgebra_of_integral - ((integral {p ^ (k + 1)} K L).isIntegral _)] - refine Subalgebra.ext fun x => ⟨fun hx => adjoin_le ?_ hx, fun hx => adjoin_le ?_ hx⟩ - · simp only [Set.singleton_subset_iff, SetLike.mem_coe] - exact Subalgebra.add_mem _ (subset_adjoin (mem_singleton η)) (Subalgebra.one_mem _) - · simp only [Set.singleton_subset_iff, SetLike.mem_coe] - nth_rw 2 [← add_sub_cancel_right η 1] - exact Subalgebra.sub_mem _ (subset_adjoin (mem_singleton _)) (Subalgebra.one_mem _) --- Porting note: the previous proof was `rw [H] at this; exact this` but it now fails. - exact IsCyclotomicExtension.equiv _ _ _ (Subalgebra.equivOfEq _ _ H) --- Porting note: the next `refine` was `rw [H]`, abusing defeq, and it now fails. + have HKη : K⟮η⟯ = K⟮η + 1⟯ := by + refine le_antisymm ?_ ?_ + all_goals rw [IntermediateField.adjoin_simple_le_iff] + · nth_rw 2 [← add_sub_cancel_right η 1] + exact sub_mem (IntermediateField.mem_adjoin_simple_self K (η + 1)) (one_mem _) + · exact add_mem (IntermediateField.mem_adjoin_simple_self K η) (one_mem _) + rw [HKη] have H := IntermediateField.adjoin_simple_toSubalgebra_of_integral - ((integral {p ^ (k + 1)} K L).isIntegral (η + 1)) - refine @IsCyclotomicExtension.equiv _ _ _ _ _ _ _ _ _ ?_ (Subalgebra.equivOfEq _ _ H).symm + ((integral {p ^ (k + 1)} K L).isIntegral (η + 1)) + refine IsCyclotomicExtension.equiv _ _ _ (h := ?_) (.refl : K⟮η + 1⟯.toSubalgebra ≃ₐ[K] _) + rw [H] have hη' : IsPrimitiveRoot (η + 1) ↑(p ^ (k + 1 - s)) := by simpa using hη -- Porting note: `using 1` was not needed. convert hη'.adjoin_isCyclotomicExtension K using 1 @@ -427,10 +422,10 @@ theorem norm_pow_sub_one_of_prime_pow_ne_two {k s : ℕ} (hζ : IsPrimitiveRoot apply coe_submonoidClass_iff.1 convert hη using 1 rw [Nat.sub_add_comm hs, pow_coe] --- Porting note: the following `haveI` were not needed because the locale `cyclotomic` set them +-- Porting note: the following `have` were not needed because the locale `cyclotomic` set them -- as instances. - haveI := IsCyclotomicExtension.finiteDimensional {p ^ (k + 1)} K L - haveI := IsCyclotomicExtension.isGalois (p ^ (k + 1)) K L + have := IsCyclotomicExtension.finiteDimensional {p ^ (k + 1)} K L + have := IsCyclotomicExtension.isGalois (p ^ (k + 1)) K L rw [norm_eq_norm_adjoin K] have H := hη.sub_one_norm_isPrimePow ?_ hirr₁ htwo swap; · rw [PNat.pow_coe]; exact hpri.1.isPrimePow.pow (Nat.succ_ne_zero _) @@ -439,7 +434,7 @@ theorem norm_pow_sub_one_of_prime_pow_ne_two {k s : ℕ} (hζ : IsPrimitiveRoot congr · rw [PNat.pow_coe, Nat.pow_minFac, hpri.1.minFac_eq] exact Nat.succ_ne_zero _ - have := FiniteDimensional.finrank_mul_finrank K K⟮η⟯ L + have := Module.finrank_mul_finrank K K⟮η⟯ L rw [IsCyclotomicExtension.finrank L hirr, IsCyclotomicExtension.finrank K⟮η⟯ hirr₁, PNat.pow_coe, PNat.pow_coe, Nat.totient_prime_pow hpri.out (k - s).succ_pos, Nat.totient_prime_pow hpri.out k.succ_pos, mul_comm _ ((p : ℕ) - 1), mul_assoc, diff --git a/Mathlib/NumberTheory/Cyclotomic/Rat.lean b/Mathlib/NumberTheory/Cyclotomic/Rat.lean index 58f251949cb62..39cdf61a38935 100644 --- a/Mathlib/NumberTheory/Cyclotomic/Rat.lean +++ b/Mathlib/NumberTheory/Cyclotomic/Rat.lean @@ -293,7 +293,7 @@ theorem zeta_sub_one_prime_of_ne_two [IsCyclotomicExtension {p ^ (k + 1)} ℚ K] Prime (hζ.toInteger - 1) := by letI := IsCyclotomicExtension.numberField {p ^ (k + 1)} ℚ K refine Ideal.prime_of_irreducible_absNorm_span (fun h ↦ ?_) ?_ - · apply hζ.pow_ne_one_of_pos_of_lt zero_lt_one (one_lt_pow hp.out.one_lt (by simp)) + · apply hζ.pow_ne_one_of_pos_of_lt zero_lt_one (one_lt_pow₀ hp.out.one_lt (by simp)) rw [sub_eq_zero] at h simpa using congrArg (algebraMap _ K) h rw [Nat.irreducible_iff_prime, Ideal.absNorm_span_singleton, ← Nat.prime_iff, @@ -312,7 +312,7 @@ theorem zeta_sub_one_prime_of_two_pow [IsCyclotomicExtension {(2 : ℕ+) ^ (k + Prime (hζ.toInteger - 1) := by letI := IsCyclotomicExtension.numberField {(2 : ℕ+) ^ (k + 1)} ℚ K refine Ideal.prime_of_irreducible_absNorm_span (fun h ↦ ?_) ?_ - · apply hζ.pow_ne_one_of_pos_of_lt zero_lt_one (one_lt_pow (by decide) (by simp)) + · apply hζ.pow_ne_one_of_pos_of_lt zero_lt_one (one_lt_pow₀ (by decide) (by simp)) rw [sub_eq_zero] at h simpa using congrArg (algebraMap _ K) h rw [Nat.irreducible_iff_prime, Ideal.absNorm_span_singleton, ← Nat.prime_iff, @@ -453,7 +453,7 @@ theorem not_exists_int_prime_dvd_sub_of_prime_pow_ne_two · simp only [hk, zero_add, pow_one, pow_zero, one_mul, Nat.lt_sub_iff_add_lt, Nat.reduceAdd] at htwo ⊢ exact htwo.symm.lt_of_le hp.1.two_le - · exact one_lt_mul_of_lt_of_le (one_lt_pow hp.1.one_lt hk) + · exact one_lt_mul_of_lt_of_le (one_lt_pow₀ hp.1.one_lt hk) (have := Nat.Prime.two_le hp.out; by omega) rw [sub_eq_iff_eq_add] at h -- We are assuming that `ζ = n + p * x` for some integer `n` and `x : 𝓞 K`. Looking at the @@ -498,7 +498,8 @@ theorem finite_quotient_span_sub_one [hcycl : IsCyclotomicExtension {p ^ (k + 1) have : NumberField K := IsCyclotomicExtension.numberField {p ^ (k + 1)} ℚ K refine Fintype.finite <| Ideal.fintypeQuotientOfFreeOfNeBot _ (fun h ↦ ?_) simp only [Ideal.span_singleton_eq_bot, sub_eq_zero, ← Subtype.coe_inj] at h - exact hζ.ne_one (one_lt_pow hp.1.one_lt (Nat.zero_ne_add_one k).symm) (RingOfIntegers.ext_iff.1 h) + exact hζ.ne_one (one_lt_pow₀ hp.1.one_lt (Nat.zero_ne_add_one k).symm) + (RingOfIntegers.ext_iff.1 h) theorem finite_quotient_span_sub_one' [hcycl : IsCyclotomicExtension {p} ℚ K] (hζ : IsPrimitiveRoot ζ ↑p) : diff --git a/Mathlib/NumberTheory/DiophantineApproximation.lean b/Mathlib/NumberTheory/DiophantineApproximation.lean index 77d109b645420..1d052c7a9f81e 100644 --- a/Mathlib/NumberTheory/DiophantineApproximation.lean +++ b/Mathlib/NumberTheory/DiophantineApproximation.lean @@ -235,7 +235,7 @@ theorem den_le_and_le_num_le_of_sub_lt_one_div_den_sq {ξ q : ℚ} · exact le_rfl · have hξ₀ : (0 : ℚ) < ξ.den := Nat.cast_pos.mpr ξ.pos rw [← Rat.num_div_den ξ, div_mul_eq_mul_div, div_sub' _ _ _ hξ₀.ne', abs_div, abs_of_pos hξ₀, - div_lt_iff hξ₀, div_mul_comm, mul_one] at h + div_lt_iff₀ hξ₀, div_mul_comm, mul_one] at h refine Nat.cast_le.mp ((one_lt_div hq₀).mp <| lt_of_le_of_lt ?_ h).le norm_cast rw [mul_comm _ q.num] @@ -406,8 +406,7 @@ private theorem aux₁ : 0 < fract ξ := by refine fract_pos.mpr fun hf => ?_ rw [hf] at h have H : (2 * v - 1 : ℝ) < 1 := by - refine - (mul_lt_iff_lt_one_right hv₀).mp ((inv_lt_inv hv₀ (mul_pos hv₁ hv₂)).mp (lt_of_le_of_lt ?_ h)) + refine (mul_lt_iff_lt_one_right hv₀).1 ((inv_lt_inv₀ hv₀ (mul_pos hv₁ hv₂)).1 (h.trans_le' ?_)) have h' : (⌊ξ⌋ : ℝ) - u / v = (⌊ξ⌋ * v - u) / v := by field_simp rw [h', abs_div, abs_of_pos hv₀, ← one_div, div_le_div_right hv₀] norm_cast @@ -422,9 +421,9 @@ private theorem aux₂ : 0 < u - ⌊ξ⌋ * v ∧ u - ⌊ξ⌋ * v < v := by obtain ⟨hcop, _, h⟩ := h obtain ⟨hv₀, hv₀'⟩ := aux₀ (zero_lt_two.trans_le hv) have hv₁ : 0 < 2 * v - 1 := by linarith only [hv] - rw [← one_div, lt_div_iff (mul_pos hv₀ hv₀'), ← abs_of_pos (mul_pos hv₀ hv₀'), ← abs_mul, sub_mul, - ← mul_assoc, ← mul_assoc, div_mul_cancel₀ _ hv₀.ne', abs_sub_comm, abs_lt, lt_sub_iff_add_lt, - sub_lt_iff_lt_add, mul_assoc] at h + rw [← one_div, lt_div_iff₀ (mul_pos hv₀ hv₀'), ← abs_of_pos (mul_pos hv₀ hv₀'), ← abs_mul, + sub_mul, ← mul_assoc, ← mul_assoc, div_mul_cancel₀ _ hv₀.ne', abs_sub_comm, abs_lt, + lt_sub_iff_add_lt, sub_lt_iff_lt_add, mul_assoc] at h have hu₀ : 0 ≤ u - ⌊ξ⌋ * v := by -- Porting note: this abused the definitional equality `-1 + 1 = 0` -- refine' (mul_nonneg_iff_of_pos_right hv₁).mp ((lt_iff_add_one_le (-1 : ℤ) _).mp _) @@ -490,7 +489,7 @@ private theorem aux₃ : _ < ((v : ℝ) * (2 * v - 1))⁻¹ * (v / u' / fract ξ) := (mul_lt_mul_right H₁).mpr h' _ = (u' * (2 * v - 1) * fract ξ)⁻¹ := help₂ hξ₀.ne' Hv.ne' Hv'.ne' Hu.ne' _ ≤ ((u' : ℝ) * (2 * u' - 1))⁻¹ := by - rwa [inv_le_inv (mul_pos (mul_pos Hu Hv') hξ₀) <| mul_pos Hu Hu', mul_assoc, + rwa [inv_le_inv₀ (mul_pos (mul_pos Hu Hv') hξ₀) <| mul_pos Hu Hu', mul_assoc, mul_le_mul_left Hu] -- The conditions `ass ξ u v` persist in the inductive step. @@ -506,7 +505,7 @@ private theorem invariant : ContfracLegendre.Ass (fract ξ)⁻¹ v (u - ⌊ξ⌋ have h' := (abs_sub_lt_iff.mp h.2.2).1 rw [Huv, ← sub_sub, sub_lt_iff_lt_add, self_sub_floor, Hv] at h' rwa [lt_sub_iff_add_lt', (by ring : (v : ℝ) + -(1 / 2) = (2 * v - 1) / 2), - lt_inv (div_pos hv₀' zero_lt_two) (aux₁ hv h), inv_div] + lt_inv_comm₀ (div_pos hv₀' zero_lt_two) (aux₁ hv h), inv_div] end @@ -538,8 +537,8 @@ theorem exists_rat_eq_convergent' {v : ℕ} (h : ContfracLegendre.Ass ξ u v) : · rw [Hξ, hξ₁, cast_sub, cast_one, ← sub_eq_add_neg, sub_lt_sub_iff_left] at h₁ exact False.elim (lt_irrefl _ <| h₁.trans one_half_lt_one) · have hξ₂ : ⌊(fract ξ)⁻¹⌋ = 1 := by - rw [floor_eq_iff, cast_one, le_inv zero_lt_one (fract_pos.mpr Hξ), inv_one, - one_add_one_eq_two, inv_lt (fract_pos.mpr Hξ) zero_lt_two] + rw [floor_eq_iff, cast_one, le_inv_comm₀ zero_lt_one (fract_pos.mpr Hξ), inv_one, + one_add_one_eq_two, inv_lt_comm₀ (fract_pos.mpr Hξ) zero_lt_two] refine ⟨(fract_lt_one ξ).le, ?_⟩ rw [fract, hξ₁, cast_sub, cast_one, lt_sub_iff_add_lt', sub_add] convert h₁ using 1 diff --git a/Mathlib/NumberTheory/FactorisationProperties.lean b/Mathlib/NumberTheory/FactorisationProperties.lean new file mode 100644 index 0000000000000..28cabcc7fd958 --- /dev/null +++ b/Mathlib/NumberTheory/FactorisationProperties.lean @@ -0,0 +1,198 @@ +/- +Copyright (c) 2024 Colin Jones. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Colin Jones +-/ +import Mathlib.Algebra.GeomSum +import Mathlib.Algebra.IsPrimePow +import Mathlib.NumberTheory.Divisors +import Mathlib.Tactic.FinCases +import Mathlib.Tactic.NormNum.Prime + +/-! +# Factorisation properties of natural numbers + +This file defines abundant, pseudoperfect, deficient, and weird numbers and formalizes their +relations with prime and perfect numbers. + +## Main Definitions + +* `Nat.Abundant`: a natural number `n` is _abundant_ if the sum of its proper divisors is greater + than `n` +* `Nat.Pseudoperfect`: a natural number `n` is _pseudoperfect_ if the sum of a subset of its proper + divisors equals `n` +* `Nat.Deficient`: a natural number `n` is _deficient_ if the sum of its proper divisors is less + than `n` +* `Nat.Weird`: a natural number is _weird_ if it is abundant but not pseudoperfect + +## Main Results + +* `Nat.deficient_or_perfect_or_abundant`: A positive natural number is either deficient, + perfect, or abundant. +* `Nat.Prime.deficient`: All prime natural numbers are deficient. +* `Nat.infinite_deficient`: There are infinitely many deficient numbers. +* `Nat.Prime.deficient_pow`: Any natural number power of a prime is deficient. + +## Implementation Notes +* Zero is not included in any of the definitions and these definitions only apply to natural + numbers greater than zero. + +## References +* [R. W. Prielipp, *PERFECT NUMBERS, ABUNDANT NUMBERS, AND DEFICIENT NUMBERS*][Prielipp1970] + +## Tags + +abundant, deficient, weird, pseudoperfect +-/ + +open Finset + +namespace Nat + +variable {n m p : ℕ} + +/-- `n : ℕ` is _abundant_ if the sum of the proper divisors of `n` is greater than `n`. -/ +def Abundant (n : ℕ) : Prop := n < ∑ i ∈ properDivisors n, i + +/-- `n : ℕ` is _deficient_ if the sum of the proper divisors of `n` is less than `n`. -/ +def Deficient (n : ℕ) : Prop := ∑ i ∈ properDivisors n, i < n + +/-- A positive natural number `n` is _pseudoperfect_ if there exists a subset of the proper + divisors of `n` such that the sum of that subset is equal to `n`. -/ +def Pseudoperfect (n : ℕ) : Prop := + 0 < n ∧ ∃ s ⊆ properDivisors n, ∑ i ∈ s, i = n + +/-- `n : ℕ` is a _weird_ number if and only if it is abundant but not pseudoperfect. -/ +def Weird (n : ℕ) : Prop := Abundant n ∧ ¬ Pseudoperfect n + +theorem not_pseudoperfect_iff_forall : + ¬ Pseudoperfect n ↔ n = 0 ∨ ∀ s ⊆ properDivisors n, ∑ i ∈ s, i ≠ n := by + rw [Pseudoperfect, not_and_or] + simp only [not_lt, nonpos_iff_eq_zero, mem_powerset, not_exists, not_and, ne_eq] + +theorem deficient_one : Deficient 1 := zero_lt_one +theorem deficient_two : Deficient 2 := one_lt_two +theorem deficient_three : Deficient 3 := by norm_num [Deficient] + +theorem abundant_twelve : Abundant 12 := by + rw [Abundant, show properDivisors 12 = {1,2,3,4,6} by rfl] + norm_num + +set_option maxRecDepth 1730 in +theorem weird_seventy : Weird 70 := by + rw [Weird, Abundant, not_pseudoperfect_iff_forall] + have h : properDivisors 70 = {1, 2, 5, 7, 10, 14, 35} := by rfl + constructor + · rw [h] + repeat norm_num + · rw [h] + right + intro s hs + have hs' := mem_powerset.mpr hs + fin_cases hs' <;> decide + +lemma deficient_iff_not_abundant_and_not_perfect (hn : n ≠ 0) : + Deficient n ↔ ¬ Abundant n ∧ ¬ Perfect n := by + dsimp only [Perfect, Abundant, Deficient] + omega + +lemma perfect_iff_not_abundant_and_not_deficient (hn : 0 ≠ n) : + Perfect n ↔ ¬ Abundant n ∧ ¬ Deficient n := by + dsimp only [Perfect, Abundant, Deficient] + omega + +lemma abundant_iff_not_perfect_and_not_deficient (hn : 0 ≠ n) : + Abundant n ↔ ¬ Perfect n ∧ ¬ Deficient n := by + dsimp only [Perfect, Abundant, Deficient] + omega + +/-- A positive natural number is either deficient, perfect, or abundant -/ +theorem deficient_or_perfect_or_abundant (hn : 0 ≠ n) : + Deficient n ∨ Abundant n ∨ Perfect n := by + dsimp only [Perfect, Abundant, Deficient] + omega + +theorem Perfect.pseudoperfect (h : Perfect n) : Pseudoperfect n := + ⟨h.2, ⟨properDivisors n, ⟨fun ⦃_⦄ a ↦ a, h.1⟩⟩⟩ + +theorem Prime.not_abundant (h : Prime n) : ¬ Abundant n := + fun h1 ↦ (h.one_lt.trans h1).ne' (sum_properDivisors_eq_one_iff_prime.mpr h) + +theorem Prime.not_weird (h : Prime n) : ¬ Weird n := by + simp only [Nat.Weird, not_and_or] + left + exact h.not_abundant + +theorem Prime.not_pseudoperfect (h : Prime p) : ¬ Pseudoperfect p := by + simp_rw [not_pseudoperfect_iff_forall, ← mem_powerset, + show p.properDivisors.powerset = {∅, {1}} by rw [Prime.properDivisors h]; rfl] + refine Or.inr (fun s hs ↦ ?_) + fin_cases hs <;> + simp only [sum_empty, sum_singleton] <;> + linarith [Prime.one_lt h] + +theorem Prime.not_perfect (h : Prime p) : ¬ Perfect p := by + have h1 := Prime.not_pseudoperfect h + revert h1 + exact not_imp_not.mpr (Perfect.pseudoperfect) + +/-- Any natural number power of a prime is deficient -/ +theorem Prime.deficient_pow (h : Prime n) : Deficient (n ^ m) := by + rcases Nat.eq_zero_or_pos m with (rfl | _) + · simpa using deficient_one + · have h1 : (n ^ m).properDivisors = image (n ^ ·) (range m) := by + apply subset_antisymm <;> intro a + · simp only [mem_properDivisors, mem_image, mem_range, dvd_prime_pow h] + rintro ⟨⟨t, ht, rfl⟩, ha'⟩ + exact ⟨t, lt_of_le_of_ne ht (fun ht' ↦ lt_irrefl _ (ht' ▸ ha')), rfl⟩ + · simp only [mem_image, mem_range, mem_properDivisors, forall_exists_index, and_imp] + intro x hx hy + constructor + · rw [← hy, dvd_prime_pow h] + exact ⟨x, Nat.le_of_succ_le hx, rfl⟩ + · rw [← hy] + exact (Nat.pow_lt_pow_iff_right (Prime.two_le h)).mpr hx + have h2 : ∑ i in image (fun x => n ^ x) (range m), i = ∑ i in range m, n^i := by + rw [Finset.sum_image] + rintro x _ y _ + apply pow_injective_of_not_isUnit h.not_unit <| Prime.ne_zero h + rw [Deficient, h1, h2] + calc + ∑ i ∈ range m, n ^ i + = (n ^ m - 1) / (n - 1) := (Nat.geomSum_eq (Prime.two_le h) _) + _ ≤ (n ^ m - 1) := Nat.div_le_self (n ^ m - 1) (n - 1) + _ < n ^ m := sub_lt (pow_pos (Prime.pos h) m) (Nat.one_pos) + +theorem _root_.IsPrimePow.deficient (h : IsPrimePow n) : Deficient n := by + obtain ⟨p, k, hp, -, rfl⟩ := h + exact hp.nat_prime.deficient_pow + +theorem Prime.deficient (h : Prime n) : Deficient n := by + rw [← pow_one n] + exact h.deficient_pow + +/-- There exists infinitely many deficient numbers -/ +theorem infinite_deficient : {n : ℕ | n.Deficient}.Infinite := by + rw [Set.infinite_iff_exists_gt] + intro a + obtain ⟨b, h1, h2⟩ := exists_infinite_primes a.succ + exact ⟨b, h2.deficient, h1⟩ + +theorem infinite_even_deficient : {n : ℕ | Even n ∧ n.Deficient}.Infinite := by + rw [Set.infinite_iff_exists_gt] + intro n + use 2 ^ (n + 1) + constructor + · exact ⟨⟨2 ^ n, by ring⟩, prime_two.deficient_pow⟩ + · calc + n ≤ 2 ^ n := Nat.le_of_lt (lt_two_pow n) + _ < 2 ^ (n + 1) := (Nat.pow_lt_pow_iff_right (Nat.one_lt_two)).mpr (lt_add_one n) + +theorem infinite_odd_deficient : {n : ℕ | Odd n ∧ n.Deficient}.Infinite := by + rw [Set.infinite_iff_exists_gt] + intro n + obtain ⟨p, ⟨_, h2⟩⟩ := exists_infinite_primes (max (n + 1) 3) + exact ⟨p, Set.mem_setOf.mpr ⟨Prime.odd_of_ne_two h2 (Ne.symm (ne_of_lt (by omega))), + Prime.deficient h2⟩, by omega⟩ + +end Nat diff --git a/Mathlib/NumberTheory/Fermat.lean b/Mathlib/NumberTheory/Fermat.lean new file mode 100644 index 0000000000000..0fcd105b0a600 --- /dev/null +++ b/Mathlib/NumberTheory/Fermat.lean @@ -0,0 +1,77 @@ +/- +Copyright (c) 2024 Moritz Firsching. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Moritz Firsching +-/ +import Mathlib.Algebra.BigOperators.Group.Finset +import Mathlib.Algebra.Order.Ring.Basic +import Mathlib.Algebra.Order.Star.Basic +import Mathlib.Data.Nat.Prime.Defs +import Mathlib.Tactic.Ring.RingNF + +/-! +# Fermat numbers + +The Fermat numbers are a sequence of natural numbers defined as `Nat.fermatNumber n = 2^(2^n) + 1`, +for all natural numbers `n`. + +## Main theorems + +- `Nat.coprime_fermatNumber_fermatNumber`: two distinct Fermat numbers are coprime. +-/ + +namespace Nat + +open Finset +open scoped BigOperators + +/-- Fermat numbers: the `n`-th Fermat number is defined as `2^(2^n) + 1`. -/ +def fermatNumber (n : ℕ) : ℕ := 2 ^ (2 ^ n) + 1 + +@[simp] theorem fermatNumber_zero : fermatNumber 0 = 3 := rfl +@[simp] theorem fermatNumber_one : fermatNumber 1 = 5 := rfl +@[simp] theorem fermatNumber_two : fermatNumber 2 = 17 := rfl + +theorem strictMono_fermatNumber : StrictMono fermatNumber := by + intro m n + simp only [fermatNumber, add_lt_add_iff_right, pow_lt_pow_iff_right (one_lt_two : 1 < 2), + imp_self] + +theorem two_lt_fermatNumber (n : ℕ) : 2 < fermatNumber n := by + cases n + · simp + · exact lt_of_succ_lt <| strictMono_fermatNumber <| zero_lt_succ _ + +theorem odd_fermatNumber (n : ℕ) : Odd (fermatNumber n) := + (even_pow.mpr ⟨even_two, (pow_pos two_pos n).ne'⟩).add_one + +theorem fermatNumber_product (n : ℕ) : ∏ k in range n, fermatNumber k = fermatNumber n - 2 := by + induction' n with n hn + · rfl + rw [prod_range_succ, hn, fermatNumber, fermatNumber, mul_comm, + (show 2 ^ 2 ^ n + 1 - 2 = 2 ^ 2 ^ n - 1 by omega), ← sq_sub_sq] + ring_nf + omega + +theorem fermatNumber_eq_prod_add_two (n : ℕ) : + fermatNumber n = (∏ k in range n, fermatNumber k) + 2 := by + rw [fermatNumber_product, Nat.sub_add_cancel] + exact le_of_lt <| two_lt_fermatNumber _ + +/-- +**Goldbach's theorem** : no two distinct Fermat numbers share a common factor greater than one. + +From a letter to Euler, see page 37 in [juskevic2022]. +-/ +theorem coprime_fermatNumber_fermatNumber {k n : ℕ} (h : k ≠ n) : + Coprime (fermatNumber n) (fermatNumber k) := by + wlog hkn : k < n + · simpa only [coprime_comm] using this h.symm (by omega) + let m := (fermatNumber n).gcd (fermatNumber k) + have h_n : m ∣ fermatNumber n := (fermatNumber n).gcd_dvd_left (fermatNumber k) + have h_m : m ∣ 2 := (Nat.dvd_add_right <| (gcd_dvd_right _ _).trans <| dvd_prod_of_mem _ + <| mem_range.mpr hkn).mp <| fermatNumber_eq_prod_add_two _ ▸ h_n + refine ((dvd_prime prime_two).mp h_m).elim id (fun h_two ↦ ?_) + exact ((odd_fermatNumber _).not_two_dvd_nat (h_two ▸ h_n)).elim + + end Nat diff --git a/Mathlib/NumberTheory/FermatPsp.lean b/Mathlib/NumberTheory/FermatPsp.lean index 360f3dc05e0c5..113b74cc7f237 100644 --- a/Mathlib/NumberTheory/FermatPsp.lean +++ b/Mathlib/NumberTheory/FermatPsp.lean @@ -94,7 +94,7 @@ theorem coprime_of_probablePrime {n b : ℕ} (h : ProbablePrime n b) (h₁ : 1 theorem probablePrime_iff_modEq (n : ℕ) {b : ℕ} (h : 1 ≤ b) : ProbablePrime n b ↔ b ^ (n - 1) ≡ 1 [MOD n] := by - have : 1 ≤ b ^ (n - 1) := one_le_pow_of_one_le h (n - 1) + have : 1 ≤ b ^ (n - 1) := one_le_pow₀ h -- For exact mod_cast rw [Nat.ModEq.comm] constructor @@ -135,7 +135,7 @@ private theorem b_id_helper {a b : ℕ} (ha : 2 ≤ a) (hb : 2 < b) : 2 ≤ (a ^ calc 2 * a + 1 ≤ a ^ 2 * a := by nlinarith _ = a ^ 3 := by rw [Nat.pow_succ a 2] - _ ≤ a ^ b := pow_le_pow_right (Nat.le_of_succ_le ha) hb + _ ≤ a ^ b := pow_right_mono₀ (Nat.le_of_succ_le ha) hb private theorem AB_id_helper (b p : ℕ) (_ : 2 ≤ b) (hp : Odd p) : (b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1)) = (b ^ (2 * p) - 1) / (b ^ 2 - 1) := by diff --git a/Mathlib/NumberTheory/FunctionField.lean b/Mathlib/NumberTheory/FunctionField.lean index 2093382c27cb9..69740e0014839 100644 --- a/Mathlib/NumberTheory/FunctionField.lean +++ b/Mathlib/NumberTheory/FunctionField.lean @@ -44,7 +44,7 @@ noncomputable section open scoped nonZeroDivisors Polynomial Multiplicative -variable (Fq F : Type) [Field Fq] [Field F] +variable (Fq F : Type*) [Field Fq] [Field F] /-- `F` is a function field over the finite field `Fq` if it is a finite extension of the field of rational functions in one variable over `Fq`. @@ -69,9 +69,9 @@ theorem functionField_iff (Fqt : Type*) [Field Fqt] [Algebra Fq[X] Fqt] refine IsLocalization.ext (nonZeroDivisors Fq[X]) _ _ ?_ ?_ ?_ ?_ ?_ <;> intros <;> simp only [map_one, map_mul, AlgEquiv.commutes, ← IsScalarTower.algebraMap_apply] constructor <;> intro h - · let b := FiniteDimensional.finBasis (RatFunc Fq) F + · let b := Module.finBasis (RatFunc Fq) F exact FiniteDimensional.of_fintype_basis (b.mapCoeffs e this) - · let b := FiniteDimensional.finBasis Fqt F + · let b := Module.finBasis Fqt F refine FiniteDimensional.of_fintype_basis (b.mapCoeffs e.symm ?_) intro c x; convert (this (e.symm c) x).symm; simp only [e.apply_symm_apply] diff --git a/Mathlib/NumberTheory/GaussSum.lean b/Mathlib/NumberTheory/GaussSum.lean index 5140078baa06e..6af4f9545d5ff 100644 --- a/Mathlib/NumberTheory/GaussSum.lean +++ b/Mathlib/NumberTheory/GaussSum.lean @@ -97,8 +97,15 @@ lemma gaussSum_mul {R : Type u} [CommRing R] [Fintype R] {R' : Type v} [CommRing · exact fun a _ ↦ by rw [add_sub_cancel_right, add_comm] rw [sum_congr rfl fun x _ ↦ sum_eq x, sum_comm] --- In the following, we need `R` to be a finite field and `R'` to be a domain. -variable {R : Type u} [Field R] [Fintype R] {R' : Type v} [CommRing R'] [IsDomain R'] +-- In the following, we need `R` to be a finite field. +variable {R : Type u} [Field R] [Fintype R] {R' : Type v} [CommRing R'] + +lemma mul_gaussSum_inv_eq_gaussSum (χ : MulChar R R') (ψ : AddChar R R') : + χ (-1) * gaussSum χ ψ⁻¹ = gaussSum χ ψ := by + rw [ψ.inv_mulShift, ← Units.coe_neg_one] + exact gaussSum_mulShift χ ψ (-1) + +variable [IsDomain R'] -- From now on, `R'` needs to be a domain. -- A helper lemma for `gaussSum_mul_gaussSum_eq_card` below -- Is this useful enough in other contexts to be public? @@ -130,6 +137,17 @@ theorem gaussSum_mul_gaussSum_eq_card {χ : MulChar R R'} (hχ : χ ≠ 1) {ψ : rw [Finset.sum_ite_eq' Finset.univ (1 : R)] simp only [Finset.mem_univ, map_one, one_mul, if_true] +/-- If `χ` is a multiplicative character of order `n` on a finite field `F`, +then `g(χ) * g(χ^(n-1)) = χ(-1)*#F` -/ +lemma gaussSum_mul_gaussSum_pow_orderOf_sub_one {χ : MulChar R R'} {ψ : AddChar R R'} + (hχ : χ ≠ 1) (hψ : ψ.IsPrimitive) : + gaussSum χ ψ * gaussSum (χ ^ (orderOf χ - 1)) ψ = χ (-1) * Fintype.card R := by + have h : χ ^ (orderOf χ - 1) = χ⁻¹ := by + refine (inv_eq_of_mul_eq_one_right ?_).symm + rw [← pow_succ', Nat.sub_one_add_one_eq_of_pos χ.orderOf_pos, pow_orderOf_eq_one] + rw [h, ← mul_gaussSum_inv_eq_gaussSum χ⁻¹, mul_left_comm, gaussSum_mul_gaussSum_eq_card hχ hψ, + MulChar.inv_apply', inv_neg_one] + /-- The Gauss sum of a nontrivial character on a finite field does not vanish. -/ lemma gaussSum_ne_zero_of_nontrivial (h : (Fintype.card R : R') ≠ 0) {χ : MulChar R R'} (hχ : χ ≠ 1) {ψ : AddChar R R'} (hψ : ψ.IsPrimitive) : diff --git a/Mathlib/NumberTheory/Harmonic/Int.lean b/Mathlib/NumberTheory/Harmonic/Int.lean index cf5d3e429630e..822c1dac331cb 100644 --- a/Mathlib/NumberTheory/Harmonic/Int.lean +++ b/Mathlib/NumberTheory/Harmonic/Int.lean @@ -43,4 +43,4 @@ theorem harmonic_not_int {n : ℕ} (h : 2 ≤ n) : ¬ (harmonic n).isInt := by apply padicNorm.not_int_of_not_padic_int 2 rw [padicNorm.eq_zpow_of_nonzero (harmonic_pos (ne_zero_of_lt h)).ne', padicValRat_two_harmonic, neg_neg, zpow_natCast] - exact one_lt_pow one_lt_two (Nat.log_pos one_lt_two h).ne' + exact one_lt_pow₀ one_lt_two (Nat.log_pos one_lt_two h).ne' diff --git a/Mathlib/NumberTheory/JacobiSum/Basic.lean b/Mathlib/NumberTheory/JacobiSum/Basic.lean index 5025b602f0542..a936f799462ca 100644 --- a/Mathlib/NumberTheory/JacobiSum/Basic.lean +++ b/Mathlib/NumberTheory/JacobiSum/Basic.lean @@ -4,6 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Michael Stoll -/ import Mathlib.NumberTheory.GaussSum +import Mathlib.NumberTheory.MulChar.Lemmas +import Mathlib.RingTheory.RootsOfUnity.Lemmas /-! # Jacobi Sums @@ -226,3 +228,109 @@ lemma jacobiSum_mul_jacobiSum_inv (h : ringChar F' ≠ ringChar F) {χ φ : MulC ← mul_inv, gaussSum_mul_gaussSum_eq_card Hχφ ψ.prim] end field_field + +section image + +variable {F R : Type*} [Fintype F] [Field F] [CommRing R] [IsDomain R] + +/-- If `χ` and `φ` are multiplicative characters on a finite field `F` satisfying `χ^n = φ^n = 1` +and with values in an integral domain `R`, and `μ` is a primitive `n`th root of unity in `R`, +then the Jacobi sum `J(χ,φ)` is in `ℤ[μ] ⊆ R`. -/ +lemma jacobiSum_mem_algebraAdjoin_of_pow_eq_one {n : ℕ} (hn : n ≠ 0) {χ φ : MulChar F R} + (hχ : χ ^ n = 1) (hφ : φ ^ n = 1) {μ : R} (hμ : IsPrimitiveRoot μ n) : + jacobiSum χ φ ∈ Algebra.adjoin ℤ {μ} := + Subalgebra.sum_mem _ fun _ _ ↦ Subalgebra.mul_mem _ + (MulChar.apply_mem_algebraAdjoin_of_pow_eq_one hn hχ hμ _) + (MulChar.apply_mem_algebraAdjoin_of_pow_eq_one hn hφ hμ _) + +open Algebra in +private +lemma MulChar.exists_apply_sub_one_eq_mul_sub_one {n : ℕ} (hn : n ≠ 0) {χ : MulChar F R} {μ : R} + (hχ : χ ^ n = 1) (hμ : IsPrimitiveRoot μ n) {x : F} (hx : x ≠ 0) : + ∃ z ∈ Algebra.adjoin ℤ {μ}, χ x - 1 = z * (μ - 1) := by + obtain ⟨k, _, hk⟩ := exists_apply_eq_pow hn hχ hμ hx + refine hk ▸ ⟨(Finset.range k).sum (μ ^ ·), ?_, (geom_sum_mul μ k).symm⟩ + exact Subalgebra.sum_mem _ fun m _ ↦ Subalgebra.pow_mem _ (self_mem_adjoin_singleton _ μ) _ + +private +lemma MulChar.exists_apply_sub_one_mul_apply_sub_one {n : ℕ} (hn : n ≠ 0) {χ ψ : MulChar F R} + {μ : R} (hχ : χ ^ n = 1) (hψ : ψ ^ n = 1) (hμ : IsPrimitiveRoot μ n) (x : F) : + ∃ z ∈ Algebra.adjoin ℤ {μ}, (χ x - 1) * (ψ (1 - x) - 1) = z * (μ - 1) ^ 2 := by + rcases eq_or_ne x 0 with rfl | hx₀ + · exact ⟨0, Subalgebra.zero_mem _, by rw [sub_zero, ψ.map_one, sub_self, mul_zero, zero_mul]⟩ + rcases eq_or_ne x 1 with rfl | hx₁ + · exact ⟨0, Subalgebra.zero_mem _, by rw [χ.map_one, sub_self, zero_mul, zero_mul]⟩ + obtain ⟨z₁, hz₁, Hz₁⟩ := MulChar.exists_apply_sub_one_eq_mul_sub_one hn hχ hμ hx₀ + obtain ⟨z₂, hz₂, Hz₂⟩ := + MulChar.exists_apply_sub_one_eq_mul_sub_one hn hψ hμ (sub_ne_zero_of_ne hx₁.symm) + rewrite [Hz₁, Hz₂, sq] + exact ⟨z₁ * z₂, Subalgebra.mul_mem _ hz₁ hz₂, mul_mul_mul_comm ..⟩ + +/-- If `χ` and `ψ` are multiplicative characters of order dividing `n` on a finite field `F` +with values in an integral domain `R` and `μ` is a primitive `n`th root of unity in `R`, +then `J(χ,ψ) = -1 + z*(μ - 1)^2` for some `z ∈ ℤ[μ] ⊆ R`. (We assume that `#F ≡ 1 mod n`.) +Note that we do not state this as a divisibility in `R`, as this would give a weaker statement. -/ +lemma exists_jacobiSum_eq_neg_one_add {n : ℕ} (hn : 2 < n) {χ ψ : MulChar F R} + {μ : R} (hχ : χ ^ n = 1) (hψ : ψ ^ n = 1) (hn' : n ∣ Fintype.card F - 1) + (hμ : IsPrimitiveRoot μ n) : + ∃ z ∈ Algebra.adjoin ℤ {μ}, jacobiSum χ ψ = -1 + z * (μ - 1) ^ 2 := by + obtain ⟨q, hq⟩ := hn' + rw [Nat.sub_eq_iff_eq_add NeZero.one_le] at hq + obtain ⟨z₁, hz₁, Hz₁⟩ := hμ.self_sub_one_pow_dvd_order hn + by_cases hχ₀ : χ = 1 <;> by_cases hψ₀ : ψ = 1 + · rw [hχ₀, hψ₀, jacobiSum_one_one] + refine ⟨q * z₁, Subalgebra.mul_mem _ (Subalgebra.natCast_mem _ q) hz₁, ?_⟩ + rw [hq, Nat.cast_add, Nat.cast_mul, Hz₁] + ring + · refine ⟨0, Subalgebra.zero_mem _, ?_⟩ + rw [hχ₀, jacobiSum_one_nontrivial hψ₀, zero_mul, add_zero] + · refine ⟨0, Subalgebra.zero_mem _, ?_⟩ + rw [jacobiSum_comm, hψ₀, jacobiSum_one_nontrivial hχ₀, zero_mul, add_zero] + · classical + rw [jacobiSum_eq_aux, MulChar.sum_eq_zero_of_ne_one hχ₀, MulChar.sum_eq_zero_of_ne_one hψ₀, hq] + have H := MulChar.exists_apply_sub_one_mul_apply_sub_one (by omega) hχ hψ hμ + have Hcs x := (H x).choose_spec + refine ⟨-q * z₁ + ∑ x ∈ (univ \ {0, 1} : Finset F), (H x).choose, ?_, ?_⟩ + · refine Subalgebra.add_mem _ (Subalgebra.mul_mem _ (Subalgebra.neg_mem _ ?_) hz₁) ?_ + · exact Subalgebra.natCast_mem .. + · exact Subalgebra.sum_mem _ fun x _ ↦ (Hcs x).1 + · conv => enter [1, 2, 2, x]; rw [(Hcs x).2] + rw [← Finset.sum_mul, Nat.cast_add, Nat.cast_mul, Hz₁] + ring + +end image + +section GaussSum + +variable {F R : Type*} [Fintype F] [Field F] [CommRing R] [IsDomain R] + +lemma gaussSum_pow_eq_prod_jacobiSum_aux (χ : MulChar F R) (ψ : AddChar F R) {n : ℕ} + (hn₁ : 0 < n) (hn₂ : n < orderOf χ) : + gaussSum χ ψ ^ n = gaussSum (χ ^ n) ψ * ∏ j ∈ Ico 1 n, jacobiSum χ (χ ^ j) := by + induction n, hn₁ using Nat.le_induction with + | base => simp only [pow_one, le_refl, Ico_eq_empty_of_le, prod_empty, mul_one] + | succ n hn ih => + specialize ih <| lt_trans (Nat.lt_succ_self n) hn₂ + have gauss_rw : gaussSum (χ ^ n) ψ * gaussSum χ ψ = + jacobiSum χ (χ ^ n) * gaussSum (χ ^ (n + 1)) ψ := by + have hχn : χ * (χ ^ n) ≠ 1 := + pow_succ' χ n ▸ pow_ne_one_of_lt_orderOf n.add_one_ne_zero hn₂ + rw [mul_comm, ← jacobiSum_mul_nontrivial hχn, mul_comm, ← pow_succ'] + apply_fun (· * gaussSum χ ψ) at ih + rw [mul_right_comm, ← pow_succ, gauss_rw] at ih + rw [ih, Finset.prod_Ico_succ_top hn, mul_rotate, mul_assoc] + +/-- If `χ` is a multiplicative character of order `n ≥ 2` on a finite field `F`, +then `g(χ)^n = χ(-1) * #F * J(χ,χ) * J(χ,χ²) * ... * J(χ,χⁿ⁻²)`. -/ +theorem gaussSum_pow_eq_prod_jacobiSum {χ : MulChar F R} {ψ : AddChar F R} (hχ : 2 ≤ orderOf χ) + (hψ : ψ.IsPrimitive) : + gaussSum χ ψ ^ orderOf χ = + χ (-1) * Fintype.card F * ∏ i ∈ Ico 1 (orderOf χ - 1), jacobiSum χ (χ ^ i) := by + have := gaussSum_pow_eq_prod_jacobiSum_aux χ ψ (n := orderOf χ - 1) (by omega) (by omega) + apply_fun (gaussSum χ ψ * ·) at this + rw [← pow_succ', Nat.sub_one_add_one_eq_of_pos (by omega)] at this + have hχ₁ : χ ≠ 1 := + fun h ↦ ((orderOf_one (G := MulChar F R) ▸ h ▸ hχ).trans_lt Nat.one_lt_two).false + rw [this, ← mul_assoc, gaussSum_mul_gaussSum_pow_orderOf_sub_one hχ₁ hψ] + +end GaussSum diff --git a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean index df6dd1f46c15f..5f25d59164fa6 100644 --- a/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean +++ b/Mathlib/NumberTheory/LSeries/AbstractFuncEq.lean @@ -167,7 +167,7 @@ lemma hf_zero' (P : WeakFEPair E) : filter_upwards [eventually_le_nhds zero_lt_one] with x hx' (hx : 0 < x) apply le_mul_of_one_le_right (norm_nonneg _) rw [norm_of_nonneg (rpow_pos_of_pos hx _).le, rpow_neg hx.le] - exact one_le_inv (rpow_pos_of_pos hx _) (rpow_le_one hx.le hx' P.hk.le) + exact (one_le_inv₀ (rpow_pos_of_pos hx _)).2 (rpow_le_one hx.le hx' P.hk.le) end WeakFEPair @@ -226,8 +226,8 @@ theorem functional_equation (s : ℂ) : have step3 := mellin_const_smul (fun t ↦ (t : ℂ) ^ (-P.k : ℂ) • P.g (1 / t)) (P.k - s) P.ε rw [step2] at step3 rw [← step3] - -- now the integrand matches `P.h_feq'` on `Ioi 0`, so we can apply `setIntegral_congr` - refine setIntegral_congr measurableSet_Ioi (fun t ht ↦ ?_) + -- now the integrand matches `P.h_feq'` on `Ioi 0`, so we can apply `setIntegral_congr_fun` + refine setIntegral_congr_fun measurableSet_Ioi (fun t ht ↦ ?_) simp_rw [P.h_feq' t ht, ← mul_smul] -- some simple `cpow` arithmetic to finish rw [cpow_neg, ofReal_cpow (le_of_lt ht)] @@ -343,7 +343,7 @@ lemma f_modif_aux2 [CompleteSpace E] {s : ℂ} (hs : P.k < re s) : _ = ∫ (x : ℝ) in Ioi 0, (x : ℂ) ^ (s - 1) • ((Ioo 0 1).indicator (fun t : ℝ ↦ P.f₀ - (P.ε * ↑(t ^ (-P.k))) • P.g₀) x + ({1} : Set ℝ).indicator (fun _ ↦ P.f₀ - P.f 1) x) := - setIntegral_congr measurableSet_Ioi (fun x hx ↦ by simp [f_modif_aux1 P hx]) + setIntegral_congr_fun measurableSet_Ioi (fun x hx ↦ by simp [f_modif_aux1 P hx]) _ = ∫ (x : ℝ) in Ioi 0, (x : ℂ) ^ (s - 1) • ((Ioo 0 1).indicator (fun t : ℝ ↦ P.f₀ - (P.ε * ↑(t ^ (-P.k))) • P.g₀) x) := by refine setIntegral_congr_ae measurableSet_Ioi (eventually_of_mem (U := {1}ᶜ) @@ -353,7 +353,7 @@ lemma f_modif_aux2 [CompleteSpace E] {s : ℂ} (hs : P.k < re s) : simp_rw [← indicator_smul, setIntegral_indicator measurableSet_Ioo, inter_eq_right.mpr Ioo_subset_Ioi_self, integral_Ioc_eq_integral_Ioo] _ = ∫ x : ℝ in Ioc 0 1, ((x : ℂ) ^ (s - 1) • P.f₀ - P.ε • (x : ℂ) ^ (s - P.k - 1) • P.g₀) := by - refine setIntegral_congr measurableSet_Ioc (fun x ⟨hx, _⟩ ↦ ?_) + refine setIntegral_congr_fun measurableSet_Ioc (fun x ⟨hx, _⟩ ↦ ?_) rw [ofReal_cpow hx.le, ofReal_neg, smul_sub, ← mul_smul, mul_comm, mul_assoc, mul_smul, mul_comm, ← cpow_add _ _ (ofReal_ne_zero.mpr hx.ne'), ← sub_eq_add_neg, sub_right_comm] _ = (∫ (x : ℝ) in Ioc 0 1, (x : ℂ) ^ (s - 1)) • P.f₀ @@ -427,10 +427,8 @@ theorem functional_equation₀ (s : ℂ) : P.Λ₀ (P.k - s) = P.ε • P.symm. /-- Functional equation formulated for `Λ`. -/ theorem functional_equation (s : ℂ) : P.Λ (P.k - s) = P.ε • P.symm.Λ s := by - have := P.functional_equation₀ s - rw [P.Λ₀_eq, P.symm_Λ₀_eq, sub_sub_cancel] at this - rwa [smul_add, smul_add, ← mul_smul, mul_one_div, ← mul_smul, ← mul_div_assoc, - mul_inv_cancel₀ P.hε, add_assoc, add_comm (_ • _), add_assoc, add_left_inj] at this + linear_combination (norm := module) P.functional_equation₀ s - P.Λ₀_eq (P.k - s) + + congr(P.ε • $(P.symm_Λ₀_eq s)) + congr(($(mul_inv_cancel₀ P.hε) / ((P.k:ℂ) - s)) • P.f₀) /-- The residue of `Λ` at `s = k` is equal to `ε • g₀`. -/ theorem Λ_residue_k : @@ -444,8 +442,7 @@ theorem Λ_residue_k : exact continuousAt_const.div continuousAt_id (ofReal_ne_zero.mpr P.hk.ne') · refine (tendsto_const_nhds.mono_left nhdsWithin_le_nhds).congr' ?_ refine eventually_nhdsWithin_of_forall (fun s (hs : s ≠ P.k) ↦ ?_) - simp_rw [← mul_smul] - congr 1 + match_scalars field_simp [sub_ne_zero.mpr hs.symm] ring @@ -457,7 +454,7 @@ theorem Λ_residue_zero : · exact (continuous_id.smul P.differentiable_Λ₀.continuous).tendsto _ · refine (tendsto_const_nhds.mono_left nhdsWithin_le_nhds).congr' ?_ refine eventually_nhdsWithin_of_forall (fun s (hs : s ≠ 0) ↦ ?_) - simp_rw [← mul_smul] + match_scalars field_simp [sub_ne_zero.mpr hs.symm] · rw [show 𝓝 0 = 𝓝 ((0 : ℂ) • (P.ε / (P.k - 0 : ℂ)) • P.g₀) by rw [zero_smul]] exact (continuousAt_id.smul ((continuousAt_const.div ((continuous_sub_left _).continuousAt) diff --git a/Mathlib/NumberTheory/LSeries/Deriv.lean b/Mathlib/NumberTheory/LSeries/Deriv.lean index d9a355faf2a9f..f8f5726a088aa 100644 --- a/Mathlib/NumberTheory/LSeries/Deriv.lean +++ b/Mathlib/NumberTheory/LSeries/Deriv.lean @@ -20,7 +20,7 @@ import Mathlib.Analysis.Complex.HalfPlane * We prove similar results for iterated derivatives (`LSeries.iteratedDeriv`). * We use this to show that `LSeries f` is holomorphic on the right half-plane of - absolute convergence (`LSeries.analyticOn`). + absolute convergence (`LSeries.analyticOnNhd`). ## Implementation notes @@ -151,6 +151,10 @@ lemma LSeries_differentiableOn (f : ℕ → ℂ) : fun _ hz ↦ (LSeries_hasDerivAt hz).differentiableAt.differentiableWithinAt /-- The L-series of `f` is holomorphic on its open half-plane of absolute convergence. -/ +lemma LSeries_analyticOnNhd (f : ℕ → ℂ) : + AnalyticOnNhd ℂ (LSeries f) {s | abscissaOfAbsConv f < s.re} := + (LSeries_differentiableOn f).analyticOnNhd <| isOpen_re_gt_EReal _ + lemma LSeries_analyticOn (f : ℕ → ℂ) : AnalyticOn ℂ (LSeries f) {s | abscissaOfAbsConv f < s.re} := - (LSeries_differentiableOn f).analyticOn <| isOpen_re_gt_EReal _ + (LSeries_analyticOnNhd f).analyticOn diff --git a/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean b/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean index 7f8d7a14ef207..445256d8910b7 100644 --- a/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean +++ b/Mathlib/NumberTheory/LSeries/MellinEqDirichlet.lean @@ -23,7 +23,7 @@ lemma hasSum_mellin {a : ι → ℂ} {p : ι → ℝ} {F : ℝ → ℂ} {s : ℂ (hF : ∀ t ∈ Ioi 0, HasSum (fun i ↦ a i * rexp (-p i * t)) (F t)) (h_sum : Summable fun i ↦ ‖a i‖ / (p i) ^ s.re) : HasSum (fun i ↦ Gamma s * a i / p i ^ s) (mellin F s) := by - simp_rw [mellin, smul_eq_mul, ← setIntegral_congr measurableSet_Ioi + simp_rw [mellin, smul_eq_mul, ← setIntegral_congr_fun measurableSet_Ioi (fun t ht ↦ congr_arg _ (hF t ht).tsum_eq), ← tsum_mul_left] convert hasSum_integral_of_summable_integral_norm (F := fun i t ↦ t ^ (s - 1) * (a i * rexp (-p i * t))) (fun i ↦ ?_) ?_ using 2 with i @@ -56,7 +56,7 @@ lemma hasSum_mellin {a : ι → ℂ} {p : ι → ℝ} {F : ℝ → ℂ} {s : ℂ have := Real.integral_rpow_mul_exp_neg_mul_Ioi hs hpi simp_rw [← neg_mul (p i), one_div, inv_rpow hpi.le, ← div_eq_inv_mul] at this rw [norm_of_nonneg (integral_nonneg (fun _ ↦ norm_nonneg _)), ← this] - refine setIntegral_congr measurableSet_Ioi (fun t ht ↦ ?_) + refine setIntegral_congr_fun measurableSet_Ioi (fun t ht ↦ ?_) rw [norm_mul, norm_real, Real.norm_eq_abs, Real.abs_exp, Complex.norm_eq_abs, abs_cpow_eq_rpow_re_of_pos ht, sub_re, one_re] diff --git a/Mathlib/NumberTheory/LSeries/ZMod.lean b/Mathlib/NumberTheory/LSeries/ZMod.lean index 66dbde51f1f55..2ef6c910b132d 100644 --- a/Mathlib/NumberTheory/LSeries/ZMod.lean +++ b/Mathlib/NumberTheory/LSeries/ZMod.lean @@ -177,13 +177,13 @@ lemma LFunction_stdAddChar_eq_expZeta (j : ZMod N) (s : ℂ) (hjs : j ≠ 0 ∨ let g := expZeta (toAddCircle j) have hU {u} : u ∈ U ↔ u ≠ 1 ∨ j ≠ 0 := by simp only [mem_ite_univ_right, U]; tauto -- hypotheses for uniqueness of analytic continuation - have hf : AnalyticOn ℂ f U := by - refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo + have hf : AnalyticOnNhd ℂ f U := by + refine DifferentiableOn.analyticOnNhd (fun u hu ↦ ?_) hUo refine (differentiableAt_LFunction _ _ ((hU.mp hu).imp_right fun h ↦ ?_)).differentiableWithinAt simp only [mul_comm j, AddChar.sum_mulShift _ (isPrimitive_stdAddChar _), h, ↓reduceIte, CharP.cast_eq_zero, or_true] - have hg : AnalyticOn ℂ g U := by - refine DifferentiableOn.analyticOn (fun u hu ↦ ?_) hUo + have hg : AnalyticOnNhd ℂ g U := by + refine DifferentiableOn.analyticOnNhd (fun u hu ↦ ?_) hUo refine (differentiableAt_expZeta _ _ ((hU.mp hu).imp_right fun h ↦ ?_)).differentiableWithinAt rwa [ne_eq, toAddCircle_eq_zero] have hUc : IsPreconnected U := by @@ -451,7 +451,7 @@ Functional equation for completed L-functions (even case), valid at all points o theorem completedLFunction_one_sub_even (hΦ : Φ.Even) (s : ℂ) (hs₀ : s ≠ 0 ∨ ∑ j, Φ j = 0) (hs₁ : s ≠ 1 ∨ Φ 0 = 0) : completedLFunction Φ (1 - s) = N ^ (s - 1) * completedLFunction (𝓕 Φ) s := by - -- We prove this using `AnalyticOn.eqOn_of_preconnected_of_eventuallyEq`, so we need to + -- We prove this using `AnalyticOnNhd.eqOn_of_preconnected_of_eventuallyEq`, so we need to -- gather up the ingredients for this big theorem. -- First set up some notations: let F (t) := completedLFunction Φ (1 - t) @@ -477,12 +477,14 @@ theorem completedLFunction_one_sub_even (hΦ : Φ.Even) (s : ℂ) simp [U, Uc, h, h', and_comm] · simp only [rank_real_complex, Nat.one_lt_ofNat] -- Analyticity on U: - have hF : AnalyticOn ℂ F U := by - refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + have hF : AnalyticOnNhd ℂ F U := by + refine DifferentiableOn.analyticOnNhd + (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo refine (differentiableAt_completedLFunction Φ _ ?_ ?_).comp t (differentiableAt_id.const_sub 1) exacts [ht.2.imp_left (sub_ne_zero.mpr ∘ Ne.symm), ht.1.imp_left sub_eq_self.not.mpr] - have hG : AnalyticOn ℂ G U := by - refine DifferentiableOn.analyticOn (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo + have hG : AnalyticOnNhd ℂ G U := by + refine DifferentiableOn.analyticOnNhd + (fun t ht ↦ DifferentiableAt.differentiableWithinAt ?_) hUo apply ((differentiableAt_id.sub_const 1).const_cpow (.inl (NeZero.ne _))).mul apply differentiableAt_completedLFunction _ _ (ht.1.imp_right fun h ↦ dft_apply_zero Φ ▸ h) exact ht.2.imp_right (fun h ↦ by simp only [← dft_apply_zero, dft_dft, neg_zero, h, smul_zero]) @@ -512,7 +514,7 @@ theorem completedLFunction_one_sub_odd (hΦ : Φ.Odd) (s : ℂ) : have hFG : F =ᶠ[𝓝 2] G := by filter_upwards [this] with t ht using completedLFunction_one_sub_of_one_lt_odd hΦ ht -- now apply the big hammer to finish - rw [← analyticOn_univ_iff_differentiable] at hF hG + rw [← analyticOnNhd_univ_iff_differentiable] at hF hG exact congr_fun (hF.eq_of_eventuallyEq hG hFG) s end signed diff --git a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean index 392736e26084d..edf39ca7e1be8 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/GaussEisensteinLemmas.lean @@ -49,9 +49,9 @@ theorem Ico_map_valMinAbs_natAbs_eq_Ico_map_id (p : ℕ) [hp : Fact p.Prime] (a · apply lt_succ_of_le; apply natAbs_valMinAbs_le · rw [natCast_natAbs_valMinAbs] split_ifs - · erw [mul_div_cancel₀ _ hap, valMinAbs_def_pos, val_cast_of_lt (hep hb), + · rw [mul_div_cancel₀ _ hap, valMinAbs_def_pos, val_cast_of_lt (hep hb), if_pos (le_of_lt_succ (mem_Ico.1 hb).2), Int.natAbs_ofNat] - · erw [mul_neg, mul_div_cancel₀ _ hap, natAbs_valMinAbs_neg, valMinAbs_def_pos, + · rw [mul_neg, mul_div_cancel₀ _ hap, natAbs_valMinAbs_neg, valMinAbs_def_pos, val_cast_of_lt (hep hb), if_pos (le_of_lt_succ (mem_Ico.1 hb).2), Int.natAbs_ofNat] exact Multiset.map_eq_map_of_bij_of_nodup _ _ (Finset.nodup _) (Finset.nodup _) (fun x _ => (a * x : ZMod p).valMinAbs.natAbs) hmem diff --git a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean index 74dce799b0ee1..c4b313daf7c59 100644 --- a/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean +++ b/Mathlib/NumberTheory/LegendreSymbol/JacobiSymbol.lean @@ -156,6 +156,10 @@ theorem mul_left (a₁ a₂ : ℤ) (b : ℕ) : J(a₁ * a₂ | b) = J(a₁ | b) (f := fun x ↦ @legendreSym x {out := prime_of_mem_primeFactorsList x.2} a₁) (g := fun x ↦ @legendreSym x {out := prime_of_mem_primeFactorsList x.2} a₂) +#adaptation_note +/-- +After nightly-2024-09-06 we can remove the `_root_` prefixes below. +-/ /-- The symbol `J(a | b)` vanishes iff `a` and `b` are not coprime (assuming `b ≠ 0`). -/ theorem eq_zero_iff_not_coprime {a : ℤ} {b : ℕ} [NeZero b] : J(a | b) = 0 ↔ a.gcd b ≠ 1 := List.prod_eq_zero_iff.trans @@ -165,7 +169,7 @@ theorem eq_zero_iff_not_coprime {a : ℤ} {b : ℕ} [NeZero b] : J(a | b) = 0 -- been deprecated so we replace them with `and_assoc` and `and_comm` simp_rw [legendreSym.eq_zero_iff _ _, intCast_zmod_eq_zero_iff_dvd, mem_primeFactorsList (NeZero.ne b), ← Int.natCast_dvd, Int.natCast_dvd_natCast, exists_prop, - and_assoc, and_comm]) + _root_.and_assoc, _root_.and_comm]) /-- The symbol `J(a | b)` is nonzero when `a` and `b` are coprime. -/ protected theorem ne_zero {a : ℤ} {b : ℕ} (h : a.gcd b = 1) : J(a | b) ≠ 0 := by @@ -214,7 +218,7 @@ theorem sq_one' {a : ℤ} {b : ℕ} (h : a.gcd b = 1) : J(a ^ 2 | b) = 1 := by r /-- The symbol `J(a | b)` depends only on `a` mod `b`. -/ theorem mod_left (a : ℤ) (b : ℕ) : J(a | b) = J(a % b | b) := congr_arg List.prod <| - List.pmap_congr _ + List.pmap_congr_left _ (by -- Porting note: Lean does not synthesize the instance [Fact (Nat.Prime p)] automatically -- (it is needed for `legendreSym.mod` on line 227). Thus, we name the hypothesis @@ -309,7 +313,7 @@ theorem value_at (a : ℤ) {R : Type*} [CommSemiring R] (χ : R →* ℤ) conv_rhs => rw [← prod_primeFactorsList hb.pos.ne', cast_list_prod, map_list_prod χ] rw [jacobiSym, List.map_map, ← List.pmap_eq_map Nat.Prime _ _ fun _ => prime_of_mem_primeFactorsList] - congr 1; apply List.pmap_congr + congr 1; apply List.pmap_congr_left exact fun p h pp _ => hp p pp (hb.ne_two_of_dvd_nat <| dvd_of_mem_primeFactorsList h) /-- If `b` is odd, then `J(-1 | b)` is given by `χ₄ b`. -/ diff --git a/Mathlib/NumberTheory/Liouville/Basic.lean b/Mathlib/NumberTheory/Liouville/Basic.lean index a9e820e8d2cad..04403810047a7 100644 --- a/Mathlib/NumberTheory/Liouville/Basic.lean +++ b/Mathlib/NumberTheory/Liouville/Basic.lean @@ -143,7 +143,7 @@ theorem exists_pos_real_of_irrational_root {α : ℝ} (ha : Irrational α) {f : @exists_one_le_pow_mul_dist ℤ ℕ ℝ _ _ _ (fun y => fR.eval y) α ζ |fR.derivative.eval xm| ?_ z0 (fun y hy => ?_) fun z a hq => ?_ -- 1: the denominators are positive -- essentially by definition; - · exact fun a => one_le_pow_of_one_le ((le_add_iff_nonneg_left 1).mpr a.cast_nonneg) _ + · exact fun a => one_le_pow₀ ((le_add_iff_nonneg_left 1).mpr a.cast_nonneg) -- 2: the polynomial `fR` is Lipschitz at `α` -- as its derivative continuous; · rw [mul_comm] rw [Real.closedBall_eq_Icc] at hy @@ -191,11 +191,11 @@ protected theorem transcendental {x : ℝ} (lx : Liouville x) : Transcendental -- recall, this is a proof by contradiction! refine lt_irrefl ((b : ℝ) ^ f.natDegree * |x - ↑a / ↑b|) ?_ -- clear denominators at `a1` - rw [lt_div_iff' (pow_pos b0 _), pow_add, mul_assoc] at a1 + rw [lt_div_iff₀' (pow_pos b0 _), pow_add, mul_assoc] at a1 -- split the inequality via `1 / A`. refine (?_ : (b : ℝ) ^ f.natDegree * |x - a / b| < 1 / A).trans_le ?_ -- This branch of the proof uses the Liouville condition and the Archimedean property - · refine (lt_div_iff' hA).mpr ?_ + · refine (lt_div_iff₀' hA).mpr ?_ refine lt_of_le_of_lt ?_ a1 gcongr refine hn.le.trans ?_ diff --git a/Mathlib/NumberTheory/Liouville/LiouvilleNumber.lean b/Mathlib/NumberTheory/Liouville/LiouvilleNumber.lean index 2a8dad8fad8f5..49a8325713112 100644 --- a/Mathlib/NumberTheory/Liouville/LiouvilleNumber.lean +++ b/Mathlib/NumberTheory/Liouville/LiouvilleNumber.lean @@ -145,7 +145,7 @@ theorem aux_calc (n : ℕ) {m : ℝ} (hm : 2 ≤ m) : any_goals exact pow_pos (zero_lt_two.trans_le hm) _ -- `2 ≤ m ^ n!` is a consequence of monotonicity of exponentiation at `2 ≤ m`. exact _root_.trans (_root_.trans hm (pow_one _).symm.le) - (pow_right_mono (one_le_two.trans hm) n.factorial_pos) + (pow_right_mono₀ (one_le_two.trans hm) n.factorial_pos) _ = 1 / (m ^ n !) ^ n := congr_arg (1 / ·) (pow_mul m n ! n) /-- An upper estimate on the remainder. This estimate works with `m ∈ ℝ` satisfying `2 ≤ m` and is @@ -183,7 +183,7 @@ theorem liouville_liouvilleNumber {m : ℕ} (hm : 2 ≤ m) : Liouville (liouvill intro n -- the first `n` terms sum to `p / m ^ k!` rcases partialSum_eq_rat (zero_lt_two.trans_le hm) n with ⟨p, hp⟩ - refine ⟨p, m ^ n !, one_lt_pow mZ1 n.factorial_ne_zero, ?_⟩ + refine ⟨p, m ^ n !, one_lt_pow₀ mZ1 n.factorial_ne_zero, ?_⟩ push_cast rw [Nat.cast_pow] at hp -- separate out the sum of the first `n` terms and the rest diff --git a/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean b/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean index 45980956c089e..26c83fc23c3a5 100644 --- a/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean +++ b/Mathlib/NumberTheory/Liouville/LiouvilleWith.lean @@ -53,7 +53,7 @@ theorem liouvilleWith_one (x : ℝ) : LiouvilleWith 1 x := by refine ((eventually_gt_atTop 0).mono fun n hn => ?_).frequently have hn' : (0 : ℝ) < n := by simpa have : x < ↑(⌊x * ↑n⌋ + 1) / ↑n := by - rw [lt_div_iff hn', Int.cast_add, Int.cast_one] + rw [lt_div_iff₀ hn', Int.cast_add, Int.cast_one] exact Int.lt_floor_add_one _ refine ⟨⌊x * n⌋ + 1, this.ne, ?_⟩ rw [abs_sub_comm, abs_of_pos (sub_pos.2 this), rpow_one, sub_lt_iff_lt_add', @@ -100,7 +100,7 @@ theorem frequently_lt_rpow_neg (h : LiouvilleWith p x) (hlt : q < p) : refine (this.and_frequently hC).mono ?_ rintro n ⟨hnC, hn, m, hne, hlt⟩ replace hn : (0 : ℝ) < n := Nat.cast_pos.2 hn - refine ⟨m, hne, hlt.trans <| (div_lt_iff <| rpow_pos_of_pos hn _).2 ?_⟩ + refine ⟨m, hne, hlt.trans <| (div_lt_iff₀ <| rpow_pos_of_pos hn _).2 ?_⟩ rwa [mul_comm, ← rpow_add hn, ← sub_eq_add_neg] /-- The product of a Liouville number and a nonzero rational number is again a Liouville number. -/ diff --git a/Mathlib/NumberTheory/Liouville/Residual.lean b/Mathlib/NumberTheory/Liouville/Residual.lean index 4d72a848d850a..38feb5335e927 100644 --- a/Mathlib/NumberTheory/Liouville/Residual.lean +++ b/Mathlib/NumberTheory/Liouville/Residual.lean @@ -53,7 +53,7 @@ theorem setOf_liouville_eq_irrational_inter_iInter_iUnion : theorem eventually_residual_liouville : ∀ᶠ x in residual ℝ, Liouville x := by rw [Filter.Eventually, setOf_liouville_eq_irrational_inter_iInter_iUnion] refine eventually_residual_irrational.and ?_ - refine residual_of_dense_Gδ ?_ (Rat.denseEmbedding_coe_real.dense.mono ?_) + refine residual_of_dense_Gδ ?_ (Rat.isDenseEmbedding_coe_real.dense.mono ?_) · exact .iInter fun n => IsOpen.isGδ <| isOpen_iUnion fun a => isOpen_iUnion fun b => isOpen_iUnion fun _hb => isOpen_ball · rintro _ ⟨r, rfl⟩ diff --git a/Mathlib/NumberTheory/LucasLehmer.lean b/Mathlib/NumberTheory/LucasLehmer.lean index eed5e96c27d87..fd4fbbd8441a4 100644 --- a/Mathlib/NumberTheory/LucasLehmer.lean +++ b/Mathlib/NumberTheory/LucasLehmer.lean @@ -55,7 +55,7 @@ theorem mersenne_le_mersenne {p q : ℕ} : mersenne p ≤ mersenne q ↔ p ≤ q @[simp] lemma mersenne_odd : ∀ {p : ℕ}, Odd (mersenne p) ↔ p ≠ 0 | 0 => by simp | p + 1 => by - simpa using Nat.Even.sub_odd (one_le_pow_of_one_le one_le_two _) + simpa using Nat.Even.sub_odd (one_le_pow₀ one_le_two) (even_two.pow_of_ne_zero p.succ_ne_zero) odd_one @[simp] theorem mersenne_pos {p : ℕ} : 0 < mersenne p ↔ 0 < p := mersenne_lt_mersenne (p := 0) @@ -87,7 +87,7 @@ theorem one_lt_mersenne {p : ℕ} : 1 < mersenne p ↔ 1 < p := @[simp] theorem succ_mersenne (k : ℕ) : mersenne k + 1 = 2 ^ k := by rw [mersenne, tsub_add_cancel_of_le] - exact one_le_pow_of_one_le (by norm_num) k + exact one_le_pow₀ (by norm_num) namespace LucasLehmer diff --git a/Mathlib/NumberTheory/LucasPrimality.lean b/Mathlib/NumberTheory/LucasPrimality.lean index ac590aca60046..2f2f71e0b2bae 100644 --- a/Mathlib/NumberTheory/LucasPrimality.lean +++ b/Mathlib/NumberTheory/LucasPrimality.lean @@ -7,9 +7,10 @@ import Mathlib.Data.Fintype.Basic import Mathlib.GroupTheory.OrderOfElement import Mathlib.Tactic.Zify import Mathlib.Data.Nat.Totient +import Mathlib.RingTheory.IntegralDomain /-! -# The Lucas test for primes. +# The Lucas test for primes This file implements the Lucas test for primes (not to be confused with the Lucas-Lehmer test for Mersenne primes). A number `a` witnesses that `n` is prime if `a` has order `n-1` in the @@ -18,16 +19,13 @@ and `a^d ≠ 1 (mod n)` for any divisor `d | n - 1`. This test is the basis of t certificate. ## TODO - -- Bonus: Show the reverse implication i.e. if a number is prime then it has a Lucas witness. - Use `Units.IsCyclic` from `RingTheory/IntegralDomain` to show the group is cyclic. - Write a tactic that uses this theorem to generate Pratt primality certificates - Integrate Pratt primality certificates into the norm_num primality verifier ## Implementation notes Note that the proof for `lucas_primality` relies on analyzing the multiplicative group -modulo `p`. Despite this, the theorem still holds vacuously for `p = 0` and `p = 1`: In these +modulo `p`. Despite this, the theorem still holds vacuously for `p = 0` and `p = 1`. In these cases, we can take `q` to be any prime and see that `hd` does not hold, since `a^((p-1)/q)` reduces to `1`. -/ @@ -39,23 +37,37 @@ group must itself have order `p-1`, which only happens when `p` is prime. -/ theorem lucas_primality (p : ℕ) (a : ZMod p) (ha : a ^ (p - 1) = 1) (hd : ∀ q : ℕ, q.Prime → q ∣ p - 1 → a ^ ((p - 1) / q) ≠ 1) : p.Prime := by - have h0 : p ≠ 0 := by - rintro ⟨⟩ - exact hd 2 Nat.prime_two (dvd_zero _) (pow_zero _) - have h1 : p ≠ 1 := by - rintro ⟨⟩ - exact hd 2 Nat.prime_two (dvd_zero _) (pow_zero _) - have hp1 : 1 < p := lt_of_le_of_ne h0.bot_lt h1.symm - have order_of_a : orderOf a = p - 1 := by - apply orderOf_eq_of_pow_and_pow_div_prime _ ha hd - exact tsub_pos_of_lt hp1 - haveI : NeZero p := ⟨h0⟩ + have h : p ≠ 0 ∧ p ≠ 1 := by + constructor <;> rintro rfl <;> exact hd 2 Nat.prime_two (dvd_zero _) (pow_zero _) + have hp1 : 1 < p := Nat.one_lt_iff_ne_zero_and_ne_one.2 h + have : NeZero p := ⟨h.1⟩ rw [Nat.prime_iff_card_units] - -- Prove cardinality of `Units` of `ZMod p` is both `≤ p-1` and `≥ p-1` - refine le_antisymm (Nat.card_units_zmod_lt_sub_one hp1) ?_ - have hp' : p - 2 + 1 = p - 1 := tsub_add_eq_add_tsub hp1 - let a' : (ZMod p)ˣ := Units.mkOfMulEqOne a (a ^ (p - 2)) (by rw [← pow_succ', hp', ha]) - calc - p - 1 = orderOf a := order_of_a.symm - _ = orderOf a' := (orderOf_injective (Units.coeHom (ZMod p)) Units.ext a') + apply (Nat.card_units_zmod_lt_sub_one hp1).antisymm + let a' : (ZMod p)ˣ := Units.mkOfMulEqOne a _ (by rwa [← pow_succ', tsub_add_eq_add_tsub hp1]) + calc p - 1 = orderOf a := (orderOf_eq_of_pow_and_pow_div_prime (tsub_pos_of_lt hp1) ha hd).symm + _ = orderOf a' := orderOf_injective (Units.coeHom _) Units.ext a' _ ≤ Fintype.card (ZMod p)ˣ := orderOf_le_card_univ + +/-- If `p` is prime, then there exists an `a` such that `a^(p-1) = 1 mod p` +and `a^((p-1)/q) ≠ 1 mod p` for all prime factors `q` of `p-1`. +The multiplicative group mod `p` is cyclic, so `a` can be any generator of the group +(which must have order `p-1`). +-/ +theorem reverse_lucas_primality (p : ℕ) (hP : p.Prime) : + ∃ a : ZMod p, a ^ (p - 1) = 1 ∧ ∀ q : ℕ, q.Prime → q ∣ p - 1 → a ^ ((p - 1) / q) ≠ 1 := by + have : Fact p.Prime := ⟨hP⟩ + obtain ⟨g, hg⟩ := IsCyclic.exists_generator (α := (ZMod p)ˣ) + have h1 : orderOf g = p - 1 := by + rwa [orderOf_eq_card_of_forall_mem_zpowers hg, ← Nat.prime_iff_card_units] + have h2 := tsub_pos_iff_lt.2 hP.one_lt + rw [← orderOf_injective (Units.coeHom _) Units.ext _, orderOf_eq_iff h2] at h1 + refine ⟨g, h1.1, fun q hq hqd ↦ ?_⟩ + replace hq := hq.one_lt + exact h1.2 _ (Nat.div_lt_self h2 hq) (Nat.div_pos (Nat.le_of_dvd h2 hqd) (zero_lt_one.trans hq)) + +/-- A number `p` is prime if and only if there exists an `a` such that +`a^(p-1) = 1 mod p` and `a^((p-1)/q) ≠ 1 mod p` for all prime factors `q` of `p-1`. +-/ +theorem lucas_primality_iff (p : ℕ) : p.Prime ↔ + ∃ a : ZMod p, a ^ (p - 1) = 1 ∧ ∀ q : ℕ, q.Prime → q ∣ p - 1 → a ^ ((p - 1) / q) ≠ 1 := + ⟨reverse_lucas_primality p, fun ⟨a, ⟨ha, hb⟩⟩ ↦ lucas_primality p a ha hb⟩ diff --git a/Mathlib/NumberTheory/Modular.lean b/Mathlib/NumberTheory/Modular.lean index 812b9760b6b67..d27a687df5826 100644 --- a/Mathlib/NumberTheory/Modular.lean +++ b/Mathlib/NumberTheory/Modular.lean @@ -351,13 +351,13 @@ theorem g_eq_of_c_eq_one (hc : (↑ₘg) 1 0 = 1) : g = T ^ (↑ₘg) 0 0 * S * /-- If `1 < |z|`, then `|S • z| < 1`. -/ theorem normSq_S_smul_lt_one (h : 1 < normSq z) : normSq ↑(S • z) < 1 := by - simpa [coe_S, num, denom] using (inv_lt_inv z.normSq_pos zero_lt_one).mpr h + simpa [coe_S, num, denom] using (inv_lt_inv₀ z.normSq_pos zero_lt_one).mpr h /-- If `|z| < 1`, then applying `S` strictly decreases `im`. -/ theorem im_lt_im_S_smul (h : normSq z < 1) : z.im < (S • z).im := by have : z.im < z.im / normSq (z : ℂ) := by have imz : 0 < z.im := im_pos z - apply (lt_div_iff z.normSq_pos).mpr + apply (lt_div_iff₀ z.normSq_pos).mpr nlinarith convert this simp only [ModularGroup.im_smul_eq_div_normSq] @@ -380,7 +380,7 @@ scoped[Modular] notation "𝒟ᵒ" => ModularGroup.fdo open scoped Modular theorem abs_two_mul_re_lt_one_of_mem_fdo (h : z ∈ 𝒟ᵒ) : |2 * z.re| < 1 := by - rw [abs_mul, abs_two, ← lt_div_iff' (zero_lt_two' ℝ)] + rw [abs_mul, abs_two, ← lt_div_iff₀' (zero_lt_two' ℝ)] exact h.2 theorem three_lt_four_mul_im_sq_of_mem_fdo (h : z ∈ 𝒟ᵒ) : 3 < 4 * z.im ^ 2 := by @@ -465,7 +465,7 @@ theorem abs_c_le_one (hz : z ∈ 𝒟ᵒ) (hg : g • z ∈ 𝒟ᵒ) : |(↑ₘg (by linarith) (by linarith)) hc have h₂ : (c * z.im) ^ 4 / normSq (denom (↑g) z) ^ 2 ≤ 1 := - div_le_one_of_le + div_le_one_of_le₀ (pow_four_le_pow_two_of_pow_two_le (UpperHalfPlane.c_mul_im_sq_le_normSq_denom z g)) (sq_nonneg _) let nsq := normSq (denom g z) diff --git a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean index 2ff96d352b04b..7268d68dd4275 100644 --- a/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean +++ b/Mathlib/NumberTheory/ModularForms/EisensteinSeries/UniformConvergence.lean @@ -78,7 +78,7 @@ lemma r_lower_bound_on_verticalStrip {A B : ℝ} (h : 0 < B) (hz : z ∈ vertica apply min_le_min hz.2 rw [Real.sqrt_le_sqrt_iff (by apply (r1_pos z).le)] simp only [r1_eq, div_pow, one_div] - rw [inv_le_inv (by positivity) (by positivity), add_le_add_iff_right] + rw [inv_le_inv₀ (by positivity) (by positivity), add_le_add_iff_right] apply div_le_div (sq_nonneg _) _ (by positivity) (pow_le_pow_left h.le hz.2 2) simpa only [even_two.pow_abs] using pow_le_pow_left (abs_nonneg _) hz.1 2 diff --git a/Mathlib/NumberTheory/NumberField/Basic.lean b/Mathlib/NumberTheory/NumberField/Basic.lean index fa4d279501117..cd142c881c370 100644 --- a/Mathlib/NumberTheory/NumberField/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Basic.lean @@ -134,22 +134,55 @@ lemma mk_eq_mk (x y : K) (hx hy) : (⟨x, hx⟩ : 𝓞 K) = ⟨y, hy⟩ ↔ x = @[simp] lemma neg_mk (x : K) (hx) : (-⟨x, hx⟩ : 𝓞 K) = ⟨-x, neg_mem hx⟩ := rfl +/-- The ring homomorphism `(𝓞 K) →+* (𝓞 L)` given by restricting a ring homomorphism + `f : K →+* L` to `𝓞 K`. -/ +def mapRingHom {K L F : Type*} [Field K] [Field L] [FunLike F K L] + [RingHomClass F K L] (f : F) : (𝓞 K) →+* (𝓞 L) where + toFun k := ⟨f k.val, map_isIntegral_int f k.2⟩ + map_zero' := by ext; simp only [map_mk, map_zero] + map_one' := by ext; simp only [map_mk, map_one] + map_add' x y:= by ext; simp only [map_mk, map_add] + map_mul' x y := by ext; simp only [map_mk, map_mul] + +/-- The ring isomorphsim `(𝓞 K) ≃+* (𝓞 L)` given by restricting + a ring isomorphsim `e : K ≃+* L` to `𝓞 K`. -/ +def mapRingEquiv {K L E : Type*} [Field K] [Field L] [EquivLike E K L] + [RingEquivClass E K L] (e : E) : (𝓞 K) ≃+* (𝓞 L) := + RingEquiv.ofRingHom (mapRingHom e) (mapRingHom (e : K ≃+* L).symm) + (RingHom.ext fun x => ext (EquivLike.right_inv e x.1)) + (RingHom.ext fun x => ext (EquivLike.left_inv e x.1)) + end RingOfIntegers /-- Given an algebra between two fields, create an algebra between their two rings of integers. -/ instance inst_ringOfIntegersAlgebra [Algebra K L] : Algebra (𝓞 K) (𝓞 L) := - RingHom.toAlgebra - { toFun := fun k => ⟨algebraMap K L (algebraMap _ K k), IsIntegral.algebraMap k.2⟩ - map_zero' := by ext; simp only [RingOfIntegers.map_mk, map_zero] - map_one' := by ext; simp only [RingOfIntegers.map_mk, map_one] - map_add' := fun x y => by ext; simp only [RingOfIntegers.map_mk, map_add] - map_mul' := fun x y => by ext; simp only [RingOfIntegers.map_mk, map_mul] } + (RingOfIntegers.mapRingHom (algebraMap K L)).toAlgebra -- diamond at `reducible_and_instances` #10906 example : Algebra.id (𝓞 K) = inst_ringOfIntegersAlgebra K K := rfl namespace RingOfIntegers +/-- The algebra homomorphism `(𝓞 K) →ₐ[𝓞 k] (𝓞 L)` given by restricting a algebra homomorphism + `f : K →ₐ[k] L` to `𝓞 K`. -/ +def mapAlgHom {k K L F : Type*} [Field k] [Field K] [Field L] [Algebra k K] + [Algebra k L] [FunLike F K L] [AlgHomClass F k K L] (f : F) : (𝓞 K) →ₐ[𝓞 k] (𝓞 L) where + toRingHom := mapRingHom f + commutes' x := SetCoe.ext (AlgHomClass.commutes ((f : K →ₐ[k] L).restrictScalars (𝓞 k)) x) + +/-- The isomorphism of algebras `(𝓞 K) ≃ₐ[𝓞 k] (𝓞 L)` given by restricting + an isomorphism of algebras `e : K ≃ₐ[k] L` to `𝓞 K`. -/ +def mapAlgEquiv {k K L E : Type*} [Field k] [Field K] [Field L] [Algebra k K] + [Algebra k L] [EquivLike E K L] [AlgEquivClass E k K L] (e : E) : (𝓞 K) ≃ₐ[𝓞 k] (𝓞 L) := + AlgEquiv.ofAlgHom (mapAlgHom e) (mapAlgHom (e : K ≃ₐ[k] L).symm) + (AlgHom.ext fun x => ext (EquivLike.right_inv e x.1)) + (AlgHom.ext fun x => ext (EquivLike.left_inv e x.1)) + +instance inst_isScalarTower (k K L : Type*) [Field k] [Field K] [Field L] + [Algebra k K] [Algebra k L] [Algebra K L] [IsScalarTower k K L] : + IsScalarTower (𝓞 k) (𝓞 K) (𝓞 L) := + IsScalarTower.of_algHom (mapAlgHom (IsScalarTower.toAlgHom k K L)) + variable {K} /-- The canonical map from `𝓞 K` to `K` is injective. @@ -274,7 +307,7 @@ theorem mem_span_integralBasis {x : K} : rw [integralBasis, Basis.localizationLocalization_span, LinearMap.mem_range, IsScalarTower.coe_toAlgHom', RingHom.mem_range] -theorem RingOfIntegers.rank : FiniteDimensional.finrank ℤ (𝓞 K) = FiniteDimensional.finrank ℚ K := +theorem RingOfIntegers.rank : Module.finrank ℤ (𝓞 K) = Module.finrank ℚ K := IsIntegralClosure.rank ℤ ℚ K (𝓞 K) end NumberField diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean index 8e0ff1ca52eca..c62e465bc30d5 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/Basic.lean @@ -100,7 +100,7 @@ theorem integerLattice.inter_ball_finite [NumberField K] (r : ℝ) : · rintro ⟨x, ⟨hx1, hx2⟩, rfl⟩ exact ⟨⟨x, ⟨⟨x, hx1⟩, rfl⟩, rfl⟩, (heq x).mpr hx2⟩ -open Module Fintype FiniteDimensional +open Module Fintype Module /-- A `ℂ`-basis of `ℂ^n` that is also a `ℤ`-basis of the `integerLattice`. -/ noncomputable def latticeBasis [NumberField K] : @@ -176,7 +176,7 @@ end NumberField.canonicalEmbedding namespace NumberField.mixedEmbedding -open NumberField.InfinitePlace FiniteDimensional Finset +open NumberField.InfinitePlace Module Finset /-- The mixed space `ℝ^r₁ × ℂ^r₂` with `(r₁, r₂)` the signature of `K`. -/ abbrev mixedSpace := @@ -491,7 +491,7 @@ def indexEquiv : (index K) ≃ (K →+* ℂ) := by · exact ⟨Sum.inr ⟨InfinitePlace.mkComplex ⟨φ, hφ⟩, 1⟩, by simp [(embedding_mk_eq φ).resolve_left hw]⟩ · rw [Embeddings.card, ← mixedEmbedding.finrank K, - ← FiniteDimensional.finrank_eq_card_basis (stdBasis K)] + ← Module.finrank_eq_card_basis (stdBasis K)] variable {K} @@ -613,7 +613,7 @@ theorem mem_span_latticeBasis (x : (mixedSpace K)) : rfl theorem span_latticeBasis : - (Submodule.span ℤ (Set.range (latticeBasis K))) = (mixedEmbedding.integerLattice K) := + Submodule.span ℤ (Set.range (latticeBasis K)) = mixedEmbedding.integerLattice K := Submodule.ext_iff.mpr (mem_span_latticeBasis K) instance : DiscreteTopology (mixedEmbedding.integerLattice K) := by diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean index be75dd9a3e776..36a06aabe738b 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/ConvexBody.lean @@ -40,7 +40,7 @@ variable (K : Type*) [Field K] namespace NumberField.mixedEmbedding -open NumberField NumberField.InfinitePlace FiniteDimensional +open NumberField NumberField.InfinitePlace Module section convexBodyLT @@ -94,8 +94,7 @@ theorem convexBodyLTFactor_ne_zero : convexBodyLTFactor K ≠ 0 := mul_ne_zero (pow_ne_zero _ two_ne_zero) (pow_ne_zero _ pi_ne_zero) theorem one_le_convexBodyLTFactor : 1 ≤ convexBodyLTFactor K := - one_le_mul (one_le_pow_of_one_le one_le_two _) - (one_le_pow_of_one_le (le_trans one_le_two Real.two_le_pi) _) + one_le_mul (one_le_pow₀ one_le_two) (one_le_pow₀ (one_le_two.trans Real.two_le_pi)) /-- The volume of `(ConvexBodyLt K f)` where `convexBodyLT K f` is the set of points `x` such that `‖x w‖ < f w` for all infinite places `w`. -/ @@ -212,8 +211,7 @@ theorem convexBodyLT'Factor_ne_zero : convexBodyLT'Factor K ≠ 0 := mul_ne_zero (pow_ne_zero _ two_ne_zero) (pow_ne_zero _ pi_ne_zero) theorem one_le_convexBodyLT'Factor : 1 ≤ convexBodyLT'Factor K := - one_le_mul (one_le_pow_of_one_le one_le_two _) - (one_le_pow_of_one_le (le_trans one_le_two Real.two_le_pi) _) + one_le_mul (one_le_pow₀ one_le_two) (one_le_pow₀ (one_le_two.trans Real.two_le_pi)) theorem convexBodyLT'_volume : volume (convexBodyLT' K f w₀) = convexBodyLT'Factor K * ∏ w, (f w) ^ (mult w) := by @@ -405,7 +403,7 @@ theorem convexBodySum_volume : convert addHaar_smul volume B (convexBodySum K 1) · simp_rw [← Set.preimage_smul_inv₀ (ne_of_gt hB), Set.preimage_setOf_eq, convexBodySumFun, normAtPlace_smul, abs_inv, abs_eq_self.mpr (le_of_lt hB), ← mul_assoc, mul_comm, mul_assoc, - ← Finset.mul_sum, inv_mul_le_iff hB, mul_one] + ← Finset.mul_sum, inv_mul_le_iff₀ hB, mul_one] · rw [abs_pow, ofReal_pow (abs_nonneg _), abs_eq_self.mpr (le_of_lt hB), mixedEmbedding.finrank] · exact this.symm @@ -452,7 +450,7 @@ end convexBodySum section minkowski open scoped Classical -open MeasureTheory MeasureTheory.Measure FiniteDimensional ZSpan Real Submodule +open MeasureTheory MeasureTheory.Measure Module ZSpan Real Submodule open scoped ENNReal NNReal nonZeroDivisors IntermediateField diff --git a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean index 911bb6fc07048..419b0f6e623c0 100644 --- a/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean +++ b/Mathlib/NumberTheory/NumberField/CanonicalEmbedding/FundamentalCone.lean @@ -87,7 +87,7 @@ end UnitSMul noncomputable section logMap -open NumberField.Units NumberField.Units.dirichletUnitTheorem FiniteDimensional +open NumberField.Units NumberField.Units.dirichletUnitTheorem Module variable [NumberField K] {K} @@ -250,22 +250,22 @@ variable (K) in /-- The set of images by `mixedEmbedding` of algebraic integers of `K` contained in the fundamental cone. -/ def integralPoint : Set (mixedSpace K) := - fundamentalCone K ∩ (mixedEmbedding.integerLattice K) + fundamentalCone K ∩ mixedEmbedding.integerLattice K theorem mem_integralPoint {a : mixedSpace K} : - a ∈ integralPoint K ↔ a ∈ fundamentalCone K ∧ ∃ x : (𝓞 K), mixedEmbedding K x = a:= by + a ∈ integralPoint K ↔ a ∈ fundamentalCone K ∧ ∃ x : 𝓞 K, mixedEmbedding K x = a := by simp only [integralPoint, Set.mem_inter_iff, SetLike.mem_coe, LinearMap.mem_range, AlgHom.toLinearMap_apply, RingHom.toIntAlgHom_coe, RingHom.coe_comp, Function.comp_apply] /-- If `a` is an integral point, then there is a *unique* algebraic integer in `𝓞 K` such that `mixedEmbedding K x = a`. -/ theorem exists_unique_preimage_of_integralPoint {a : mixedSpace K} (ha : a ∈ integralPoint K) : - ∃! x : (𝓞 K), mixedEmbedding K x = a := by + ∃! x : 𝓞 K, mixedEmbedding K x = a := by obtain ⟨_, ⟨x, rfl⟩⟩ := mem_integralPoint.mp ha - refine Function.Injective.exists_unique_of_mem_range ?_ (Set.mem_range_self x) + refine Function.Injective.existsUnique_of_mem_range ?_ (Set.mem_range_self x) exact (mixedEmbedding_injective K).comp RingOfIntegers.coe_injective -theorem integralPoint_ne_zero (a : integralPoint K) : (a : mixedSpace K) ≠ 0 := by +theorem integralPoint_ne_zero (a : integralPoint K) : (a : mixedSpace K) ≠ 0 := by by_contra! exact a.prop.1.2 (this.symm ▸ mixedEmbedding.norm.map_zero') diff --git a/Mathlib/NumberTheory/NumberField/ClassNumber.lean b/Mathlib/NumberTheory/NumberField/ClassNumber.lean index c6726b41347b6..06ed53e2b5316 100644 --- a/Mathlib/NumberTheory/NumberField/ClassNumber.lean +++ b/Mathlib/NumberTheory/NumberField/ClassNumber.lean @@ -41,7 +41,7 @@ variable {K} theorem classNumber_eq_one_iff : classNumber K = 1 ↔ IsPrincipalIdealRing (𝓞 K) := card_classGroup_eq_one_iff -open FiniteDimensional NumberField.InfinitePlace +open Module NumberField.InfinitePlace open scoped nonZeroDivisors Real @@ -75,7 +75,7 @@ theorem _root_.RingOfIntegers.isPrincipalIdealRing_of_abs_discr_lt ((finrank ℚ K) ^ (finrank ℚ K) / (finrank ℚ K).factorial)) ^ 2) : IsPrincipalIdealRing (𝓞 K) := by have : 0 < finrank ℚ K := finrank_pos -- Lean needs to know that for positivity to succeed - rw [← Real.sqrt_lt (by positivity) (by positivity), mul_assoc, ← inv_mul_lt_iff' (by positivity), + rw [← Real.sqrt_lt (by positivity) (by positivity), mul_assoc, ← inv_mul_lt_iff₀' (by positivity), mul_inv, ← inv_pow, inv_div, inv_div, mul_assoc, Int.cast_abs] at h rw [← classNumber_eq_one_iff, classNumber, Fintype.card_eq_one_iff] refine ⟨1, fun C ↦ ?_⟩ diff --git a/Mathlib/NumberTheory/NumberField/Discriminant.lean b/Mathlib/NumberTheory/NumberField/Discriminant.lean index 0800c7995ee2d..52a08d5551c4a 100644 --- a/Mathlib/NumberTheory/NumberField/Discriminant.lean +++ b/Mathlib/NumberTheory/NumberField/Discriminant.lean @@ -32,7 +32,7 @@ number field, discriminant namespace NumberField -open FiniteDimensional NumberField NumberField.InfinitePlace Matrix +open Module NumberField NumberField.InfinitePlace Matrix open scoped Classical Real nonZeroDivisors @@ -173,7 +173,7 @@ theorem abs_discr_ge (h : 1 < finrank ℚ K) : rw [← Algebra.coe_norm_int, ← Int.cast_one, ← Int.cast_abs, Rat.cast_intCast, Int.cast_le] exact Int.one_le_abs (Algebra.norm_ne_zero_iff.mpr h_nz) replace h_bd := le_trans h_nm h_bd - rw [← inv_mul_le_iff (by positivity), inv_div, mul_one, Real.le_sqrt (by positivity) + rw [← inv_mul_le_iff₀ (by positivity), inv_div, mul_one, Real.le_sqrt (by positivity) (by positivity), ← Int.cast_abs, div_pow, mul_pow, ← pow_mul, ← pow_mul] at h_bd refine le_trans ?_ h_bd -- The sequence `a n` is a lower bound for `|discr K|`. We prove below by induction an uniform @@ -277,7 +277,7 @@ theorem rank_le_rankOfDiscrBdd : refine fun h ↦ discr_ne_zero K ?_ rwa [h, Nat.cast_zero, abs_nonpos_iff] at hK have h₂ : 1 < 3 * π / 4 := by - rw [_root_.lt_div_iff (by positivity), ← _root_.div_lt_iff' (by positivity), one_mul] + rw [_root_.lt_div_iff₀ (by positivity), ← _root_.div_lt_iff₀' (by positivity), one_mul] linarith [Real.pi_gt_three] obtain h | h := lt_or_le 1 (finrank ℚ K) · apply le_max_of_le_right @@ -307,7 +307,7 @@ theorem minkowskiBound_lt_boundOfDiscBdd : minkowskiBound K ↑1 < boundOfDiscBd ENNReal.ofReal_one, one_mul, mixedEmbedding.finrank, volume_fundamentalDomain_latticeBasis, coe_mul, ENNReal.coe_pow, coe_ofNat, show sqrt N = (1 : ℝ≥0∞) * sqrt N by rw [one_mul]] gcongr - · exact pow_le_one _ (by positivity) (by norm_num) + · exact pow_le_one₀ (by positivity) (by norm_num) · rwa [sqrt_le_sqrt, ← NNReal.coe_le_coe, coe_nnnorm, Int.norm_eq_abs, ← Int.cast_abs, NNReal.coe_natCast, ← Int.cast_natCast, Int.cast_le] · exact one_le_two @@ -337,6 +337,8 @@ theorem finite_of_discr_bdd_of_isReal : (Set.finite_Icc (-C : ℤ) C)) (fun ⟨K, hK₀⟩ ⟨hK₁, hK₂⟩ ↦ ?_) -- We now need to prove that each field is generated by an element of the union of the rootset simp_rw [Set.mem_iUnion] + -- this is purely an optimization + have : CharZero K := SubsemiringClass.instCharZero K haveI : NumberField K := @NumberField.mk _ _ inferInstance hK₀ obtain ⟨w₀, hw₀⟩ := hK₁ suffices minkowskiBound K ↑1 < (convexBodyLTFactor K) * B by @@ -360,12 +362,15 @@ theorem finite_of_discr_bdd_of_isReal : · refine mem_rootSet.mpr ⟨minpoly.ne_zero hx, ?_⟩ exact (aeval_algebraMap_eq_zero_iff _ _ _).mpr (minpoly.aeval ℤ (x : K)) · rw [← (IntermediateField.lift_injective _).eq_iff, eq_comm] at hx₁ - convert hx₁ <;> simp + convert hx₁ + · simp only [IntermediateField.lift_top] + · simp only [IntermediateField.lift_adjoin, Set.image_singleton] have := one_le_convexBodyLTFactor K convert lt_of_le_of_lt (mul_right_mono (coe_le_coe.mpr this)) (ENNReal.mul_lt_mul_left' (by positivity) coe_ne_top (minkowskiBound_lt_boundOfDiscBdd hK₂)) simp_rw [ENNReal.coe_one, one_mul] + theorem finite_of_discr_bdd_of_isComplex : {K : { F : IntermediateField ℚ A // FiniteDimensional ℚ F} | haveI : NumberField K := @NumberField.mk _ _ inferInstance K.prop @@ -380,6 +385,8 @@ theorem finite_of_discr_bdd_of_isComplex : (Set.finite_Icc (-C : ℤ) C)) (fun ⟨K, hK₀⟩ ⟨hK₁, hK₂⟩ ↦ ?_) -- We now need to prove that each field is generated by an element of the union of the rootset simp_rw [Set.mem_iUnion] + -- this is purely an optimization + have : CharZero K := SubsemiringClass.instCharZero K haveI : NumberField K := @NumberField.mk _ _ inferInstance hK₀ obtain ⟨w₀, hw₀⟩ := hK₁ suffices minkowskiBound K ↑1 < (convexBodyLT'Factor K) * boundOfDiscBdd N by @@ -404,7 +411,9 @@ theorem finite_of_discr_bdd_of_isComplex : · refine mem_rootSet.mpr ⟨minpoly.ne_zero hx, ?_⟩ exact (aeval_algebraMap_eq_zero_iff _ _ _).mpr (minpoly.aeval ℤ (x : K)) · rw [← (IntermediateField.lift_injective _).eq_iff, eq_comm] at hx₁ - convert hx₁ <;> simp + convert hx₁ + · simp only [IntermediateField.lift_top] + · simp only [IntermediateField.lift_adjoin, Set.image_singleton] have := one_le_convexBodyLT'Factor K convert lt_of_le_of_lt (mul_right_mono (coe_le_coe.mpr this)) (ENNReal.mul_lt_mul_left' (by positivity) coe_ne_top (minkowskiBound_lt_boundOfDiscBdd hK₂)) @@ -419,6 +428,8 @@ theorem _root_.NumberField.finite_of_discr_bdd : refine Set.Finite.subset (Set.Finite.union (finite_of_discr_bdd_of_isReal A N) (finite_of_discr_bdd_of_isComplex A N)) ?_ rintro ⟨K, hK₀⟩ hK₁ + -- this is purely an optimization + have : CharZero K := SubsemiringClass.instCharZero K haveI : NumberField K := @NumberField.mk _ _ inferInstance hK₀ obtain ⟨w₀⟩ := (inferInstance : Nonempty (InfinitePlace K)) by_cases hw₀ : IsReal w₀ diff --git a/Mathlib/NumberTheory/NumberField/Embeddings.lean b/Mathlib/NumberTheory/NumberField/Embeddings.lean index d2421c79c769e..d713d6bce1442 100644 --- a/Mathlib/NumberTheory/NumberField/Embeddings.lean +++ b/Mathlib/NumberTheory/NumberField/Embeddings.lean @@ -38,7 +38,7 @@ namespace NumberField.Embeddings section Fintype -open FiniteDimensional +open Module variable (K : Type*) [Field K] [NumberField K] variable (A : Type*) [Field A] [CharZero A] @@ -55,7 +55,7 @@ theorem card : Fintype.card (K →+* A) = finrank ℚ K := by instance : Nonempty (K →+* A) := by rw [← Fintype.card_pos_iff, NumberField.Embeddings.card K A] - exact FiniteDimensional.finrank_pos + exact Module.finrank_pos end Fintype @@ -78,7 +78,7 @@ end Roots section Bounded -open FiniteDimensional Polynomial Set +open Module Polynomial Set variable {K : Type*} [Field K] [NumberField K] variable {A : Type*} [NormedField A] [IsAlgClosed A] [NormedAlgebra ℚ A] @@ -259,7 +259,7 @@ open NumberField instance {K : Type*} [Field K] : FunLike (InfinitePlace K) K ℝ where coe w x := w.1 x - coe_injective' := fun _ _ h => Subtype.eq (AbsoluteValue.ext fun x => congr_fun h x) + coe_injective' _ _ h := Subtype.eq (AbsoluteValue.ext fun x => congr_fun h x) instance : MonoidWithZeroHomClass (InfinitePlace K) K ℝ where map_mul w _ _ := w.1.map_mul _ _ @@ -450,7 +450,7 @@ noncomputable instance NumberField.InfinitePlace.fintype [NumberField K] : Fintype (InfinitePlace K) := Set.fintypeRange _ theorem sum_mult_eq [NumberField K] : - ∑ w : InfinitePlace K, mult w = FiniteDimensional.finrank ℚ K := by + ∑ w : InfinitePlace K, mult w = Module.finrank ℚ K := by rw [← Embeddings.card K ℂ, Fintype.card, Finset.card_eq_sum_ones, ← Finset.univ.sum_fiberwise (fun φ => InfinitePlace.mk φ)] exact Finset.sum_congr rfl @@ -489,7 +489,7 @@ theorem prod_eq_abs_norm (x : K) : convert (congr_arg Complex.abs (@Algebra.norm_eq_prod_embeddings ℚ _ _ _ _ ℂ _ _ _ _ _ x)).symm · rw [map_prod, ← Fintype.prod_equiv RingHom.equivRatAlgHom (fun f => Complex.abs (f x)) (fun φ => Complex.abs (φ x)) fun _ => by simp [RingHom.equivRatAlgHom_apply]; rfl] - rw [← Finset.prod_fiberwise Finset.univ (fun φ => mk φ) (fun φ => Complex.abs (φ x))] + rw [← Finset.prod_fiberwise Finset.univ mk (fun φ => Complex.abs (φ x))] have : ∀ w : InfinitePlace K, ∀ φ ∈ Finset.filter (fun a ↦ mk a = w) Finset.univ, Complex.abs (φ x) = w x := by intro _ _ hφ @@ -505,7 +505,7 @@ theorem one_le_of_lt_one {w : InfinitePlace K} {a : (𝓞 K)} (ha : a ≠ 0) rw [← InfinitePlace.prod_eq_abs_norm, ← Finset.prod_const_one] refine Finset.prod_lt_prod_of_nonempty (fun _ _ ↦ ?_) (fun z _ ↦ ?_) Finset.univ_nonempty · exact pow_pos (pos_iff.mpr ((Subalgebra.coe_eq_zero _).not.mpr ha)) _ - · refine pow_lt_one (apply_nonneg _ _) ?_ (by rw [mult]; split_ifs <;> norm_num) + · refine pow_lt_one₀ (apply_nonneg _ _) ?_ (by rw [mult]; split_ifs <;> norm_num) by_cases hz : z = w · rwa [hz] · exact h hz @@ -546,7 +546,7 @@ theorem _root_.NumberField.adjoin_eq_top_of_infinitePlace_lt {x : 𝓞 K} {w : I end NumberField -open Fintype FiniteDimensional +open Fintype Module variable (K) @@ -1024,12 +1024,12 @@ lemma IsUnramifiedAtInfinitePlaces_of_odd_card_aut [IsGalois k K] [FiniteDimensi ⟨fun _ ↦ not_not.mp (Nat.not_even_iff_odd.2 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 := + (h : Odd (Module.finrank k K)) : IsUnramifiedAtInfinitePlaces k K := ⟨fun _ ↦ not_not.mp (Nat.not_even_iff_odd.2 h ∘ InfinitePlace.even_finrank_of_not_isUnramified)⟩ variable (k K) -open FiniteDimensional in +open Module 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 diff --git a/Mathlib/NumberTheory/NumberField/EquivReindex.lean b/Mathlib/NumberTheory/NumberField/EquivReindex.lean index 67fc4926a8307..0226ce9f8e5d5 100644 --- a/Mathlib/NumberTheory/NumberField/EquivReindex.lean +++ b/Mathlib/NumberTheory/NumberField/EquivReindex.lean @@ -21,7 +21,7 @@ namespace NumberField noncomputable section -open Module.Free FiniteDimensional canonicalEmbedding Matrix Finset +open Module.Free Module canonicalEmbedding Matrix Finset /-- An equivalence between the set of embeddings of `K` into `ℂ` and the index set of the chosen basis of the ring of integers of `K`. -/ diff --git a/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean index 3d5cc80dab357..1444de4b7e903 100644 --- a/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean +++ b/Mathlib/NumberTheory/NumberField/FractionalIdeal.lean @@ -61,7 +61,7 @@ instance (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) : · 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 ⊢ + · simp_rw [LinearMap.coe_restrictScalars, Submodule.coe_subtype] at h ⊢ rw [← h] simp only [Submonoid.mk_smul, zsmul_eq_mul, Int.cast_mul, Int.cast_natCast, algebraMap_int_eq, eq_intCast, map_intCast] @@ -89,7 +89,7 @@ theorem mem_span_basisOfFractionalIdeal {I : (FractionalIdeal (𝓞 K)⁰ K)ˣ} rw [basisOfFractionalIdeal, (fractionalIdealBasis K I.1).ofIsLocalizedModule_span ℚ ℤ⁰ _] simp -open FiniteDimensional in +open Module in theorem fractionalIdeal_rank (I : (FractionalIdeal (𝓞 K)⁰ K)ˣ) : finrank ℤ I = finrank ℤ (𝓞 K) := by rw [finrank_eq_card_chooseBasisIndex, RingOfIntegers.rank, diff --git a/Mathlib/NumberTheory/NumberField/House.lean b/Mathlib/NumberTheory/NumberField/House.lean index 5d0cc0062fc60..d56eb4d18c668 100644 --- a/Mathlib/NumberTheory/NumberField/House.lean +++ b/Mathlib/NumberTheory/NumberField/House.lean @@ -27,7 +27,7 @@ namespace NumberField noncomputable section -open Module.Free FiniteDimensional canonicalEmbedding Matrix Finset +open Module.Free Module canonicalEmbedding Matrix Finset attribute [local instance] Matrix.seminormedAddCommGroup @@ -62,7 +62,7 @@ noncomputable section variable (K) -open Module.Free FiniteDimensional canonicalEmbedding Matrix Finset +open Module.Free Module canonicalEmbedding Matrix Finset attribute [local instance] Matrix.seminormedAddCommGroup diff --git a/Mathlib/NumberTheory/NumberField/Norm.lean b/Mathlib/NumberTheory/NumberField/Norm.lean index 2b529a1d239bb..e8964a687a66b 100644 --- a/Mathlib/NumberTheory/NumberField/Norm.lean +++ b/Mathlib/NumberTheory/NumberField/Norm.lean @@ -22,7 +22,7 @@ rings of integers. open scoped NumberField -open Finset NumberField Algebra FiniteDimensional +open Finset NumberField Algebra Module section Rat diff --git a/Mathlib/NumberTheory/NumberField/Units/Basic.lean b/Mathlib/NumberTheory/NumberField/Units/Basic.lean index eaabbc19a44f8..7907293a0c950 100644 --- a/Mathlib/NumberTheory/NumberField/Units/Basic.lean +++ b/Mathlib/NumberTheory/NumberField/Units/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Xavier Roblot -/ import Mathlib.NumberTheory.NumberField.Embeddings +import Mathlib.RingTheory.LocalRing.RingHom.Basic /-! # Units of a number field diff --git a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean index 2f8a1d3a28cd8..12b15e1ddd7d7 100644 --- a/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean +++ b/Mathlib/NumberTheory/NumberField/Units/DirichletTheorem.lean @@ -217,7 +217,7 @@ theorem seq_next {x : 𝓞 K} (hx : x ≠ 0) : fun w => ⟨(w x) / 2, div_nonneg (AbsoluteValue.nonneg _ _) (by norm_num)⟩ suffices ∀ w, w ≠ w₁ → f w ≠ 0 by obtain ⟨g, h_geqf, h_gprod⟩ := adjust_f K B this - obtain ⟨y, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt (f := g) + obtain ⟨y, h_ynz, h_yle⟩ := exists_ne_zero_mem_ringOfIntegers_lt K (f := g) (by rw [convexBodyLT_volume]; convert hB; exact congr_arg ((↑) : NNReal → ENNReal) h_gprod) refine ⟨y, h_ynz, fun w hw => (h_geqf w hw ▸ h_yle w).trans ?_, ?_⟩ · rw [← Rat.cast_le (K := ℝ), Rat.cast_natCast] @@ -304,7 +304,7 @@ theorem exists_unit (w₁ : InfinitePlace K) : _ = w (algebraMap (𝓞 K) K (seq K w₁ hB m)) * w (algebraMap (𝓞 K) K (seq K w₁ hB n))⁻¹ := _root_.map_mul _ _ _ _ < 1 := by - rw [map_inv₀, mul_inv_lt_iff (pos_iff.mpr (seq_ne_zero K w₁ hB n)), mul_one] + rw [map_inv₀, mul_inv_lt_iff₀ (pos_iff.mpr (seq_ne_zero K w₁ hB n)), one_mul] exact seq_decreasing K w₁ hB hnm w hw refine Set.Finite.exists_lt_map_eq_of_forall_mem (t := { I : Ideal (𝓞 K) | 1 ≤ Ideal.absNorm I ∧ Ideal.absNorm I ≤ B }) @@ -354,7 +354,7 @@ section statements variable [NumberField K] open scoped Classical -open dirichletUnitTheorem FiniteDimensional +open dirichletUnitTheorem Module /-- The unit rank of the number field `K`, it is equal to `card (InfinitePlace K) - 1`. -/ def rank : ℕ := Fintype.card (InfinitePlace K) - 1 @@ -462,13 +462,13 @@ instance : Monoid.FG (𝓞 K)ˣ := by infer_instance theorem rank_modTorsion : - FiniteDimensional.finrank ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) = rank K := by + Module.finrank ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) = rank K := by rw [← LinearEquiv.finrank_eq (logEmbeddingEquiv K).symm, unitLattice_rank] /-- A basis of the quotient `(𝓞 K)ˣ ⧸ (torsion K)` seen as an additive ℤ-module. -/ def basisModTorsion : Basis (Fin (rank K)) ℤ (Additive ((𝓞 K)ˣ ⧸ (torsion K))) := Basis.reindex (Module.Free.chooseBasis ℤ _) (Fintype.equivOfCardEq <| by - rw [← FiniteDimensional.finrank_eq_card_chooseBasisIndex, rank_modTorsion, Fintype.card_fin]) + rw [← Module.finrank_eq_card_chooseBasisIndex, rank_modTorsion, Fintype.card_fin]) /-- The basis of the `unitLattice` obtained by mapping `basisModTorsion` via `logEmbedding`. -/ def basisUnitLattice : Basis (Fin (rank K)) ℤ (unitLattice K) := diff --git a/Mathlib/NumberTheory/Padics/Hensel.lean b/Mathlib/NumberTheory/Padics/Hensel.lean index d32fe3c1f17a2..05f97027ce268 100644 --- a/Mathlib/NumberTheory/Padics/Hensel.lean +++ b/Mathlib/NumberTheory/Padics/Hensel.lean @@ -131,7 +131,7 @@ private theorem T_lt_one : T < 1 := by have h := (div_lt_one (deriv_sq_norm_pos hnorm)).2 hnorm rw [T_def]; exact h -private theorem T_pow {n : ℕ} (hn : n ≠ 0) : T ^ n < 1 := pow_lt_one T_nonneg (T_lt_one hnorm) hn +private theorem T_pow {n : ℕ} (hn : n ≠ 0) : T ^ n < 1 := pow_lt_one₀ T_nonneg (T_lt_one hnorm) hn private theorem T_pow' (n : ℕ) : T ^ 2 ^ n < 1 := T_pow hnorm (pow_ne_zero _ two_ne_zero) @@ -156,7 +156,7 @@ private theorem calc_norm_le_one {n : ℕ} {z : ℤ_[p]} (hz : ih n z) : gcongr apply hz.2 _ = ‖F.derivative.eval a‖ * T ^ 2 ^ n := div_sq_cancel _ _ - _ ≤ 1 := mul_le_one (PadicInt.norm_le_one _) (T_pow_nonneg _) (le_of_lt (T_pow' hnorm _)) + _ ≤ 1 := mul_le_one₀ (PadicInt.norm_le_one _) (T_pow_nonneg _) (le_of_lt (T_pow' hnorm _)) private theorem calc_deriv_dist {z z' z1 : ℤ_[p]} (hz' : z' = z - z1) @@ -183,7 +183,7 @@ private def calc_eval_z' {z z' z1 : ℤ_[p]} (hz' : z' = z - z1) {n} (hz : ih n obtain ⟨q, hq⟩ := F.binomExpansion z (-z1) have : ‖(↑(F.derivative.eval z) * (↑(F.eval z) / ↑(F.derivative.eval z)) : ℚ_[p])‖ ≤ 1 := by rw [padicNormE.mul] - exact mul_le_one (PadicInt.norm_le_one _) (norm_nonneg _) h1 + exact mul_le_one₀ (PadicInt.norm_le_one _) (norm_nonneg _) h1 have : F.derivative.eval z * -z1 = -F.eval z := by calc F.derivative.eval z * -z1 = @@ -275,7 +275,7 @@ private theorem newton_seq_dist_aux (n : ℕ) : | 0 => by simp [T_pow_nonneg, mul_nonneg] | k + 1 => have : 2 ^ n ≤ 2 ^ (n + k) := by - apply pow_le_pow_right + apply pow_right_mono₀ · norm_num · apply Nat.le_add_right calc @@ -356,7 +356,7 @@ private theorem T_pos : T > 0 := by private theorem newton_seq_succ_dist_weak (n : ℕ) : ‖newton_seq (n + 2) - newton_seq (n + 1)‖ < ‖F.eval a‖ / ‖F.derivative.eval a‖ := have : 2 ≤ 2 ^ (n + 1) := by - have := pow_le_pow_right (by norm_num : 1 ≤ 2) (Nat.le_add_left _ _ : 1 ≤ n + 1) + have := pow_right_mono₀ (by norm_num : 1 ≤ 2) (Nat.le_add_left _ _ : 1 ≤ n + 1) simpa using this calc ‖newton_seq (n + 2) - newton_seq (n + 1)‖ ≤ ‖F.derivative.eval a‖ * T ^ 2 ^ (n + 1) := @@ -401,7 +401,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 (deriv_norm_pos _), ← sq] <;> assumption + rw [soln_dist_to_a, div_lt_iff₀ (deriv_norm_pos _), ← sq] <;> assumption private theorem soln_unique (z : ℤ_[p]) (hev : F.eval z = 0) (hnlt : ‖z - a‖ < ‖F.derivative.eval a‖) : z = soln := diff --git a/Mathlib/NumberTheory/Padics/PadicIntegers.lean b/Mathlib/NumberTheory/Padics/PadicIntegers.lean index 02820e33e2483..798a8c9d36b41 100644 --- a/Mathlib/NumberTheory/Padics/PadicIntegers.lean +++ b/Mathlib/NumberTheory/Padics/PadicIntegers.lean @@ -78,7 +78,7 @@ def subring : Subring ℚ_[p] where zero_mem' := by norm_num one_mem' := by norm_num add_mem' hx hy := (padicNormE.nonarchimedean _ _).trans <| max_le_iff.2 ⟨hx, hy⟩ - mul_mem' hx hy := (padicNormE.mul _ _).trans_le <| mul_le_one hx (norm_nonneg _) hy + mul_mem' hx hy := (padicNormE.mul _ _).trans_le <| mul_le_one₀ hx (norm_nonneg _) hy neg_mem' hx := (norm_neg _).trans_le hx @[simp] @@ -304,7 +304,7 @@ variable (p : ℕ) [hp : Fact p.Prime] theorem exists_pow_neg_lt {ε : ℝ} (hε : 0 < ε) : ∃ k : ℕ, (p : ℝ) ^ (-(k : ℤ)) < ε := by obtain ⟨k, hk⟩ := exists_nat_gt ε⁻¹ use k - rw [← inv_lt_inv hε (_root_.zpow_pos_of_pos _ _)] + rw [← inv_lt_inv₀ hε (zpow_pos _ _)] · rw [zpow_neg, inv_inv, zpow_natCast] apply lt_of_lt_of_le hk norm_cast @@ -356,7 +356,7 @@ theorem valuation_nonneg (x : ℤ_[p]) : 0 ≤ x.valuation := by by_cases hx : x = 0 · simp [hx] have h : (1 : ℝ) < p := mod_cast hp.1.one_lt - rw [← neg_nonpos, ← (zpow_strictMono h).le_iff_le] + rw [← neg_nonpos, ← (zpow_right_strictMono₀ h).le_iff_le] show (p : ℝ) ^ (-valuation x) ≤ (p : ℝ) ^ (0 : ℤ) rw [← norm_eq_pow_val hx] simpa using x.property @@ -373,7 +373,7 @@ theorem valuation_p_pow_mul (n : ℕ) (c : ℤ_[p]) (hc : c ≠ 0) : exact_mod_cast pow_eq_zero hc · exact hc rwa [norm_eq_pow_val aux, norm_p_pow, norm_eq_pow_val hc, ← zpow_add₀, ← neg_add, - zpow_inj, neg_inj] at this + zpow_right_inj₀, neg_inj] at this · exact mod_cast hp.1.pos · exact mod_cast hp.1.ne_one · exact mod_cast hp.1.ne_zero @@ -433,8 +433,7 @@ See `unitCoeff_spec`. -/ def unitCoeff {x : ℤ_[p]} (hx : x ≠ 0) : ℤ_[p]ˣ := let u : ℚ_[p] := x * (p : ℚ_[p]) ^ (-x.valuation) have hu : ‖u‖ = 1 := by - simp [u, hx, Nat.zpow_ne_zero_of_pos (mod_cast hp.1.pos) x.valuation, norm_eq_pow_val, - zpow_neg, inv_mul_cancel] + simp [u, hx, zpow_ne_zero (G₀ := ℝ) _ (Nat.cast_ne_zero.2 hp.1.pos.ne'), norm_eq_pow_val] mkUnits hu @[simp] @@ -468,7 +467,7 @@ theorem norm_le_pow_iff_le_valuation (x : ℤ_[p]) (hx : x ≠ 0) (n : ℕ) : intro m refine pow_pos ?_ m exact mod_cast hp.1.pos - rw [inv_le_inv (aux _) (aux _)] + rw [inv_le_inv₀ (aux _) (aux _)] have : p ^ n ≤ p ^ k ↔ n ≤ k := (pow_right_strictMono hp.1.one_lt).le_iff_le rw [← this] norm_cast @@ -528,7 +527,7 @@ instance : LocalRing ℤ_[p] := LocalRing.of_nonunits_add <| by simp only [mem_nonunits]; exact fun x y => norm_lt_one_add theorem p_nonnunit : (p : ℤ_[p]) ∈ nonunits ℤ_[p] := by - have : (p : ℝ)⁻¹ < 1 := inv_lt_one <| mod_cast hp.1.one_lt + have : (p : ℝ)⁻¹ < 1 := inv_lt_one_of_one_lt₀ <| mod_cast hp.1.one_lt rwa [← norm_p, ← mem_nonunits] at this theorem maximalIdeal_eq_span_p : maximalIdeal ℤ_[p] = Ideal.span {(p : ℤ_[p])} := by @@ -569,7 +568,7 @@ instance : IsAdicComplete (maximalIdeal ℤ_[p]) ℤ_[p] where exact hx hn · refine ⟨x'.lim, fun n => ?_⟩ have : (0 : ℝ) < (p : ℝ) ^ (-n : ℤ) := by - apply zpow_pos_of_pos + apply zpow_pos exact mod_cast hp.1.pos obtain ⟨i, hi⟩ := equiv_def₃ (equiv_lim x') this by_cases hin : i ≤ n diff --git a/Mathlib/NumberTheory/Padics/PadicNorm.lean b/Mathlib/NumberTheory/Padics/PadicNorm.lean index 9a46b58826307..311b2e21e81be 100644 --- a/Mathlib/NumberTheory/Padics/PadicNorm.lean +++ b/Mathlib/NumberTheory/Padics/PadicNorm.lean @@ -3,7 +3,6 @@ Copyright (c) 2018 Robert Y. Lewis. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Robert Y. Lewis -/ -import Mathlib.Algebra.Order.Field.Power import Mathlib.NumberTheory.Padics.PadicVal.Basic /-! @@ -92,7 +91,7 @@ theorem padicNorm_of_prime_of_ne {q : ℕ} [p_prime : Fact p.Prime] [q_prime : F See also `padicNorm.padicNorm_p_lt_one_of_prime` for a version assuming `p` is prime. -/ theorem padicNorm_p_lt_one (hp : 1 < p) : padicNorm p p < 1 := by - rw [padicNorm_p hp, inv_lt_one_iff] + rw [padicNorm_p hp, inv_lt_one_iff₀] exact mod_cast Or.inr hp /-- The `p`-adic norm of `p` is less than `1` if `p` is prime. @@ -143,17 +142,11 @@ protected theorem div (q r : ℚ) : padicNorm p (q / r) = padicNorm p q / padicN else eq_div_of_mul_eq (padicNorm.nonzero hr) (by rw [← padicNorm.mul, div_mul_cancel₀ _ hr]) /-- The `p`-adic norm of an integer is at most `1`. -/ -protected theorem of_int (z : ℤ) : padicNorm p z ≤ 1 := - if hz : z = 0 then by simp [hz, zero_le_one] - else by - unfold padicNorm - rw [if_neg _] - · refine zpow_le_one_of_nonpos ?_ ?_ - · exact mod_cast le_of_lt hp.1.one_lt - · rw [padicValRat.of_int, neg_nonpos] - norm_cast - simp - exact mod_cast hz +protected theorem of_int (z : ℤ) : padicNorm p z ≤ 1 := by + obtain rfl | hz := eq_or_ne z 0 + · simp + · rw [padicNorm, if_neg (mod_cast hz)] + exact zpow_le_one_of_nonpos₀ (mod_cast hp.1.one_le) (by simp) private theorem nonarchimedean_aux {q r : ℚ} (h : padicValRat p q ≤ padicValRat p r) : padicNorm p (q + r) ≤ max (padicNorm p q) (padicNorm p r) := @@ -168,7 +161,7 @@ private theorem nonarchimedean_aux {q r : ℚ} (h : padicValRat p q ≤ padicVal unfold padicNorm; split_ifs apply le_max_iff.2 left - apply zpow_le_of_le + apply zpow_le_zpow_right₀ · exact mod_cast le_of_lt hp.1.one_lt · apply neg_le_neg have : padicValRat p q = min (padicValRat p q) (padicValRat p r) := (min_eq_left h).symm @@ -232,7 +225,7 @@ theorem dvd_iff_norm_le {n : ℕ} {z : ℤ} : ↑(p ^ n) ∣ z ↔ padicNorm p z unfold padicNorm; split_ifs with hz · norm_cast at hz simp [hz] - · rw [zpow_le_iff_le, neg_le_neg_iff, padicValRat.of_int, + · rw [zpow_le_zpow_iff_right₀, neg_le_neg_iff, padicValRat.of_int, padicValInt.of_ne_one_ne_zero hp.1.ne_one _] · norm_cast rw [← PartENat.coe_le_coe, PartENat.natCast_get, ← multiplicity.pow_dvd_iff_le_multiplicity, @@ -246,7 +239,7 @@ theorem int_eq_one_iff (m : ℤ) : padicNorm p m = 1 ↔ ¬(p : ℤ) ∣ m := by simp only [dvd_iff_norm_le, Int.cast_natCast, Nat.cast_one, zpow_neg, zpow_one, not_le] constructor · intro h - rw [h, inv_lt_one_iff_of_pos] <;> norm_cast + rw [h, inv_lt_one₀] <;> norm_cast · exact Nat.Prime.one_lt Fact.out · exact Nat.Prime.pos Fact.out · simp only [padicNorm] @@ -255,10 +248,10 @@ theorem int_eq_one_iff (m : ℤ) : padicNorm p m = 1 ↔ ¬(p : ℤ) ∣ m := by intro h exact (Nat.not_lt_zero p h).elim · have : 1 < (p : ℚ) := by norm_cast; exact Nat.Prime.one_lt (Fact.out : Nat.Prime p) - rw [← zpow_neg_one, zpow_lt_iff_lt this] + rw [← zpow_neg_one, zpow_lt_zpow_iff_right₀ this] have : 0 ≤ padicValRat p m := by simp only [of_int, Nat.cast_nonneg] intro h - rw [← zpow_zero (p : ℚ), zpow_inj] <;> linarith + rw [← zpow_zero (p : ℚ), zpow_right_inj₀] <;> linarith theorem int_lt_one_iff (m : ℤ) : padicNorm p m < 1 ↔ (p : ℤ) ∣ m := by rw [← not_iff_not, ← int_eq_one_iff, eq_iff_le_not_lt] diff --git a/Mathlib/NumberTheory/Padics/PadicNumbers.lean b/Mathlib/NumberTheory/Padics/PadicNumbers.lean index abccff73fbb92..33559d1491dfe 100644 --- a/Mathlib/NumberTheory/Padics/PadicNumbers.lean +++ b/Mathlib/NumberTheory/Padics/PadicNumbers.lean @@ -211,7 +211,7 @@ theorem norm_eq_pow_val {f : PadicSeq p} (hf : ¬f ≈ 0) : f.norm = (p : ℚ) ^ theorem val_eq_iff_norm_eq {f g : PadicSeq p} (hf : ¬f ≈ 0) (hg : ¬g ≈ 0) : f.valuation = g.valuation ↔ f.norm = g.norm := by - rw [norm_eq_pow_val hf, norm_eq_pow_val hg, ← neg_inj, zpow_inj] + rw [norm_eq_pow_val hf, norm_eq_pow_val hg, ← neg_inj, zpow_right_inj₀] · exact mod_cast (Fact.out : p.Prime).pos · exact mod_cast (Fact.out : p.Prime).ne_one @@ -779,8 +779,7 @@ theorem norm_p : ‖(p : ℚ_[p])‖ = (p : ℝ)⁻¹ := by theorem norm_p_lt_one : ‖(p : ℚ_[p])‖ < 1 := by rw [norm_p] - apply inv_lt_one - exact mod_cast hp.1.one_lt + exact inv_lt_one_of_one_lt₀ <| mod_cast hp.1.one_lt -- Porting note: Linter thinks this is a duplicate simp lemma, so `priority` is assigned @[simp (high)] @@ -833,7 +832,7 @@ theorem norm_rat_le_one : ∀ {q : ℚ} (_ : ¬p ∣ q.den), ‖(q : ℚ_[p])‖ -- Porting note: `Nat.cast_zero` instead of another `norm_cast` call rw [padicNorm.eq_zpow_of_nonzero hnz', padicValRat, neg_sub, padicValNat.eq_zero_of_not_dvd hq, Nat.cast_zero, zero_sub, zpow_neg, zpow_natCast] - apply inv_le_one + apply inv_le_one_of_one_le₀ norm_cast apply one_le_pow exact hp.1.pos @@ -860,8 +859,7 @@ theorem norm_int_lt_one_iff_dvd (k : ℤ) : ‖(k : ℚ_[p])‖ < 1 ↔ ↑p ∣ mul_le_mul le_rfl (by simpa using norm_int_le_one _) (norm_nonneg _) (norm_nonneg _) _ < 1 := by rw [mul_one, padicNormE.norm_p] - apply inv_lt_one - exact mod_cast hp.1.one_lt + exact inv_lt_one_of_one_lt₀ <| mod_cast hp.1.one_lt theorem norm_int_le_pow_iff_dvd (k : ℤ) (n : ℕ) : ‖(k : ℚ_[p])‖ ≤ (p : ℝ) ^ (-n : ℤ) ↔ (p ^ n : ℤ) ∣ k := by @@ -973,7 +971,7 @@ theorem norm_eq_pow_val {x : ℚ_[p]} : x ≠ 0 → ‖x‖ = (p : ℝ) ^ (-x.va @[simp] theorem valuation_p : valuation (p : ℚ_[p]) = 1 := by have h : (1 : ℝ) < p := mod_cast (Fact.out : p.Prime).one_lt - refine neg_injective ((zpow_strictMono h).injective <| (norm_eq_pow_val ?_).symm.trans ?_) + refine neg_injective ((zpow_right_strictMono₀ h).injective <| (norm_eq_pow_val ?_).symm.trans ?_) · exact mod_cast (Fact.out : p.Prime).ne_zero · simp @@ -989,8 +987,9 @@ theorem valuation_map_add {x y : ℚ_[p]} (hxy : x + y ≠ 0) : have hp_one : (1 : ℝ) < p := by rw [← Nat.cast_one, Nat.cast_lt] exact Nat.Prime.one_lt hp.elim - rwa [norm_eq_pow_val hx, norm_eq_pow_val hy, norm_eq_pow_val hxy, - zpow_le_max_iff_min_le hp_one] at h_norm + rwa [norm_eq_pow_val hx, norm_eq_pow_val hy, norm_eq_pow_val hxy, le_max_iff, + zpow_le_zpow_iff_right₀ hp_one, zpow_le_zpow_iff_right₀ hp_one, neg_le_neg_iff, + neg_le_neg_iff, ← min_le_iff] at h_norm @[simp] theorem valuation_map_mul {x y : ℚ_[p]} (hx : x ≠ 0) (hy : y ≠ 0) : @@ -1003,7 +1002,7 @@ theorem valuation_map_mul {x y : ℚ_[p]} (hx : x ≠ 0) (hy : y ≠ 0) : rw [← Nat.cast_zero, Nat.cast_lt] exact Nat.Prime.pos hp.elim rw [norm_eq_pow_val hx, norm_eq_pow_val hy, norm_eq_pow_val (mul_ne_zero hx hy), ← - zpow_add₀ (ne_of_gt hp_pos), zpow_inj hp_pos hp_ne_one, ← neg_add, neg_inj] at h_norm + zpow_add₀ (ne_of_gt hp_pos), zpow_right_inj₀ hp_pos hp_ne_one, ← neg_add, neg_inj] at h_norm exact h_norm open Classical in @@ -1061,14 +1060,12 @@ section NormLEIff theorem norm_le_pow_iff_norm_lt_pow_add_one (x : ℚ_[p]) (n : ℤ) : ‖x‖ ≤ (p : ℝ) ^ n ↔ ‖x‖ < (p : ℝ) ^ (n + 1) := by - have aux : ∀ n : ℤ, 0 < ((p : ℝ) ^ n) := by - apply Nat.zpow_pos_of_pos - exact hp.1.pos + have aux (n : ℤ) : 0 < ((p : ℝ) ^ n) := zpow_pos (mod_cast hp.1.pos) _ by_cases hx0 : x = 0 · simp [hx0, norm_zero, aux, le_of_lt (aux _)] rw [norm_eq_pow_val hx0] have h1p : 1 < (p : ℝ) := mod_cast hp.1.one_lt - have H := zpow_strictMono h1p + have H := zpow_right_strictMono₀ h1p rw [H.le_iff_le, H.lt_iff_lt, Int.lt_add_one_iff] theorem norm_lt_pow_iff_norm_le_pow_sub_one (x : ℚ_[p]) (n : ℤ) : @@ -1078,7 +1075,7 @@ theorem norm_lt_pow_iff_norm_le_pow_sub_one (x : ℚ_[p]) (n : ℤ) : theorem norm_le_one_iff_val_nonneg (x : ℚ_[p]) : ‖x‖ ≤ 1 ↔ 0 ≤ x.valuation := by by_cases hx : x = 0 · simp only [hx, norm_zero, valuation_zero, zero_le_one, le_refl] - · rw [norm_eq_pow_val hx, ← zpow_zero (p : ℝ), zpow_le_iff_le, Right.neg_nonpos_iff] + · rw [norm_eq_pow_val hx, ← zpow_zero (p : ℝ), zpow_le_zpow_iff_right₀, Right.neg_nonpos_iff] exact Nat.one_lt_cast.2 (Nat.Prime.one_lt' p).1 end NormLEIff diff --git a/Mathlib/NumberTheory/Padics/RingHoms.lean b/Mathlib/NumberTheory/Padics/RingHoms.lean index 31ba8f2ff384a..9458144550aaf 100644 --- a/Mathlib/NumberTheory/Padics/RingHoms.lean +++ b/Mathlib/NumberTheory/Padics/RingHoms.lean @@ -256,7 +256,7 @@ theorem toZMod_spec : x - (ZMod.cast (toZMod x) : ℤ_[p]) ∈ maximalIdeal ℤ_ dsimp [toZMod, toZModHom] rcases Nat.exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩ change ↑((_ : ZMod (0 + p' + 1)).val) = (_ : ℤ_[0 + p' + 1]) - simp only [ZMod.val_natCast, add_zero, add_def, Nat.cast_inj, zero_add] + rw [Nat.cast_inj] apply mod_eq_of_lt simpa only [zero_add] using zmodRepr_lt_p x @@ -589,7 +589,7 @@ theorem lift_sub_val_mem_span (r : R) (n : ℕ) : lift f_compat r - (f n r).val ∈ (Ideal.span {(p : ℤ_[p]) ^ n}) := by obtain ⟨k, hk⟩ := limNthHom_spec f_compat r _ - (show (0 : ℝ) < (p : ℝ) ^ (-n : ℤ) from Nat.zpow_pos_of_pos hp_prime.1.pos _) + (show (0 : ℝ) < (p : ℝ) ^ (-n : ℤ) from zpow_pos (mod_cast hp_prime.1.pos) _) have := le_of_lt (hk (max n k) (le_max_right _ _)) rw [norm_le_pow_iff_mem_span_pow] at this dsimp [lift] diff --git a/Mathlib/NumberTheory/Pell.lean b/Mathlib/NumberTheory/Pell.lean index 8c063efdbcb77..8cdd56d82e73b 100644 --- a/Mathlib/NumberTheory/Pell.lean +++ b/Mathlib/NumberTheory/Pell.lean @@ -206,7 +206,7 @@ theorem y_ne_zero_of_one_lt_x {a : Solution₁ d} (ha : 1 < a.x) : a.y ≠ 0 := theorem d_pos_of_one_lt_x {a : Solution₁ d} (ha : 1 < a.x) : 0 < d := by refine pos_of_mul_pos_left ?_ (sq_nonneg a.y) rw [a.prop_y, sub_pos] - exact one_lt_pow ha two_ne_zero + exact one_lt_pow₀ ha two_ne_zero /-- If a solution has `x > 1`, then `d` is not a square. -/ theorem d_nonsquare_of_one_lt_x {a : Solution₁ d} (ha : 1 < a.x) : ¬IsSquare d := by diff --git a/Mathlib/NumberTheory/PellMatiyasevic.lean b/Mathlib/NumberTheory/PellMatiyasevic.lean index b931db03869a5..d53d6039949db 100644 --- a/Mathlib/NumberTheory/PellMatiyasevic.lean +++ b/Mathlib/NumberTheory/PellMatiyasevic.lean @@ -273,14 +273,14 @@ theorem eq_pell_lem : ∀ (n) (b : ℤ√(d a1)), 1 ≤ b → IsPell b → have y0l : (0 : ℤ√d a1) < ⟨x - x, y - -y⟩ := sub_lt_sub h1l fun hn : (1 : ℤ√d a1) ≤ ⟨x, -y⟩ => by have t := mul_le_mul_of_nonneg_left hn (le_trans zero_le_one h1) - erw [bm, mul_one] at t + rw [bm, mul_one] at t exact h1l t have yl2 : (⟨_, _⟩ : ℤ√_) < ⟨_, _⟩ := show (⟨x, y⟩ - ⟨x, -y⟩ : ℤ√d a1) < ⟨a, 1⟩ - ⟨a, -1⟩ from sub_lt_sub ha fun hn : (⟨x, -y⟩ : ℤ√d a1) ≤ ⟨a, -1⟩ => by have t := mul_le_mul_of_nonneg_right (mul_le_mul_of_nonneg_left hn (le_trans zero_le_one h1)) a1p - erw [bm, one_mul, mul_assoc, Eq.trans (mul_comm _ _) a1m, mul_one] at t + rw [bm, one_mul, mul_assoc, Eq.trans (mul_comm _ _) a1m, mul_one] at t exact ha t simp only [sub_self, sub_neg_eq_add] at y0l; simp only [Zsqrtd.neg_re, add_neg_cancel, Zsqrtd.neg_im, neg_neg] at yl2 diff --git a/Mathlib/NumberTheory/PythagoreanTriples.lean b/Mathlib/NumberTheory/PythagoreanTriples.lean index 8522d8eb5a00d..57ca7ff109082 100644 --- a/Mathlib/NumberTheory/PythagoreanTriples.lean +++ b/Mathlib/NumberTheory/PythagoreanTriples.lean @@ -179,7 +179,7 @@ theorem normalize : PythagoreanTriple (x / Int.gcd x y) (y / Int.gcd x y) (z / I have hz : z = 0 := by simpa only [PythagoreanTriple, hx, hy, add_zero, zero_eq_mul, mul_zero, or_self_iff] using h - simp only [hx, hy, hz, Int.zero_div] + simp only [hx, hy, hz] exact zero rcases h.gcd_dvd with ⟨z0, rfl⟩ obtain ⟨k, x0, y0, k0, h2, rfl, rfl⟩ : diff --git a/Mathlib/NumberTheory/RamificationInertia.lean b/Mathlib/NumberTheory/RamificationInertia.lean index c059ce200afdd..10d1ba5cf00ef 100644 --- a/Mathlib/NumberTheory/RamificationInertia.lean +++ b/Mathlib/NumberTheory/RamificationInertia.lean @@ -47,7 +47,7 @@ variable {R : Type u} [CommRing R] variable {S : Type v} [CommRing S] (f : R →+* S) variable (p : Ideal R) (P : Ideal S) -open FiniteDimensional +open Module open UniqueFactorizationMonoid @@ -476,7 +476,7 @@ noncomputable def quotientToQuotientRangePowQuotSuccAux {i : ℕ} {a : S} (a_mem (P ^ i).map (Ideal.Quotient.mk (P ^ e)) ⧸ LinearMap.range (powQuotSuccInclusion f p P i) := Quotient.map' (fun x : S => ⟨_, Ideal.mem_map_of_mem _ (Ideal.mul_mem_right x _ a_mem)⟩) fun x y h => by - rw [Submodule.quotientRel_r_def] at h ⊢ + rw [Submodule.quotientRel_def] at h ⊢ simp only [_root_.map_mul, LinearMap.mem_range] refine ⟨⟨_, Ideal.mem_map_of_mem _ (Ideal.mul_mem_mul a_mem h)⟩, ?_⟩ ext @@ -699,7 +699,7 @@ instance Factors.finiteDimensional_quotient [IsNoetherian R S] [p.IsMaximal] theorem Factors.inertiaDeg_ne_zero [IsNoetherian R S] [p.IsMaximal] (P : (factors (map (algebraMap R S) p)).toFinset) : inertiaDeg (algebraMap R S) p P ≠ 0 := by - rw [inertiaDeg_algebraMap]; exact (FiniteDimensional.finrank_pos_iff.mpr inferInstance).ne' + rw [inertiaDeg_algebraMap]; exact (Module.finrank_pos_iff.mpr inferInstance).ne' instance Factors.finiteDimensional_quotient_pow [IsNoetherian R S] [p.IsMaximal] (P : (factors (map (algebraMap R S) p)).toFinset) : @@ -793,4 +793,69 @@ theorem sum_ramification_inertia (K L : Type*) [Field K] [Field L] [IsDedekindDo end FactorsMap +section tower + +variable {R S T : Type*} [CommRing R] [CommRing S] [CommRing T] + +theorem ramificationIdx_tower [IsDedekindDomain S] [IsDedekindDomain T] {f : R →+* S} {g : S →+* T} + {p : Ideal R} {P : Ideal S} {Q : Ideal T} [hpm : P.IsPrime] [hqm : Q.IsPrime] + (hg0 : map g P ≠ ⊥) (hfg : map (g.comp f) p ≠ ⊥) (hg : map g P ≤ Q) : + ramificationIdx (g.comp f) p Q = ramificationIdx f p P * ramificationIdx g P Q := by + classical + have hf0 : map f p ≠ ⊥ := + ne_bot_of_map_ne_bot (Eq.mp (congrArg (fun I ↦ I ≠ ⊥) (map_map f g).symm) hfg) + have hp0 : P ≠ ⊥ := ne_bot_of_map_ne_bot hg0 + have hq0 : Q ≠ ⊥ := ne_bot_of_le_ne_bot hg0 hg + letI : P.IsMaximal := Ring.DimensionLEOne.maximalOfPrime hp0 hpm + rw [IsDedekindDomain.ramificationIdx_eq_normalizedFactors_count hf0 hpm hp0, + IsDedekindDomain.ramificationIdx_eq_normalizedFactors_count hg0 hqm hq0, + IsDedekindDomain.ramificationIdx_eq_normalizedFactors_count hfg hqm hq0, ← map_map] + rcases eq_prime_pow_mul_coprime hf0 P with ⟨I, hcp, heq⟩ + have hcp : ⊤ = map g P ⊔ map g I := by rw [← map_sup, hcp, map_top g] + have hntq : ¬ ⊤ ≤ Q := fun ht ↦ IsPrime.ne_top hqm (Iff.mpr (eq_top_iff_one Q) (ht trivial)) + nth_rw 1 [heq, map_mul, Ideal.map_pow, normalizedFactors_mul (pow_ne_zero _ hg0) <| by + by_contra h + simp only [h, Submodule.zero_eq_bot, bot_le, sup_of_le_left] at hcp + exact hntq (hcp.trans_le hg), Multiset.count_add, normalizedFactors_pow, Multiset.count_nsmul] + exact add_right_eq_self.mpr <| Decidable.byContradiction fun h ↦ hntq <| hcp.trans_le <| + sup_le hg <| le_of_dvd <| dvd_of_mem_normalizedFactors <| Multiset.count_ne_zero.mp h + +attribute [local instance] Quotient.field in +theorem inertiaDeg_tower {f : R →+* S} {g : S →+* T} {p : Ideal R} {P : Ideal S} {I : Ideal T} + [p.IsMaximal] [P.IsMaximal] (hp : p = comap f P) (hP : P = comap g I) : + inertiaDeg (g.comp f) p I = inertiaDeg f p P * inertiaDeg g P I := by + have h : comap (g.comp f) I = p := by rw [hp, hP, comap_comap] + simp only [inertiaDeg, dif_pos hp.symm, dif_pos hP.symm, dif_pos h] + letI : Algebra (R ⧸ p) (S ⧸ P) := Ideal.Quotient.algebraQuotientOfLEComap (le_of_eq hp) + letI : Algebra (S ⧸ P) (T ⧸ I) := Ideal.Quotient.algebraQuotientOfLEComap (le_of_eq hP) + letI : Algebra (R ⧸ p) (T ⧸ I) := Ideal.Quotient.algebraQuotientOfLEComap (le_of_eq h.symm) + letI : IsScalarTower (R ⧸ p) (S ⧸ P) (T ⧸ I) := IsScalarTower.of_algebraMap_eq (by rintro ⟨⟩; rfl) + exact (finrank_mul_finrank (R ⧸ p) (S ⧸ P) (T ⧸ I)).symm + +variable [Algebra R S] [Algebra S T] [Algebra R T] [IsScalarTower R S T] + +/-- Let `T / S / R` be a tower of algebras, `p, P, Q` be ideals in `R, S, T` respectively, + and `P` and `Q` are prime. If `P = Q ∩ S`, then `e (Q | p) = e (P | p) * e (Q | P)`. -/ +theorem ramificationIdx_algebra_tower [IsDedekindDomain S] [IsDedekindDomain T] + {p : Ideal R} {P : Ideal S} {Q : Ideal T} [hpm : P.IsPrime] [hqm : Q.IsPrime] + (hg0 : map (algebraMap S T) P ≠ ⊥) + (hfg : map (algebraMap R T) p ≠ ⊥) (hg : map (algebraMap S T) P ≤ Q) : + ramificationIdx (algebraMap R T) p Q = + ramificationIdx (algebraMap R S) p P * ramificationIdx (algebraMap S T) P Q := by + classical + rw [IsScalarTower.algebraMap_eq R S T] at hfg ⊢ + exact ramificationIdx_tower hg0 hfg hg + +/-- Let `T / S / R` be a tower of algebras, `p, P, I` be ideals in `R, S, T`, respectively, + and `p` and `P` are maximal. If `p = P ∩ S` and `P = Q ∩ S`, + then `f (Q | p) = f (P | p) * f (Q | P)`. -/ +theorem inertiaDeg_algebra_tower {p : Ideal R} {P : Ideal S} {I : Ideal T} [p.IsMaximal] + [P.IsMaximal] (hp : p = comap (algebraMap R S) P) (hP : P = comap (algebraMap S T) I) : + inertiaDeg (algebraMap R T) p I = + inertiaDeg (algebraMap R S) p P * inertiaDeg (algebraMap S T) P I := by + rw [IsScalarTower.algebraMap_eq R S T] + exact inertiaDeg_tower hp hP + +end tower + end Ideal diff --git a/Mathlib/NumberTheory/Rayleigh.lean b/Mathlib/NumberTheory/Rayleigh.lean index d7a2e5f205472..0e29615583c61 100644 --- a/Mathlib/NumberTheory/Rayleigh.lean +++ b/Mathlib/NumberTheory/Rayleigh.lean @@ -63,9 +63,9 @@ private theorem no_collision (hrs : r.IsConjExponent s) : Disjoint {beattySeq r k | k} {beattySeq' s k | k} := by rw [Set.disjoint_left] intro j ⟨k, h₁⟩ ⟨m, h₂⟩ - rw [beattySeq, Int.floor_eq_iff, ← div_le_iff₀ hrs.pos, ← lt_div_iff hrs.pos] at h₁ + rw [beattySeq, Int.floor_eq_iff, ← div_le_iff₀ hrs.pos, ← lt_div_iff₀ hrs.pos] at h₁ rw [beattySeq', sub_eq_iff_eq_add, Int.ceil_eq_iff, Int.cast_add, Int.cast_one, - add_sub_cancel_right, ← div_lt_iff hrs.symm.pos, ← le_div_iff₀ hrs.symm.pos] at h₂ + add_sub_cancel_right, ← div_lt_iff₀ hrs.symm.pos, ← le_div_iff₀ hrs.symm.pos] at h₂ have h₃ := add_lt_add_of_le_of_lt h₁.1 h₂.1 have h₄ := add_lt_add_of_lt_of_le h₁.2 h₂.2 simp_rw [div_eq_inv_mul, ← right_distrib, hrs.inv_add_inv_conj, one_mul] at h₃ h₄ @@ -91,10 +91,10 @@ private theorem hit_or_miss (h : r > 0) : -- for both cases, the candidate is `k = ⌈(j + 1) / r⌉ - 1` cases lt_or_ge ((⌈(j + 1) / r⌉ - 1) * r) j · refine Or.inr ⟨⌈(j + 1) / r⌉ - 1, ?_⟩ - rw [Int.cast_sub, Int.cast_one, lt_div_iff h, sub_add_cancel] + rw [Int.cast_sub, Int.cast_one, lt_div_iff₀ h, sub_add_cancel] exact ⟨‹_›, Int.le_ceil _⟩ · refine Or.inl ⟨⌈(j + 1) / r⌉ - 1, ?_⟩ - rw [beattySeq, Int.floor_eq_iff, Int.cast_sub, Int.cast_one, ← lt_div_iff h, sub_lt_iff_lt_add] + rw [beattySeq, Int.floor_eq_iff, Int.cast_sub, Int.cast_one, ← lt_div_iff₀ h, sub_lt_iff_lt_add] exact ⟨‹_›, Int.ceil_lt_add_one _⟩ /-- Let `0 < r ∈ ℝ` and `j ∈ ℤ`. Then either `j ∈ B'_r` or `B'_r` jumps over `j`. -/ diff --git a/Mathlib/NumberTheory/SmoothNumbers.lean b/Mathlib/NumberTheory/SmoothNumbers.lean index 18f25f9900202..a130280fc2731 100644 --- a/Mathlib/NumberTheory/SmoothNumbers.lean +++ b/Mathlib/NumberTheory/SmoothNumbers.lean @@ -233,7 +233,7 @@ def equivProdNatFactoredNumbers {s : Finset ℕ} {p : ℕ} (hp : p.Prime) (hs : refine prod_eq <| (filter _ <| perm_primeFactorsList_mul (pow_ne_zero e hp.ne_zero) hm₀).trans ?_ rw [filter_append, hp.primeFactorsList_pow, - filter_eq_nil.mpr fun q hq ↦ by rw [mem_replicate] at hq; simp [hq.2, hs], + filter_eq_nil_iff.mpr fun q hq ↦ by rw [mem_replicate] at hq; simp [hq.2, hs], nil_append, filter_eq_self.mpr fun q hq ↦ by simp only [hm q hq, decide_True]] right_inv := by rintro ⟨m, hm₀, hm⟩ diff --git a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean index 413c023dba9e7..4847518e1ce0e 100644 --- a/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean +++ b/Mathlib/NumberTheory/Zsqrtd/QuadraticReciprocity.lean @@ -86,7 +86,7 @@ theorem prime_of_nat_prime_of_mod_four_eq_three (p : ℕ) [hp : Fact p.Prime] (h by_contradiction fun hpi => let ⟨a, b, hab⟩ := sq_add_sq_of_nat_prime_of_not_irreducible p hpi have : ∀ a b : ZMod 4, a ^ 2 + b ^ 2 ≠ (p : ZMod 4) := by - erw [← ZMod.natCast_mod p 4, hp3]; decide + rw [← ZMod.natCast_mod p 4, hp3]; decide this a b (hab ▸ by simp) /-- A prime natural number is prime in `ℤ[i]` if and only if it is `3` mod `4` -/ diff --git a/Mathlib/Order/Antisymmetrization.lean b/Mathlib/Order/Antisymmetrization.lean index e5205df7dc3be..8dae92170d4dd 100644 --- a/Mathlib/Order/Antisymmetrization.lean +++ b/Mathlib/Order/Antisymmetrization.lean @@ -119,11 +119,11 @@ theorem AntisymmRel.image {a b : α} (h : AntisymmRel (· ≤ ·) a b) {f : α ⟨hf h.1, hf h.2⟩ instance instPartialOrderAntisymmetrization : PartialOrder (Antisymmetrization α (· ≤ ·)) where - le a b := - (Quotient.liftOn₂' a b (· ≤ ·)) fun (_ _ _ _ : α) h₁ h₂ => + le := + Quotient.lift₂ (· ≤ ·) fun (_ _ _ _ : α) h₁ h₂ => propext ⟨fun h => h₁.2.trans <| h.trans h₂.1, fun h => h₁.1.trans <| h.trans h₂.2⟩ - lt a b := - (Quotient.liftOn₂' a b (· < ·)) fun (_ _ _ _ : α) h₁ h₂ => + lt := + Quotient.lift₂ (· < ·) fun (_ _ _ _ : α) h₁ h₂ => propext ⟨fun h => h₁.2.trans_lt <| h.trans_le h₂.1, fun h => h₁.1.trans_lt <| h.trans_le h₂.2⟩ le_refl a := Quotient.inductionOn' a <| le_refl @@ -138,11 +138,11 @@ theorem antisymmetrization_fibration : theorem acc_antisymmetrization_iff : Acc (· < ·) (@toAntisymmetrization α (· ≤ ·) _ a) ↔ Acc (· < ·) a := - acc_liftOn₂'_iff + acc_lift₂_iff theorem wellFounded_antisymmetrization_iff : WellFounded (@LT.lt (Antisymmetrization α (· ≤ ·)) _) ↔ WellFounded (@LT.lt α _) := - wellFounded_liftOn₂'_iff + wellFounded_lift₂_iff instance [WellFoundedLT α] : WellFoundedLT (Antisymmetrization α (· ≤ ·)) := ⟨wellFounded_antisymmetrization_iff.2 IsWellFounded.wf⟩ @@ -167,12 +167,12 @@ theorem toAntisymmetrization_lt_toAntisymmetrization_iff : @[simp] theorem ofAntisymmetrization_le_ofAntisymmetrization_iff {a b : Antisymmetrization α (· ≤ ·)} : ofAntisymmetrization (· ≤ ·) a ≤ ofAntisymmetrization (· ≤ ·) b ↔ a ≤ b := - (Quotient.out'RelEmbedding _).map_rel_iff + (Quotient.outRelEmbedding _).map_rel_iff @[simp] theorem ofAntisymmetrization_lt_ofAntisymmetrization_iff {a b : Antisymmetrization α (· ≤ ·)} : ofAntisymmetrization (· ≤ ·) a < ofAntisymmetrization (· ≤ ·) b ↔ a < b := - (Quotient.out'RelEmbedding _).map_rel_iff + (Quotient.outRelEmbedding _).map_rel_iff @[mono] theorem toAntisymmetrization_mono : Monotone (@toAntisymmetrization α (· ≤ ·) _) := fun _ _ => id @@ -209,7 +209,7 @@ variable (α) /-- `ofAntisymmetrization` as an order embedding. -/ @[simps] noncomputable def OrderEmbedding.ofAntisymmetrization : Antisymmetrization α (· ≤ ·) ↪o α := - { Quotient.out'RelEmbedding _ with toFun := _root_.ofAntisymmetrization _ } + { Quotient.outRelEmbedding _ with toFun := _root_.ofAntisymmetrization _ } /-- `Antisymmetrization` and `orderDual` commute. -/ def OrderIso.dualAntisymmetrization : diff --git a/Mathlib/Order/Atoms/Finite.lean b/Mathlib/Order/Atoms/Finite.lean index c17782a493d32..93cca39127a7d 100644 --- a/Mathlib/Order/Atoms/Finite.lean +++ b/Mathlib/Order/Atoms/Finite.lean @@ -22,23 +22,26 @@ variable {α β : Type*} namespace IsSimpleOrder +variable [LE α] [BoundedOrder α] [IsSimpleOrder α] + section DecidableEq /- It is important that `IsSimpleOrder` is the last type-class argument of this instance, so that type-class inference fails quickly if it doesn't apply. -/ -instance (priority := 200) {α} [DecidableEq α] [LE α] [BoundedOrder α] [IsSimpleOrder α] : - Fintype α := +instance (priority := 200) [DecidableEq α] : Fintype α := Fintype.ofEquiv Bool equivBool.symm end DecidableEq +instance (priority := 200) : Finite α := by classical infer_instance + end IsSimpleOrder namespace Fintype namespace IsSimpleOrder -variable [PartialOrder α] [BoundedOrder α] [IsSimpleOrder α] [DecidableEq α] +variable [LE α] [BoundedOrder α] [IsSimpleOrder α] [DecidableEq α] theorem univ : (Finset.univ : Finset α) = {⊤, ⊥} := by change Finset.map _ (Finset.univ : Finset Bool) = _ diff --git a/Mathlib/Order/Basic.lean b/Mathlib/Order/Basic.lean index 628c729ea2354..08b21b2de4986 100644 --- a/Mathlib/Order/Basic.lean +++ b/Mathlib/Order/Basic.lean @@ -186,7 +186,7 @@ end namespace Eq -variable [Preorder α] {x y z : α} +variable [Preorder α] {x y : α} /-- If `x = y` then `y ≤ x`. Note: this lemma uses `y ≤ x` instead of `x ≥ y`, because `le` is used almost exclusively in mathlib. -/ diff --git a/Mathlib/Order/BooleanAlgebra.lean b/Mathlib/Order/BooleanAlgebra.lean index 509ef845db9a3..24e867d0ac354 100644 --- a/Mathlib/Order/BooleanAlgebra.lean +++ b/Mathlib/Order/BooleanAlgebra.lean @@ -745,8 +745,8 @@ protected abbrev Function.Injective.generalizedBooleanAlgebra [Sup α] [Inf α] GeneralizedBooleanAlgebra α where __ := hf.generalizedCoheytingAlgebra f map_sup map_inf map_bot map_sdiff __ := hf.distribLattice f map_sup map_inf - sup_inf_sdiff a b := hf <| by erw [map_sup, map_sdiff, map_inf, sup_inf_sdiff] - inf_inf_sdiff a b := hf <| by erw [map_inf, map_sdiff, map_inf, inf_inf_sdiff, map_bot] + sup_inf_sdiff a b := hf <| by rw [map_sup, map_sdiff, map_inf, sup_inf_sdiff] + inf_inf_sdiff a b := hf <| by rw [map_inf, map_sdiff, map_inf, inf_inf_sdiff, map_bot] -- See note [reducible non-instances] /-- Pullback a `BooleanAlgebra` along an injection. -/ diff --git a/Mathlib/Order/Booleanisation.lean b/Mathlib/Order/Booleanisation.lean index dd3aa408d0c38..aa7f7370581b4 100644 --- a/Mathlib/Order/Booleanisation.lean +++ b/Mathlib/Order/Booleanisation.lean @@ -58,7 +58,7 @@ instance instCompl : HasCompl (Booleanisation α) where @[simp] lemma compl_lift (a : α) : (lift a)ᶜ = comp a := rfl @[simp] lemma compl_comp (a : α) : (comp a)ᶜ = lift a := rfl -variable [GeneralizedBooleanAlgebra α] {x y : Booleanisation α} {a b : α} +variable [GeneralizedBooleanAlgebra α] {a b : α} /-- The order on `Booleanisation α` is as follows: For `a b : α`, * `a ≤ b` iff `a ≤ b` in `α` diff --git a/Mathlib/Order/BoundedOrder.lean b/Mathlib/Order/BoundedOrder.lean index 7850b239ce06a..a28c66b0685a2 100644 --- a/Mathlib/Order/BoundedOrder.lean +++ b/Mathlib/Order/BoundedOrder.lean @@ -33,7 +33,7 @@ open Function OrderDual universe u v -variable {α : Type u} {β : Type v} {γ δ : Type*} +variable {α : Type u} {β : Type v} /-! ### Top, bottom element -/ @@ -353,7 +353,7 @@ theorem OrderBot.ext_bot {α} {hA : PartialOrder α} (A : OrderBot α) {hB : Par section SemilatticeSupTop -variable [SemilatticeSup α] [OrderTop α] {a : α} +variable [SemilatticeSup α] [OrderTop α] -- Porting note: Not simp because simp can prove it theorem top_sup_eq (a : α) : ⊤ ⊔ a = ⊤ := @@ -400,7 +400,7 @@ end SemilatticeInfTop section SemilatticeInfBot -variable [SemilatticeInf α] [OrderBot α] {a : α} +variable [SemilatticeInf α] [OrderBot α] -- Porting note: Not simp because simp can prove it lemma bot_inf_eq (a : α) : ⊥ ⊓ a = ⊥ := inf_of_le_left bot_le diff --git a/Mathlib/Order/Bounds/Basic.lean b/Mathlib/Order/Bounds/Basic.lean index 86984514ba3e7..ad3019a2ea838 100644 --- a/Mathlib/Order/Bounds/Basic.lean +++ b/Mathlib/Order/Bounds/Basic.lean @@ -3,26 +3,19 @@ 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 -/ -import Mathlib.Order.Interval.Set.Basic import Mathlib.Data.Set.NAry +import Mathlib.Order.Bounds.Defs import Mathlib.Order.Directed +import Mathlib.Order.Interval.Set.Basic /-! # Upper / lower bounds -In this file we define: -* `upperBounds`, `lowerBounds` : the set of upper bounds (resp., lower bounds) of a set; -* `BddAbove s`, `BddBelow s` : the set `s` is bounded above (resp., below), i.e., the set of upper - (resp., lower) bounds of `s` is nonempty; -* `IsLeast s a`, `IsGreatest s a` : `a` is a least (resp., greatest) element of `s`; - for a partial order, it is unique if exists; -* `IsLUB s a`, `IsGLB s a` : `a` is a least upper bound (resp., a greatest lower bound) - of `s`; for a partial order, it is unique if exists. -We also prove various lemmas about monotonicity, behaviour under `∪`, `∩`, `insert`, and provide -formulas for `∅`, `univ`, and intervals. +In this file we prove various lemmas about upper/lower bounds of a set: +monotonicity, behaviour under `∪`, `∩`, `insert`, +and provide formulas for `∅`, `univ`, and intervals. -/ - open Function Set open OrderDual (toDual ofDual) @@ -35,43 +28,6 @@ section variable [Preorder α] [Preorder β] {s t : Set α} {a b : α} -/-! -### Definitions --/ - - -/-- The set of upper bounds of a set. -/ -def upperBounds (s : Set α) : Set α := - { x | ∀ ⦃a⦄, a ∈ s → a ≤ x } - -/-- The set of lower bounds of a set. -/ -def lowerBounds (s : Set α) : Set α := - { x | ∀ ⦃a⦄, a ∈ s → x ≤ a } - -/-- A set is bounded above if there exists an upper bound. -/ -def BddAbove (s : Set α) := - (upperBounds s).Nonempty - -/-- A set is bounded below if there exists a lower bound. -/ -def BddBelow (s : Set α) := - (lowerBounds s).Nonempty - -/-- `a` is a least element of a set `s`; for a partial order, it is unique if exists. -/ -def IsLeast (s : Set α) (a : α) : Prop := - a ∈ s ∧ a ∈ lowerBounds s - -/-- `a` is a greatest element of a set `s`; for a partial order, it is unique if exists. -/ -def IsGreatest (s : Set α) (a : α) : Prop := - a ∈ s ∧ a ∈ upperBounds s - -/-- `a` is a least upper bound of a set `s`; for a partial order, it is unique if exists. -/ -def IsLUB (s : Set α) : α → Prop := - IsLeast (upperBounds s) - -/-- `a` is a greatest lower bound of a set `s`; for a partial order, it is unique if exists. -/ -def IsGLB (s : Set α) : α → Prop := - IsGreatest (lowerBounds s) - theorem mem_upperBounds : a ∈ upperBounds s ↔ ∀ x ∈ s, x ≤ a := Iff.rfl diff --git a/Mathlib/Order/Bounds/Defs.lean b/Mathlib/Order/Bounds/Defs.lean new file mode 100644 index 0000000000000..3ade7ed08f03d --- /dev/null +++ b/Mathlib/Order/Bounds/Defs.lean @@ -0,0 +1,55 @@ +/- +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 +-/ +import Mathlib.Data.Set.Defs +import Mathlib.Tactic.TypeStar + +/-! +# Definitions about upper/lower bounds + +In this file we define: +* `upperBounds`, `lowerBounds` : the set of upper bounds (resp., lower bounds) of a set; +* `BddAbove s`, `BddBelow s` : the set `s` is bounded above (resp., below), i.e., the set of upper + (resp., lower) bounds of `s` is nonempty; +* `IsLeast s a`, `IsGreatest s a` : `a` is a least (resp., greatest) element of `s`; + for a partial order, it is unique if exists; +* `IsLUB s a`, `IsGLB s a` : `a` is a least upper bound (resp., a greatest lower bound) + of `s`; for a partial order, it is unique if exists. +-/ + +variable {α : Type*} [LE α] + +/-- The set of upper bounds of a set. -/ +def upperBounds (s : Set α) : Set α := + { x | ∀ ⦃a⦄, a ∈ s → a ≤ x } + +/-- The set of lower bounds of a set. -/ +def lowerBounds (s : Set α) : Set α := + { x | ∀ ⦃a⦄, a ∈ s → x ≤ a } + +/-- A set is bounded above if there exists an upper bound. -/ +def BddAbove (s : Set α) := + (upperBounds s).Nonempty + +/-- A set is bounded below if there exists a lower bound. -/ +def BddBelow (s : Set α) := + (lowerBounds s).Nonempty + +/-- `a` is a least element of a set `s`; for a partial order, it is unique if exists. -/ +def IsLeast (s : Set α) (a : α) : Prop := + a ∈ s ∧ a ∈ lowerBounds s + +/-- `a` is a greatest element of a set `s`; for a partial order, it is unique if exists. -/ +def IsGreatest (s : Set α) (a : α) : Prop := + a ∈ s ∧ a ∈ upperBounds s + +/-- `a` is a least upper bound of a set `s`; for a partial order, it is unique if exists. -/ +def IsLUB (s : Set α) : α → Prop := + IsLeast (upperBounds s) + +/-- `a` is a greatest lower bound of a set `s`; for a partial order, it is unique if exists. -/ +def IsGLB (s : Set α) : α → Prop := + IsGreatest (lowerBounds s) + diff --git a/Mathlib/Order/Category/NonemptyFinLinOrd.lean b/Mathlib/Order/Category/NonemptyFinLinOrd.lean index 02b1bfe0adc42..3c6d13dec2f73 100644 --- a/Mathlib/Order/Category/NonemptyFinLinOrd.lean +++ b/Mathlib/Order/Category/NonemptyFinLinOrd.lean @@ -235,3 +235,6 @@ def nonemptyFinLinOrdDualCompForgetToFinPartOrd : forget₂ NonemptyFinLinOrd FinPartOrd ⋙ FinPartOrd.dual where hom := { app := fun X => OrderHom.id } inv := { app := fun X => OrderHom.id } + +/-- The generating arrow `i ⟶ i+1` in the category `Fin n`.-/ +def Fin.hom_succ {n} (i : Fin n) : i.castSucc ⟶ i.succ := homOfLE (Fin.castSucc_le_succ i) diff --git a/Mathlib/Order/Chain.lean b/Mathlib/Order/Chain.lean index 2f086f7f4f276..f8f5ce2631f67 100644 --- a/Mathlib/Order/Chain.lean +++ b/Mathlib/Order/Chain.lean @@ -52,7 +52,7 @@ def SuperChain (s t : Set α) : Prop := def IsMaxChain (s : Set α) : Prop := IsChain r s ∧ ∀ ⦃t⦄, IsChain r t → s ⊆ t → s = t -variable {r} {c c₁ c₂ c₃ s t : Set α} {a b x y : α} +variable {r} {c c₁ c₂ s t : Set α} {a x y : α} theorem isChain_empty : IsChain r ∅ := Set.pairwise_empty _ diff --git a/Mathlib/Order/Closure.lean b/Mathlib/Order/Closure.lean index 4005f3290f47d..53f361b143e1e 100644 --- a/Mathlib/Order/Closure.lean +++ b/Mathlib/Order/Closure.lean @@ -248,7 +248,7 @@ end SemilatticeSup section CompleteLattice -variable [CompleteLattice α] (c : ClosureOperator α) {p : α → Prop} +variable [CompleteLattice α] (c : ClosureOperator α) /-- Define a closure operator from a predicate that's preserved under infima. -/ @[simps!] diff --git a/Mathlib/Order/CompactlyGenerated/Basic.lean b/Mathlib/Order/CompactlyGenerated/Basic.lean index 60620cc7187cf..4fb6ec86d8fa8 100644 --- a/Mathlib/Order/CompactlyGenerated/Basic.lean +++ b/Mathlib/Order/CompactlyGenerated/Basic.lean @@ -189,10 +189,10 @@ theorem isCompactElement_finsetSup {α β : Type*} [CompleteLattice α] {f : β specialize h d hemp hdir (le_trans (Finset.le_sup hps) hsup) simpa only [exists_prop] -theorem WellFounded.isSupFiniteCompact (h : WellFounded ((· > ·) : α → α → Prop)) : +theorem WellFoundedGT.isSupFiniteCompact [WellFoundedGT α] : IsSupFiniteCompact α := fun s => by let S := { x | ∃ t : Finset α, ↑t ⊆ s ∧ t.sup id = x } - obtain ⟨m, ⟨t, ⟨ht₁, rfl⟩⟩, hm⟩ := h.has_min S ⟨⊥, ∅, by simp⟩ + obtain ⟨m, ⟨t, ⟨ht₁, rfl⟩⟩, hm⟩ := wellFounded_gt.has_min S ⟨⊥, ∅, by simp⟩ refine ⟨t, ht₁, (sSup_le _ _ fun y hy => ?_).antisymm ?_⟩ · classical rw [eq_of_le_of_not_lt (Finset.sup_mono (t.subset_insert y)) @@ -212,25 +212,26 @@ theorem IsSupFiniteCompact.isSupClosedCompact (h : IsSupFiniteCompact α) : · rw [ht₂] exact hsc.finsetSup_mem h ht₁ -theorem IsSupClosedCompact.wellFounded (h : IsSupClosedCompact α) : - WellFounded ((· > ·) : α → α → Prop) := by - refine RelEmbedding.wellFounded_iff_no_descending_seq.mpr ⟨fun a => ?_⟩ - suffices sSup (Set.range a) ∈ Set.range a by - obtain ⟨n, hn⟩ := Set.mem_range.mp this - have h' : sSup (Set.range a) < a (n + 1) := by - change _ > _ - simp [← hn, a.map_rel_iff] - apply lt_irrefl (a (n + 1)) - apply lt_of_le_of_lt _ h' - apply le_sSup - apply Set.mem_range_self - apply h (Set.range a) - · use a 37 - apply Set.mem_range_self - · rintro x ⟨m, hm⟩ y ⟨n, hn⟩ - use m ⊔ n - rw [← hm, ← hn] - apply RelHomClass.map_sup a +theorem IsSupClosedCompact.wellFoundedGT (h : IsSupClosedCompact α) : + WellFoundedGT α where + wf := by + refine RelEmbedding.wellFounded_iff_no_descending_seq.mpr ⟨fun a => ?_⟩ + suffices sSup (Set.range a) ∈ Set.range a by + obtain ⟨n, hn⟩ := Set.mem_range.mp this + have h' : sSup (Set.range a) < a (n + 1) := by + change _ > _ + simp [← hn, a.map_rel_iff] + apply lt_irrefl (a (n + 1)) + apply lt_of_le_of_lt _ h' + apply le_sSup + apply Set.mem_range_self + apply h (Set.range a) + · use a 37 + apply Set.mem_range_self + · rintro x ⟨m, hm⟩ y ⟨n, hn⟩ + use m ⊔ n + rw [← hm, ← hn] + apply RelHomClass.map_sup a theorem isSupFiniteCompact_iff_all_elements_compact : IsSupFiniteCompact α ↔ ∀ k : α, IsCompactElement k := by @@ -247,39 +248,38 @@ theorem isSupFiniteCompact_iff_all_elements_compact : exact ⟨t, hts, this⟩ open List in -theorem wellFounded_characterisations : List.TFAE - [WellFounded ((· > ·) : α → α → Prop), - IsSupFiniteCompact α, IsSupClosedCompact α, ∀ k : α, IsCompactElement k] := by - tfae_have 1 → 2 := WellFounded.isSupFiniteCompact α +theorem wellFoundedGT_characterisations : List.TFAE + [WellFoundedGT α, IsSupFiniteCompact α, IsSupClosedCompact α, ∀ k : α, IsCompactElement k] := by + tfae_have 1 → 2 := @WellFoundedGT.isSupFiniteCompact α _ tfae_have 2 → 3 := IsSupFiniteCompact.isSupClosedCompact α - tfae_have 3 → 1 := IsSupClosedCompact.wellFounded α + tfae_have 3 → 1 := IsSupClosedCompact.wellFoundedGT α tfae_have 2 ↔ 4 := isSupFiniteCompact_iff_all_elements_compact α tfae_finish -theorem wellFounded_iff_isSupFiniteCompact : - WellFounded ((· > ·) : α → α → Prop) ↔ IsSupFiniteCompact α := - (wellFounded_characterisations α).out 0 1 +theorem wellFoundedGT_iff_isSupFiniteCompact : + WellFoundedGT α ↔ IsSupFiniteCompact α := + (wellFoundedGT_characterisations α).out 0 1 theorem isSupFiniteCompact_iff_isSupClosedCompact : IsSupFiniteCompact α ↔ IsSupClosedCompact α := - (wellFounded_characterisations α).out 1 2 + (wellFoundedGT_characterisations α).out 1 2 -theorem isSupClosedCompact_iff_wellFounded : - IsSupClosedCompact α ↔ WellFounded ((· > ·) : α → α → Prop) := - (wellFounded_characterisations α).out 2 0 +theorem isSupClosedCompact_iff_wellFoundedGT : + IsSupClosedCompact α ↔ WellFoundedGT α := + (wellFoundedGT_characterisations α).out 2 0 -alias ⟨_, IsSupFiniteCompact.wellFounded⟩ := wellFounded_iff_isSupFiniteCompact +alias ⟨_, IsSupFiniteCompact.wellFoundedGT⟩ := wellFoundedGT_iff_isSupFiniteCompact alias ⟨_, IsSupClosedCompact.isSupFiniteCompact⟩ := isSupFiniteCompact_iff_isSupClosedCompact -alias ⟨_, _root_.WellFounded.isSupClosedCompact⟩ := isSupClosedCompact_iff_wellFounded +alias ⟨_, WellFoundedGT.isSupClosedCompact⟩ := isSupClosedCompact_iff_wellFoundedGT variable {α} -theorem WellFounded.finite_of_setIndependent (h : WellFounded ((· > ·) : α → α → Prop)) {s : Set α} +theorem WellFoundedGT.finite_of_setIndependent [WellFoundedGT α] {s : Set α} (hs : SetIndependent s) : s.Finite := by classical refine Set.not_infinite.mp fun contra => ?_ - obtain ⟨t, ht₁, ht₂⟩ := WellFounded.isSupFiniteCompact α h s + obtain ⟨t, ht₁, ht₂⟩ := WellFoundedGT.isSupFiniteCompact α s replace contra : ∃ x : α, x ∈ s ∧ x ≠ ⊥ ∧ x ∉ t := by have : (s \ (insert ⊥ t : Finset α)).Infinite := contra.diff (Finset.finite_toSet _) obtain ⟨x, hx₁, hx₂⟩ := this.nonempty @@ -292,14 +292,36 @@ theorem WellFounded.finite_of_setIndependent (h : WellFounded ((· > ·) : α rw [← hs, eq_comm, inf_eq_left] exact le_sSup _ _ hx₀ -theorem WellFounded.finite_ne_bot_of_independent (hwf : WellFounded ((· > ·) : α → α → Prop)) +theorem WellFoundedGT.finite_ne_bot_of_independent [WellFoundedGT α] {ι : Type*} {t : ι → α} (ht : Independent t) : Set.Finite {i | t i ≠ ⊥} := by refine Finite.of_finite_image (Finite.subset ?_ (image_subset_range t _)) ht.injOn - exact WellFounded.finite_of_setIndependent hwf ht.setIndependent_range + exact WellFoundedGT.finite_of_setIndependent ht.setIndependent_range -theorem WellFounded.finite_of_independent (hwf : WellFounded ((· > ·) : α → α → Prop)) {ι : Type*} +theorem WellFoundedGT.finite_of_independent [WellFoundedGT α] {ι : Type*} {t : ι → α} (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := - haveI := (WellFounded.finite_of_setIndependent hwf ht.setIndependent_range).to_subtype + haveI := (WellFoundedGT.finite_of_setIndependent ht.setIndependent_range).to_subtype + Finite.of_injective_finite_range (ht.injective h_ne_bot) + +theorem WellFoundedLT.finite_of_setIndependent [WellFoundedLT α] {s : Set α} + (hs : SetIndependent s) : s.Finite := by + by_contra inf + let e := (Infinite.diff inf <| finite_singleton ⊥).to_subtype.natEmbedding + let a n := ⨆ i ≥ n, (e i).1 + have sup_le n : (e n).1 ⊔ a (n + 1) ≤ a n := sup_le_iff.mpr ⟨le_iSup₂_of_le n le_rfl le_rfl, + iSup₂_le fun i hi ↦ le_iSup₂_of_le i (n.le_succ.trans hi) le_rfl⟩ + have lt n : a (n + 1) < a n := (Disjoint.right_lt_sup_of_left_ne_bot + ((hs (e n).2.1).mono_right <| iSup₂_le fun i hi ↦ le_sSup _ _ ?_) (e n).2.2).trans_le (sup_le n) + · exact (RelEmbedding.natGT a lt).not_wellFounded_of_decreasing_seq wellFounded_lt + exact ⟨(e i).2.1, fun h ↦ n.lt_succ_self.not_le <| hi.trans_eq <| e.2 <| Subtype.val_injective h⟩ + +theorem WellFoundedLT.finite_ne_bot_of_independent [WellFoundedLT α] + {ι : Type*} {t : ι → α} (ht : Independent t) : Set.Finite {i | t i ≠ ⊥} := by + refine Finite.of_finite_image (Finite.subset ?_ (image_subset_range t _)) ht.injOn + exact WellFoundedLT.finite_of_setIndependent ht.setIndependent_range + +theorem WellFoundedLT.finite_of_independent [WellFoundedLT α] {ι : Type*} + {t : ι → α} (ht : Independent t) (h_ne_bot : ∀ i, t i ≠ ⊥) : Finite ι := + haveI := (WellFoundedLT.finite_of_setIndependent ht.setIndependent_range).to_subtype Finite.of_injective_finite_range (ht.injective h_ne_bot) end CompleteLattice @@ -313,7 +335,7 @@ class IsCompactlyGenerated (α : Type*) [CompleteLattice α] : Prop where section -variable [IsCompactlyGenerated α] {a b : α} {s : Set α} +variable [IsCompactlyGenerated α] {a : α} {s : Set α} @[simp] theorem sSup_compact_le_eq (b) : @@ -452,12 +474,35 @@ end namespace CompleteLattice -theorem isCompactlyGenerated_of_wellFounded (h : WellFounded ((· > ·) : α → α → Prop)) : +theorem isCompactlyGenerated_of_wellFoundedGT [h : WellFoundedGT α] : IsCompactlyGenerated α := by - rw [wellFounded_iff_isSupFiniteCompact, isSupFiniteCompact_iff_all_elements_compact] at h + rw [wellFoundedGT_iff_isSupFiniteCompact, isSupFiniteCompact_iff_all_elements_compact] at h -- x is the join of the set of compact elements {x} exact ⟨fun x => ⟨{x}, ⟨fun x _ => h x, sSup_singleton⟩⟩⟩ +@[deprecated (since := "2024-10-07")] +alias WellFounded.isSupFiniteCompact := WellFoundedGT.isSupFiniteCompact +@[deprecated (since := "2024-10-07")] +alias IsSupClosedCompact.wellFounded := IsSupClosedCompact.wellFoundedGT +@[deprecated (since := "2024-10-07")] +alias wellFounded_characterisations := wellFoundedGT_characterisations +@[deprecated (since := "2024-10-07")] +alias wellFounded_iff_isSupFiniteCompact := wellFoundedGT_iff_isSupFiniteCompact +@[deprecated (since := "2024-10-07")] +alias isSupClosedCompact_iff_wellFounded := isSupClosedCompact_iff_wellFoundedGT +@[deprecated (since := "2024-10-07")] +alias IsSupFiniteCompact.wellFounded := IsSupFiniteCompact.wellFoundedGT +@[deprecated (since := "2024-10-07")] +alias _root_.WellFounded.isSupClosedCompact := WellFoundedGT.isSupClosedCompact +@[deprecated (since := "2024-10-07")] +alias WellFounded.finite_of_setIndependent := WellFoundedGT.finite_of_setIndependent +@[deprecated (since := "2024-10-07")] +alias WellFounded.finite_ne_bot_of_independent := WellFoundedGT.finite_ne_bot_of_independent +@[deprecated (since := "2024-10-07")] +alias WellFounded.finite_of_independent := WellFoundedGT.finite_of_independent +@[deprecated (since := "2024-10-07")] +alias isCompactlyGenerated_of_wellFounded := isCompactlyGenerated_of_wellFoundedGT + /-- A compact element `k` has the property that any `b < k` lies below a "maximal element below `k`", which is to say `[⊥, k]` is coatomic. -/ theorem Iic_coatomic_of_compact_element {k : α} (h : IsCompactElement k) : diff --git a/Mathlib/Order/CompleteLattice/Finset.lean b/Mathlib/Order/CompleteLattice/Finset.lean new file mode 100644 index 0000000000000..b02e5eb918efa --- /dev/null +++ b/Mathlib/Order/CompleteLattice/Finset.lean @@ -0,0 +1,247 @@ +/- +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.Finset.Option +import Mathlib.Data.Set.Lattice + +/-! +# Lattice operations on finsets + +This file is concerned with how big lattice or set operations behave when indexed by a finset. + +See also Lattice.lean, which is concerned with folding binary lattice operations over a finset. +-/ + +assert_not_exists OrderedCommMonoid +assert_not_exists MonoidWithZero + +open Function Multiset OrderDual + +variable {F α β γ ι κ : Type*} + +section Lattice + +variable {ι' : Sort*} [CompleteLattice α] + +/-- Supremum of `s i`, `i : ι`, is equal to the supremum over `t : Finset ι` of suprema +`⨆ i ∈ t, s i`. This version assumes `ι` is a `Type*`. See `iSup_eq_iSup_finset'` for a version +that works for `ι : Sort*`. -/ +theorem iSup_eq_iSup_finset (s : ι → α) : ⨆ i, s i = ⨆ t : Finset ι, ⨆ i ∈ t, s i := by + classical + refine le_antisymm ?_ ?_ + · exact iSup_le fun b => le_iSup_of_le {b} <| le_iSup_of_le b <| le_iSup_of_le (by simp) <| le_rfl + · exact iSup_le fun t => iSup_le fun b => iSup_le fun _ => le_iSup _ _ + +/-- Supremum of `s i`, `i : ι`, is equal to the supremum over `t : Finset ι` of suprema +`⨆ i ∈ t, s i`. This version works for `ι : Sort*`. See `iSup_eq_iSup_finset` for a version +that assumes `ι : Type*` but has no `PLift`s. -/ +theorem iSup_eq_iSup_finset' (s : ι' → α) : + ⨆ i, s i = ⨆ t : Finset (PLift ι'), ⨆ i ∈ t, s (PLift.down i) := by + rw [← iSup_eq_iSup_finset, ← Equiv.plift.surjective.iSup_comp]; rfl + +/-- Infimum of `s i`, `i : ι`, is equal to the infimum over `t : Finset ι` of infima +`⨅ i ∈ t, s i`. This version assumes `ι` is a `Type*`. See `iInf_eq_iInf_finset'` for a version +that works for `ι : Sort*`. -/ +theorem iInf_eq_iInf_finset (s : ι → α) : ⨅ i, s i = ⨅ (t : Finset ι) (i ∈ t), s i := + @iSup_eq_iSup_finset αᵒᵈ _ _ _ + +/-- Infimum of `s i`, `i : ι`, is equal to the infimum over `t : Finset ι` of infima +`⨅ i ∈ t, s i`. This version works for `ι : Sort*`. See `iInf_eq_iInf_finset` for a version +that assumes `ι : Type*` but has no `PLift`s. -/ +theorem iInf_eq_iInf_finset' (s : ι' → α) : + ⨅ i, s i = ⨅ t : Finset (PLift ι'), ⨅ i ∈ t, s (PLift.down i) := + @iSup_eq_iSup_finset' αᵒᵈ _ _ _ + +end Lattice + +namespace Set + +variable {ι' : Sort*} + +/-- Union of an indexed family of sets `s : ι → Set α` is equal to the union of the unions +of finite subfamilies. This version assumes `ι : Type*`. See also `iUnion_eq_iUnion_finset'` for +a version that works for `ι : Sort*`. -/ +theorem iUnion_eq_iUnion_finset (s : ι → Set α) : ⋃ i, s i = ⋃ t : Finset ι, ⋃ i ∈ t, s i := + iSup_eq_iSup_finset s + +/-- Union of an indexed family of sets `s : ι → Set α` is equal to the union of the unions +of finite subfamilies. This version works for `ι : Sort*`. See also `iUnion_eq_iUnion_finset` for +a version that assumes `ι : Type*` but avoids `PLift`s in the right hand side. -/ +theorem iUnion_eq_iUnion_finset' (s : ι' → Set α) : + ⋃ i, s i = ⋃ t : Finset (PLift ι'), ⋃ i ∈ t, s (PLift.down i) := + iSup_eq_iSup_finset' s + +/-- Intersection of an indexed family of sets `s : ι → Set α` is equal to the intersection of the +intersections of finite subfamilies. This version assumes `ι : Type*`. See also +`iInter_eq_iInter_finset'` for a version that works for `ι : Sort*`. -/ +theorem iInter_eq_iInter_finset (s : ι → Set α) : ⋂ i, s i = ⋂ t : Finset ι, ⋂ i ∈ t, s i := + iInf_eq_iInf_finset s + +/-- Intersection of an indexed family of sets `s : ι → Set α` is equal to the intersection of the +intersections of finite subfamilies. This version works for `ι : Sort*`. See also +`iInter_eq_iInter_finset` for a version that assumes `ι : Type*` but avoids `PLift`s in the right +hand side. -/ +theorem iInter_eq_iInter_finset' (s : ι' → Set α) : + ⋂ i, s i = ⋂ t : Finset (PLift ι'), ⋂ i ∈ t, s (PLift.down i) := + iInf_eq_iInf_finset' s + +end Set + +namespace Finset + +section minimal + +variable [DecidableEq α] {P : Finset α → Prop} {s : Finset α} + +theorem maximal_iff_forall_insert (hP : ∀ ⦃s t⦄, P t → s ⊆ t → P s) : + Maximal P s ↔ P s ∧ ∀ x ∉ s, ¬ P (insert x s) := by + simp only [Maximal, and_congr_right_iff] + exact fun _ ↦ ⟨fun h x hxs hx ↦ hxs <| h hx (subset_insert _ _) (mem_insert_self x s), + fun h t ht hst x hxt ↦ by_contra fun hxs ↦ h x hxs (hP ht (insert_subset hxt hst))⟩ + +theorem minimal_iff_forall_diff_singleton (hP : ∀ ⦃s t⦄, P t → t ⊆ s → P s) : + Minimal P s ↔ P s ∧ ∀ x ∈ s, ¬ P (s.erase x) where + mp h := ⟨h.prop, fun x hxs hx ↦ by simpa using h.le_of_le hx (erase_subset _ _) hxs⟩ + mpr h := ⟨h.1, fun t ht hts x hxs ↦ by_contra fun hxt ↦ + h.2 x hxs <| hP ht (subset_erase.2 ⟨hts, hxt⟩)⟩ + +end minimal + +/-! ### Interaction with big lattice/set operations -/ + +section Lattice + +theorem iSup_coe [SupSet β] (f : α → β) (s : Finset α) : ⨆ x ∈ (↑s : Set α), f x = ⨆ x ∈ s, f x := + rfl + +theorem iInf_coe [InfSet β] (f : α → β) (s : Finset α) : ⨅ x ∈ (↑s : Set α), f x = ⨅ x ∈ s, f x := + rfl + +variable [CompleteLattice β] + +theorem iSup_singleton (a : α) (s : α → β) : ⨆ x ∈ ({a} : Finset α), s x = s a := by simp + +theorem iInf_singleton (a : α) (s : α → β) : ⨅ x ∈ ({a} : Finset α), s x = s a := by simp + +theorem iSup_option_toFinset (o : Option α) (f : α → β) : ⨆ x ∈ o.toFinset, f x = ⨆ x ∈ o, f x := by + simp + +theorem iInf_option_toFinset (o : Option α) (f : α → β) : ⨅ x ∈ o.toFinset, f x = ⨅ x ∈ o, f x := + @iSup_option_toFinset _ βᵒᵈ _ _ _ + +variable [DecidableEq α] + +theorem iSup_union {f : α → β} {s t : Finset α} : + ⨆ x ∈ s ∪ t, f x = (⨆ x ∈ s, f x) ⊔ ⨆ x ∈ t, f x := by simp [iSup_or, iSup_sup_eq] + +theorem iInf_union {f : α → β} {s t : Finset α} : + ⨅ x ∈ s ∪ t, f x = (⨅ x ∈ s, f x) ⊓ ⨅ x ∈ t, f x := + @iSup_union α βᵒᵈ _ _ _ _ _ + +theorem iSup_insert (a : α) (s : Finset α) (t : α → β) : + ⨆ x ∈ insert a s, t x = t a ⊔ ⨆ x ∈ s, t x := by + rw [insert_eq] + simp only [iSup_union, Finset.iSup_singleton] + +theorem iInf_insert (a : α) (s : Finset α) (t : α → β) : + ⨅ x ∈ insert a s, t x = t a ⊓ ⨅ x ∈ s, t x := + @iSup_insert α βᵒᵈ _ _ _ _ _ + +theorem iSup_finset_image {f : γ → α} {g : α → β} {s : Finset γ} : + ⨆ x ∈ s.image f, g x = ⨆ y ∈ s, g (f y) := by rw [← iSup_coe, coe_image, iSup_image, iSup_coe] + +theorem iInf_finset_image {f : γ → α} {g : α → β} {s : Finset γ} : + ⨅ x ∈ s.image f, g x = ⨅ y ∈ s, g (f y) := by rw [← iInf_coe, coe_image, iInf_image, iInf_coe] + +theorem iSup_insert_update {x : α} {t : Finset α} (f : α → β) {s : β} (hx : x ∉ t) : + ⨆ i ∈ insert x t, Function.update f x s i = s ⊔ ⨆ i ∈ t, f i := by + simp only [Finset.iSup_insert, update_same] + rcongr (i hi); apply update_noteq; rintro rfl; exact hx hi + +theorem iInf_insert_update {x : α} {t : Finset α} (f : α → β) {s : β} (hx : x ∉ t) : + ⨅ i ∈ insert x t, update f x s i = s ⊓ ⨅ i ∈ t, f i := + @iSup_insert_update α βᵒᵈ _ _ _ _ f _ hx + +theorem iSup_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → β) : + ⨆ y ∈ s.biUnion t, f y = ⨆ (x ∈ s) (y ∈ t x), f y := by simp [@iSup_comm _ α, iSup_and] + +theorem iInf_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → β) : + ⨅ y ∈ s.biUnion t, f y = ⨅ (x ∈ s) (y ∈ t x), f y := + @iSup_biUnion _ βᵒᵈ _ _ _ _ _ _ + +end Lattice + +theorem set_biUnion_coe (s : Finset α) (t : α → Set β) : ⋃ x ∈ (↑s : Set α), t x = ⋃ x ∈ s, t x := + rfl + +theorem set_biInter_coe (s : Finset α) (t : α → Set β) : ⋂ x ∈ (↑s : Set α), t x = ⋂ x ∈ s, t x := + rfl + +theorem set_biUnion_singleton (a : α) (s : α → Set β) : ⋃ x ∈ ({a} : Finset α), s x = s a := + iSup_singleton a s + +theorem set_biInter_singleton (a : α) (s : α → Set β) : ⋂ x ∈ ({a} : Finset α), s x = s a := + iInf_singleton a s + +@[simp] +theorem set_biUnion_preimage_singleton (f : α → β) (s : Finset β) : + ⋃ y ∈ s, f ⁻¹' {y} = f ⁻¹' s := + Set.biUnion_preimage_singleton f s + +theorem set_biUnion_option_toFinset (o : Option α) (f : α → Set β) : + ⋃ x ∈ o.toFinset, f x = ⋃ x ∈ o, f x := + iSup_option_toFinset o f + +theorem set_biInter_option_toFinset (o : Option α) (f : α → Set β) : + ⋂ x ∈ o.toFinset, f x = ⋂ x ∈ o, f x := + iInf_option_toFinset o f + +theorem subset_set_biUnion_of_mem {s : Finset α} {f : α → Set β} {x : α} (h : x ∈ s) : + f x ⊆ ⋃ y ∈ s, f y := + show f x ≤ ⨆ y ∈ s, f y from le_iSup_of_le x <| by simp only [h, iSup_pos, le_refl] + +variable [DecidableEq α] + +theorem set_biUnion_union (s t : Finset α) (u : α → Set β) : + ⋃ x ∈ s ∪ t, u x = (⋃ x ∈ s, u x) ∪ ⋃ x ∈ t, u x := + iSup_union + +theorem set_biInter_inter (s t : Finset α) (u : α → Set β) : + ⋂ x ∈ s ∪ t, u x = (⋂ x ∈ s, u x) ∩ ⋂ x ∈ t, u x := + iInf_union + +theorem set_biUnion_insert (a : α) (s : Finset α) (t : α → Set β) : + ⋃ x ∈ insert a s, t x = t a ∪ ⋃ x ∈ s, t x := + iSup_insert a s t + +theorem set_biInter_insert (a : α) (s : Finset α) (t : α → Set β) : + ⋂ x ∈ insert a s, t x = t a ∩ ⋂ x ∈ s, t x := + iInf_insert a s t + +theorem set_biUnion_finset_image {f : γ → α} {g : α → Set β} {s : Finset γ} : + ⋃ x ∈ s.image f, g x = ⋃ y ∈ s, g (f y) := + iSup_finset_image + +theorem set_biInter_finset_image {f : γ → α} {g : α → Set β} {s : Finset γ} : + ⋂ x ∈ s.image f, g x = ⋂ y ∈ s, g (f y) := + iInf_finset_image + +theorem set_biUnion_insert_update {x : α} {t : Finset α} (f : α → Set β) {s : Set β} (hx : x ∉ t) : + ⋃ i ∈ insert x t, @update _ _ _ f x s i = s ∪ ⋃ i ∈ t, f i := + iSup_insert_update f hx + +theorem set_biInter_insert_update {x : α} {t : Finset α} (f : α → Set β) {s : Set β} (hx : x ∉ t) : + ⋂ i ∈ insert x t, @update _ _ _ f x s i = s ∩ ⋂ i ∈ t, f i := + iInf_insert_update f hx + +theorem set_biUnion_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → Set β) : + ⋃ y ∈ s.biUnion t, f y = ⋃ (x ∈ s) (y ∈ t x), f y := + iSup_biUnion s t f + +theorem set_biInter_biUnion (s : Finset γ) (t : γ → Finset α) (f : α → Set β) : + ⋂ y ∈ s.biUnion t, f y = ⋂ (x ∈ s) (y ∈ t x), f y := + iInf_biUnion s t f + +end Finset diff --git a/Mathlib/Order/Concept.lean b/Mathlib/Order/Concept.lean index b4818c18d6fc2..ea202e9b33def 100644 --- a/Mathlib/Order/Concept.lean +++ b/Mathlib/Order/Concept.lean @@ -37,8 +37,7 @@ concept, formal concept analysis, intent, extend, attribute open Function OrderDual Set -variable {ι : Sort*} {α β γ : Type*} {κ : ι → Sort*} (r : α → β → Prop) {s s₁ s₂ : Set α} - {t t₁ t₂ : Set β} +variable {ι : Sort*} {α β : Type*} {κ : ι → Sort*} (r : α → β → Prop) {s : Set α} {t : Set β} /-! ### Intent and extent -/ diff --git a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean index 9f80770bcdc85..7910ab0ffc59a 100644 --- a/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean +++ b/Mathlib/Order/ConditionallyCompleteLattice/Basic.lean @@ -219,16 +219,12 @@ complete linear orders, we prefix `sInf` and `sSup` by a `c` everywhere. The sam hold in both worlds, sometimes with additional assumptions of nonemptiness or boundedness. -/ class ConditionallyCompleteLinearOrderBot (α : Type*) extends ConditionallyCompleteLinearOrder α, - Bot α where - /-- `⊥` is the least element -/ - bot_le : ∀ x : α, ⊥ ≤ x - /-- The supremum of the empty set is `⊥` -/ + OrderBot α where + /-- The supremum of the empty set is special-cased to `⊥` -/ csSup_empty : sSup ∅ = ⊥ -- see Note [lower instance priority] -instance (priority := 100) ConditionallyCompleteLinearOrderBot.toOrderBot - [h : ConditionallyCompleteLinearOrderBot α] : OrderBot α := - { h with } +attribute [instance 100] ConditionallyCompleteLinearOrderBot.toOrderBot -- see Note [lower instance priority] /-- A complete lattice is a conditionally complete lattice, as there are no restrictions diff --git a/Mathlib/Order/CountableDenseLinearOrder.lean b/Mathlib/Order/CountableDenseLinearOrder.lean index 1527b05b689ea..1ab3a1faebbc2 100644 --- a/Mathlib/Order/CountableDenseLinearOrder.lean +++ b/Mathlib/Order/CountableDenseLinearOrder.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: David Wärn -/ import Mathlib.Order.Ideal -import Mathlib.Data.Finset.Lattice +import Mathlib.Data.Finset.Max /-! # The back and forth method and countable dense linear orders diff --git a/Mathlib/Order/Cover.lean b/Mathlib/Order/Cover.lean index 17ba059d015c4..cf13cbab95f7f 100644 --- a/Mathlib/Order/Cover.lean +++ b/Mathlib/Order/Cover.lean @@ -591,3 +591,19 @@ variable [Preorder α] {a b : α} simp only [wcovBy_iff_Ioo_eq, ← image_coe_Iio, bot_le, image_eq_empty, true_and, Iio_eq_empty_iff] end WithBot + +section WellFounded + +variable [Preorder α] + +lemma exists_covBy_of_wellFoundedLT [wf : WellFoundedLT α] ⦃a : α⦄ (h : ¬ IsMax a) : + ∃ a', a ⋖ a' := by + rw [not_isMax_iff] at h + exact ⟨_, wellFounded_lt.min_mem _ h, fun a' ↦ wf.wf.not_lt_min _ h⟩ + +lemma exists_covBy_of_wellFoundedGT [wf : WellFoundedGT α] ⦃a : α⦄ (h : ¬ IsMin a) : + ∃ a', a' ⋖ a := by + rw [not_isMin_iff] at h + exact ⟨_, wf.wf.min_mem _ h, fun a' h₁ h₂ ↦ wf.wf.not_lt_min _ h h₂ h₁⟩ + +end WellFounded diff --git a/Mathlib/Order/Defs.lean b/Mathlib/Order/Defs.lean index c53c3b994e122..7a46f0ce76cf7 100644 --- a/Mathlib/Order/Defs.lean +++ b/Mathlib/Order/Defs.lean @@ -184,6 +184,32 @@ end end +/-! ### Minimal and maximal -/ + +section LE + +variable {α : Type*} [LE α] {P : α → Prop} {x y : α} + +/-- `Minimal P x` means that `x` is a minimal element satisfying `P`. -/ +def Minimal (P : α → Prop) (x : α) : Prop := P x ∧ ∀ ⦃y⦄, P y → y ≤ x → x ≤ y + +/-- `Maximal P x` means that `x` is a maximal element satisfying `P`. -/ +def Maximal (P : α → Prop) (x : α) : Prop := P x ∧ ∀ ⦃y⦄, P y → x ≤ y → y ≤ x + +lemma Minimal.prop (h : Minimal P x) : P x := + h.1 + +lemma Maximal.prop (h : Maximal P x) : P x := + h.1 + +lemma Minimal.le_of_le (h : Minimal P x) (hy : P y) (hle : y ≤ x) : x ≤ y := + h.2 hy hle + +lemma Maximal.le_of_ge (h : Maximal P x) (hy : P y) (hge : x ≤ y) : y ≤ x := + h.2 hy hge + +end LE + /-! ### Bundled classes -/ variable {α : Type*} @@ -357,7 +383,7 @@ macro "compareOfLessAndEq_rfl" : tactic => /-- A linear order is reflexive, transitive, antisymmetric and total relation `≤`. We assume that every linear ordered type has decidable `(≤)`, `(<)`, and `(=)`. -/ -class LinearOrder (α : Type*) extends PartialOrder α, Min α, Max α, Ord α := +class LinearOrder (α : Type*) extends PartialOrder α, Min α, Max α, Ord α where /-- A linear order is total. -/ le_total (a b : α) : a ≤ b ∨ b ≤ a /-- In a linearly ordered type, we assume the order relations are all decidable. -/ @@ -501,10 +527,13 @@ lemma min_comm (a b : α) : min a b = min b a := lemma min_assoc (a b c : α) : min (min a b) c = min a (min b c) := by apply eq_min - · apply le_trans; apply min_le_left; apply min_le_left - · apply le_min; apply le_trans; apply min_le_left; apply min_le_right; apply min_le_right - · intro d h₁ h₂; apply le_min; apply le_min h₁; apply le_trans h₂; apply min_le_left - apply le_trans h₂; apply min_le_right + · apply le_trans (min_le_left ..); apply min_le_left + · apply le_min + · apply le_trans (min_le_left ..); apply min_le_right + · apply min_le_right + · intro d h₁ h₂; apply le_min + · apply le_min h₁; apply le_trans h₂; apply min_le_left + · apply le_trans h₂; apply min_le_right lemma min_left_comm (a b c : α) : min a (min b c) = min b (min a c) := by rw [← min_assoc, min_comm a, min_assoc] @@ -525,10 +554,13 @@ lemma max_comm (a b : α) : max a b = max b a := lemma max_assoc (a b c : α) : max (max a b) c = max a (max b c) := by apply eq_max - · apply le_trans; apply le_max_left a b; apply le_max_left - · apply max_le; apply le_trans; apply le_max_right a b; apply le_max_left; apply le_max_right - · intro d h₁ h₂; apply max_le; apply max_le h₁; apply le_trans (le_max_left _ _) h₂ - apply le_trans (le_max_right _ _) h₂ + · apply le_trans (le_max_left a b); apply le_max_left + · apply max_le + · apply le_trans (le_max_right a b); apply le_max_left + · apply le_max_right + · intro d h₁ h₂; apply max_le + · apply max_le h₁; apply le_trans (le_max_left _ _) h₂ + · apply le_trans (le_max_right _ _) h₂ lemma max_left_comm (a b c : α) : max a (max b c) = max b (max a c) := by rw [← max_assoc, max_comm a, max_assoc] @@ -552,7 +584,6 @@ lemma max_lt (h₁ : a < c) (h₂ : b < c) : max a b < c := by cases le_total a b <;> simp [max_eq_left, max_eq_right, *] section Ord -variable {o : Ordering} lemma compare_lt_iff_lt : compare a b = .lt ↔ a < b := by rw [LinearOrder.compare_eq_compareOfLessAndEq, compareOfLessAndEq] @@ -590,7 +621,17 @@ lemma compare_iff (a b : α) {o : Ordering} : compare a b = o ↔ o.Compares a b · exact compare_eq_iff_eq · exact compare_gt_iff_gt -instance : Batteries.TransCmp (compare (α := α)) where +theorem cmp_eq_compare (a b : α) : cmp a b = compare a b := by + refine ((compare_iff ..).2 ?_).symm + unfold cmp cmpUsing; split_ifs with h1 h2 + · exact h1 + · exact h2 + · exact le_antisymm (not_lt.1 h2) (not_lt.1 h1) + +theorem cmp_eq_compareOfLessAndEq (a b : α) : cmp a b = compareOfLessAndEq a b := + (cmp_eq_compare ..).trans (LinearOrder.compare_eq_compareOfLessAndEq ..) + +instance : Batteries.LawfulCmp (compare (α := α)) where symm a b := by cases h : compare a b <;> simp only [Ordering.swap] <;> symm @@ -599,6 +640,9 @@ instance : Batteries.TransCmp (compare (α := α)) where · exact compare_lt_iff_lt.2 <| compare_gt_iff_gt.1 h le_trans := fun h₁ h₂ ↦ compare_le_iff_le.2 <| le_trans (compare_le_iff_le.1 h₁) (compare_le_iff_le.1 h₂) + cmp_iff_beq := by simp [compare_eq_iff_eq] + cmp_iff_lt := by simp [compare_lt_iff_lt] + cmp_iff_le := by simp [compare_le_iff_le] end Ord diff --git a/Mathlib/Order/Directed.lean b/Mathlib/Order/Directed.lean index 39d27f9b220b1..29285fca18124 100644 --- a/Mathlib/Order/Directed.lean +++ b/Mathlib/Order/Directed.lean @@ -167,7 +167,7 @@ instance OrderDual.isDirected_le [LE α] [IsDirected α (· ≥ ·)] : IsDirecte /-- A monotone function on an upwards-directed type is directed. -/ theorem directed_of_isDirected_le [LE α] [IsDirected α (· ≤ ·)] {f : α → β} {r : β → β → Prop} (H : ∀ ⦃i j⦄, i ≤ j → r (f i) (f j)) : Directed r f := - directed_id.mono_comp H + directed_id.mono_comp _ H theorem Monotone.directed_le [Preorder α] [IsDirected α (· ≤ ·)] [Preorder β] {f : α → β} : Monotone f → Directed (· ≤ ·) f := diff --git a/Mathlib/Order/Disjoint.lean b/Mathlib/Order/Disjoint.lean index 29678782f984f..959e072e1b1b6 100644 --- a/Mathlib/Order/Disjoint.lean +++ b/Mathlib/Order/Disjoint.lean @@ -108,7 +108,7 @@ end PartialBoundedOrder section SemilatticeInfBot -variable [SemilatticeInf α] [OrderBot α] {a b c d : α} +variable [SemilatticeInf α] [OrderBot α] {a b c : α} theorem disjoint_iff_inf_le : Disjoint a b ↔ a ⊓ b ≤ ⊥ := ⟨fun hd ↦ hd inf_le_left inf_le_right, fun h _ ha hb ↦ (le_inf ha hb).trans h⟩ @@ -155,6 +155,10 @@ theorem Disjoint.of_disjoint_inf_of_le' (h : Disjoint (a ⊓ b) c) (hle : b ≤ end SemilatticeInfBot +theorem Disjoint.right_lt_sup_of_left_ne_bot [SemilatticeSup α] [OrderBot α] {a b : α} + (h : Disjoint a b) (ha : a ≠ ⊥) : b < a ⊔ b := + le_sup_right.lt_of_ne fun eq ↦ ha (le_bot_iff.mp <| h le_rfl <| sup_eq_right.mp eq.symm) + section DistribLatticeBot variable [DistribLattice α] [OrderBot α] {a b c : α} @@ -267,7 +271,7 @@ end PartialBoundedOrder section SemilatticeSupTop -variable [SemilatticeSup α] [OrderTop α] {a b c d : α} +variable [SemilatticeSup α] [OrderTop α] {a b c : α} theorem codisjoint_iff_le_sup : Codisjoint a b ↔ ⊤ ≤ a ⊔ b := @disjoint_iff_inf_le αᵒᵈ _ _ _ _ @@ -401,7 +405,7 @@ namespace IsCompl section BoundedPartialOrder -variable [PartialOrder α] [BoundedOrder α] {x y z : α} +variable [PartialOrder α] [BoundedOrder α] {x y : α} @[symm] protected theorem symm (h : IsCompl x y) : IsCompl y x := @@ -419,7 +423,7 @@ end BoundedPartialOrder section BoundedLattice -variable [Lattice α] [BoundedOrder α] {x y z : α} +variable [Lattice α] [BoundedOrder α] {x y : α} theorem of_le (h₁ : x ⊓ y ≤ ⊥) (h₂ : ⊤ ≤ x ⊔ y) : IsCompl x y := ⟨disjoint_iff_inf_le.mpr h₁, codisjoint_iff_le_sup.mpr h₂⟩ diff --git a/Mathlib/Order/Filter/AtTopBot.lean b/Mathlib/Order/Filter/AtTopBot.lean index eda822fe73f47..18b4a5cf5790c 100644 --- a/Mathlib/Order/Filter/AtTopBot.lean +++ b/Mathlib/Order/Filter/AtTopBot.lean @@ -6,7 +6,9 @@ Authors: Johannes Hölzl, Jeremy Avigad, Yury Kudryashov, Patrick Massot import Mathlib.Data.Finset.Preimage import Mathlib.Order.ConditionallyCompleteLattice.Basic import Mathlib.Order.Filter.Bases +import Mathlib.Order.Filter.Prod import Mathlib.Order.Interval.Set.Disjoint +import Mathlib.Order.Interval.Set.OrderIso /-! # `Filter.atTop` and `Filter.atBot` filters on preorders, monoids and groups. @@ -257,6 +259,15 @@ variable [Nonempty α] @[instance] lemma atTop_neBot : NeBot (atTop : Filter α) := atTop_basis.neBot_iff.2 fun _ => nonempty_Ici +theorem atTop_neBot_iff {α : Type*} [Preorder α] : + (atTop : Filter α).NeBot ↔ Nonempty α ∧ IsDirected α (· ≤ ·) := by + refine ⟨fun h ↦ ⟨nonempty_of_neBot atTop, ⟨fun x y ↦ ?_⟩⟩, fun ⟨h₁, h₂⟩ ↦ atTop_neBot⟩ + exact ((eventually_ge_atTop x).and (eventually_ge_atTop y)).exists + +theorem atBot_neBot_iff {α : Type*} [Preorder α] : + (atBot : Filter α).NeBot ↔ Nonempty α ∧ IsDirected α (· ≥ ·) := + atTop_neBot_iff (α := αᵒᵈ) + @[simp] lemma mem_atTop_sets {s : Set α} : s ∈ (atTop : Filter α) ↔ ∃ a : α, ∀ b ≥ a, b ∈ s := atTop_basis.mem_iff.trans <| exists_congr fun _ => iff_of_eq (true_and _) @@ -1215,3 +1226,45 @@ theorem Antitone.piecewise_eventually_eq_iInter {β : α → Type*} [Preorder ι convert ← (compl_anti.comp hs).piecewise_eventually_eq_iUnion g f a using 3 · convert congr_fun (Set.piecewise_compl (s _) g f) a · simp only [(· ∘ ·), ← compl_iInter, Set.piecewise_compl] + +namespace Nat + +theorem eventually_pow_lt_factorial_sub (c d : ℕ) : ∀ᶠ n in atTop, c ^ n < (n - d)! := by + rw [eventually_atTop] + refine ⟨2 * (c ^ 2 + d + 1), ?_⟩ + intro n hn + obtain ⟨d', rfl⟩ := Nat.exists_eq_add_of_le hn + obtain (rfl | c0) := c.eq_zero_or_pos + · simp [Nat.two_mul, ← Nat.add_assoc, Nat.add_right_comm _ 1, Nat.factorial_pos] + refine (Nat.le_mul_of_pos_right _ (Nat.pow_pos (n := d') c0)).trans_lt ?_ + convert_to (c ^ 2) ^ (c ^ 2 + d' + d + 1) < (c ^ 2 + (c ^ 2 + d' + d + 1) + 1)! + · rw [← pow_mul, ← pow_add] + congr 1 + omega + · congr 1 + omega + refine (lt_of_lt_of_le ?_ Nat.factorial_mul_pow_le_factorial).trans_le <| + (factorial_le (Nat.le_succ _)) + rw [← one_mul (_ ^ _ : ℕ)] + apply Nat.mul_lt_mul_of_le_of_lt + · exact Nat.one_le_of_lt (Nat.factorial_pos _) + · exact Nat.pow_lt_pow_left (Nat.lt_succ_self _) (Nat.succ_ne_zero _) + · exact (Nat.factorial_pos _) + +theorem eventually_mul_pow_lt_factorial_sub (a c d : ℕ) : + ∀ᶠ n in atTop, a * c ^ n < (n - d)! := by + filter_upwards [Nat.eventually_pow_lt_factorial_sub (a * c) d, Filter.eventually_gt_atTop 0] + with n hn hn0 + rw [mul_pow] at hn + exact (Nat.mul_le_mul_right _ (Nat.le_self_pow hn0.ne' _)).trans_lt hn + +@[deprecated eventually_pow_lt_factorial_sub (since := "2024-09-25")] +theorem exists_pow_lt_factorial (c : ℕ) : ∃ n0 > 1, ∀ n ≥ n0, c ^ n < (n - 1)! := + let ⟨n0, h⟩ := (eventually_pow_lt_factorial_sub c 1).exists_forall_of_atTop + ⟨max n0 2, by omega, fun n hn ↦ h n (by omega)⟩ + +@[deprecated eventually_mul_pow_lt_factorial_sub (since := "2024-09-25")] +theorem exists_mul_pow_lt_factorial (a : ℕ) (c : ℕ) : ∃ n0, ∀ n ≥ n0, a * c ^ n < (n - 1)! := + (eventually_mul_pow_lt_factorial_sub a c 1).exists_forall_of_atTop + +end Nat diff --git a/Mathlib/Order/Filter/AtTopBot/Floor.lean b/Mathlib/Order/Filter/AtTopBot/Floor.lean new file mode 100644 index 0000000000000..32e3e3aad7c86 --- /dev/null +++ b/Mathlib/Order/Filter/AtTopBot/Floor.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2022 Yuyang Zhao. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yuyang Zhao +-/ +import Mathlib.Algebra.Order.Floor +import Mathlib.Order.Filter.AtTopBot + +/-! +# `a * c ^ n < (n - d)!` holds true for sufficiently large `n`. +-/ + +open Filter +open scoped Nat + +variable {K : Type*} [LinearOrderedRing K] [FloorSemiring K] + +theorem FloorSemiring.eventually_mul_pow_lt_factorial_sub (a c : K) (d : ℕ) : + ∀ᶠ n in atTop, a * c ^ n < (n - d)! := by + filter_upwards [Nat.eventually_mul_pow_lt_factorial_sub ⌈|a|⌉₊ ⌈|c|⌉₊ d] with n h + calc a * c ^ n + _ ≤ |a * c ^ n| := le_abs_self _ + _ ≤ ⌈|a|⌉₊ * (⌈|c|⌉₊ : K) ^ n := ?_ + _ = ↑(⌈|a|⌉₊ * ⌈|c|⌉₊ ^ n) := ?_ + _ < (n - d)! := Nat.cast_lt.mpr h + · rw [abs_mul, abs_pow] + gcongr <;> try first | positivity | apply Nat.le_ceil + · simp_rw [Nat.cast_mul, Nat.cast_pow] diff --git a/Mathlib/Order/Filter/AtTopBot/ModEq.lean b/Mathlib/Order/Filter/AtTopBot/ModEq.lean index f7974d0c8d968..d45c17cc0d74b 100644 --- a/Mathlib/Order/Filter/AtTopBot/ModEq.lean +++ b/Mathlib/Order/Filter/AtTopBot/ModEq.lean @@ -3,7 +3,10 @@ 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.Algebra.Order.Ring.Abs +import Mathlib.Algebra.Order.Ring.Basic +import Mathlib.Algebra.Order.Ring.Nat +import Mathlib.Algebra.Ring.Divisibility.Basic +import Mathlib.Algebra.Ring.Int import Mathlib.Data.Nat.ModEq import Mathlib.Order.Filter.AtTopBot.Monoid diff --git a/Mathlib/Order/Filter/AtTopBot/Ring.lean b/Mathlib/Order/Filter/AtTopBot/Ring.lean index 874630711de2c..74207b0e55f14 100644 --- a/Mathlib/Order/Filter/AtTopBot/Ring.lean +++ b/Mathlib/Order/Filter/AtTopBot/Ring.lean @@ -3,8 +3,8 @@ 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.Algebra.Order.Ring.Defs import Mathlib.Order.Filter.AtTopBot.Group -import Mathlib.Algebra.Order.Ring.Basic /-! # Convergence to ±infinity in ordered rings @@ -30,7 +30,7 @@ theorem tendsto_mul_self_atTop : Tendsto (fun x : α => x * x) atTop atTop := /-- The monomial function `x^n` tends to `+∞` at `+∞` for any positive natural `n`. A version for positive real powers exists as `tendsto_rpow_atTop`. -/ theorem tendsto_pow_atTop {n : ℕ} (hn : n ≠ 0) : Tendsto (fun x : α => x ^ n) atTop atTop := - tendsto_atTop_mono' _ ((eventually_ge_atTop 1).mono fun _x hx => le_self_pow hx hn) tendsto_id + tendsto_atTop_mono' _ ((eventually_ge_atTop 1).mono fun _x hx => le_self_pow₀ hx hn) tendsto_id end OrderedSemiring diff --git a/Mathlib/Order/Filter/Bases.lean b/Mathlib/Order/Filter/Bases.lean index dfe2683487ad8..ffd5fe2a6c9e4 100644 --- a/Mathlib/Order/Filter/Bases.lean +++ b/Mathlib/Order/Filter/Bases.lean @@ -5,8 +5,7 @@ Authors: Yury Kudryashov, Johannes Hölzl, Mario Carneiro, Patrick Massot -/ import Mathlib.Data.Prod.PProd import Mathlib.Data.Set.Countable -import Mathlib.Order.Filter.Prod -import Mathlib.Order.Filter.Ker +import Mathlib.Order.Filter.Basic /-! # Filter bases @@ -117,7 +116,7 @@ def Filter.asBasis (f : Filter α) : FilterBasis α := ⟨f.sets, ⟨univ, univ_mem⟩, fun {x y} hx hy => ⟨x ∩ y, inter_mem hx hy, subset_rfl⟩⟩ -- Porting note: was `protected` in Lean 3 but `protected` didn't work; removed -/-- `is_basis p s` means the image of `s` bounded by `p` is a filter basis. -/ +/-- `IsBasis p s` means the image of `s` bounded by `p` is a filter basis. -/ structure Filter.IsBasis (p : ι → Prop) (s : ι → Set α) : Prop where /-- There exists at least one `i` that satisfies `p`. -/ nonempty : ∃ i, p i @@ -632,10 +631,6 @@ alias ⟨_, _root_.Disjoint.filter_principal⟩ := disjoint_principal_principal theorem disjoint_pure_pure {x y : α} : Disjoint (pure x : Filter α) (pure y) ↔ x ≠ y := by simp only [← principal_singleton, disjoint_principal_principal, disjoint_singleton] -@[simp] -theorem compl_diagonal_mem_prod {l₁ l₂ : Filter α} : (diagonal α)ᶜ ∈ l₁ ×ˢ l₂ ↔ Disjoint l₁ l₂ := by - simp only [mem_prod_iff, Filter.disjoint_iff, prod_subset_compl_diagonal_iff_disjoint] - -- Porting note: use `∃ i, p i ∧ _` instead of `∃ i (hi : p i), _`. theorem HasBasis.disjoint_iff_left (h : l.HasBasis p s) : Disjoint l l' ↔ ∃ i, p i ∧ (s i)ᶜ ∈ l' := by @@ -668,7 +663,7 @@ theorem HasBasis.eq_iInf (h : l.HasBasis (fun _ => True) s) : l = ⨅ i, 𝓟 (s theorem hasBasis_iInf_principal {s : ι → Set α} (h : Directed (· ≥ ·) s) [Nonempty ι] : (⨅ i, 𝓟 (s i)).HasBasis (fun _ => True) s := ⟨fun t => by - simpa only [true_and] using mem_iInf_of_directed (h.mono_comp monotone_principal.dual) t⟩ + simpa only [true_and] using mem_iInf_of_directed (h.mono_comp _ monotone_principal.dual) t⟩ /-- If `s : ι → Set α` is an indexed family of sets, then finite intersections of `s i` form a basis of `⨅ i, 𝓟 (s i)`. -/ @@ -683,7 +678,7 @@ theorem hasBasis_biInf_principal {s : β → Set α} {S : Set β} (h : DirectedO ⟨fun t => by refine mem_biInf_of_directed ?_ ne rw [directedOn_iff_directed, ← directed_comp] at h ⊢ - refine h.mono_comp ?_ + refine h.mono_comp _ ?_ exact fun _ _ => principal_mono.2⟩ theorem hasBasis_biInf_principal' {ι : Type*} {p : ι → Prop} {s : ι → Set α} @@ -722,7 +717,7 @@ protected theorem HasBasis.biInter_mem {f : Set α → Set β} (h : HasBasis l p h.biInf_mem hf 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 + sInter_eq_biInter.trans <| h.biInter_mem monotone_id variable {ι'' : Type*} [Preorder ι''] (l) (s'' : ι'' → Set α) diff --git a/Mathlib/Order/Filter/Basic.lean b/Mathlib/Order/Filter/Basic.lean index d73d46a740880..85fed348f7035 100644 --- a/Mathlib/Order/Filter/Basic.lean +++ b/Mathlib/Order/Filter/Basic.lean @@ -4,24 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jeremy Avigad -/ import Mathlib.Data.Set.Finite +import Mathlib.Order.Filter.Defs /-! # Theory of filters on sets -## Main definitions - -* `Filter` : filters on a set; -* `Filter.principal` : filter of all sets containing a given set; -* `Filter.map`, `Filter.comap` : operations on filters; -* `Filter.Tendsto` : limit with respect to filters; -* `Filter.Eventually` : `f.eventually p` means `{x | p x} ∈ f`; -* `Filter.Frequently` : `f.frequently p` means `{x | ¬p x} ∉ f`; -* `filter_upwards [h₁, ..., hₙ]` : - a tactic that takes a list of proofs `hᵢ : sᵢ ∈ f`, - and replaces a goal `s ∈ f` with `∀ x, x ∈ s₁ → ... → x ∈ sₙ → x ∈ s`; -* `Filter.NeBot f` : a utility class stating that `f` is a non-trivial filter. - -Filters on a type `X` are sets of sets of `X` satisfying three conditions. They are mostly used to +A *filter* on a type `α` is a collection of sets of `α` which contains the whole `α`, +is upwards-closed, and is stable under intersection. They are mostly used to abstract two related kinds of ideas: * *limits*, including finite or infinite limits of sequences, finite or infinite limits of functions at a point or at infinity, etc... @@ -30,8 +19,10 @@ abstract two related kinds of ideas: sense of measure theory. Dually, filters can also express the idea of *things happening often*: for arbitrarily large `n`, or at a point in any neighborhood of given a point etc... -In this file, we define the type `Filter X` of filters on `X`, and endow it with a complete lattice -structure. This structure is lifted from the lattice structure on `Set (Set X)` using the Galois +## Main definitions + +In this file, we endow `Filter α` it with a complete lattice structure. +This structure is lifted from the lattice structure on `Set (Set X)` using the Galois insertion which maps a filter to its elements in one direction, and an arbitrary set of sets to the smallest filter containing it in the other direction. We also prove `Filter` is a monadic functor, with a push-forward operation @@ -82,69 +73,27 @@ open scoped symmDiff universe u v w x y -/-- A filter `F` on a type `α` is a collection of sets of `α` which contains the whole `α`, -is upwards-closed, and is stable under intersection. We do not forbid this collection to be -all sets of `α`. -/ -structure Filter (α : Type*) where - /-- The set of sets that belong to the filter. -/ - sets : Set (Set α) - /-- The set `Set.univ` belongs to any filter. -/ - univ_sets : Set.univ ∈ sets - /-- If a set belongs to a filter, then its superset belongs to the filter as well. -/ - sets_of_superset {x y} : x ∈ sets → x ⊆ y → y ∈ sets - /-- If two sets belong to a filter, then their intersection belongs to the filter as well. -/ - inter_sets {x y} : x ∈ sets → y ∈ sets → x ∩ y ∈ sets - -/-- If `F` is a filter on `α`, and `U` a subset of `α` then we can write `U ∈ F` as on paper. -/ -instance {α : Type*} : Membership (Set α) (Filter α) := - ⟨fun F U => U ∈ F.sets⟩ - namespace Filter variable {α : Type u} {f g : Filter α} {s t : Set α} -@[simp] -protected theorem mem_mk {t : Set (Set α)} {h₁ h₂ h₃} : s ∈ mk t h₁ h₂ h₃ ↔ s ∈ t := - Iff.rfl - -@[simp] -protected theorem mem_sets : s ∈ f.sets ↔ s ∈ f := - Iff.rfl - instance inhabitedMem : Inhabited { s : Set α // s ∈ f } := ⟨⟨univ, f.univ_sets⟩⟩ -theorem filter_eq : ∀ {f g : Filter α}, f.sets = g.sets → f = g - | ⟨_, _, _, _⟩, ⟨_, _, _, _⟩, rfl => rfl - theorem filter_eq_iff : f = g ↔ f.sets = g.sets := ⟨congr_arg _, filter_eq⟩ -@[ext] -protected theorem ext (h : ∀ s, s ∈ f ↔ s ∈ g) : f = g := by - simpa [filter_eq_iff, Set.ext_iff, Filter.mem_sets] - /-- An extensionality lemma that is useful for filters with good lemmas about `sᶜ ∈ f` (e.g., `Filter.comap`, `Filter.coprod`, `Filter.Coprod`, `Filter.cofinite`). -/ protected theorem coext (h : ∀ s, sᶜ ∈ f ↔ sᶜ ∈ g) : f = g := Filter.ext <| compl_surjective.forall.2 h -@[simp] -theorem univ_mem : univ ∈ f := - f.univ_sets - -theorem mem_of_superset {x y : Set α} (hx : x ∈ f) (hxy : x ⊆ y) : y ∈ f := - f.sets_of_superset hx hxy - instance : Trans (· ⊇ ·) ((· ∈ ·) : Set α → Filter α → Prop) (· ∈ ·) where trans h₁ h₂ := mem_of_superset h₂ h₁ instance : Trans Membership.mem (· ⊆ ·) (Membership.mem : Filter α → Set α → Prop) where trans h₁ h₂ := mem_of_superset h₁ h₂ -theorem inter_mem {s t : Set α} (hs : s ∈ f) (ht : t ∈ f) : s ∩ t ∈ f := - f.inter_sets hs ht - @[simp] theorem inter_mem_iff {s t : Set α} : s ∩ t ∈ f ↔ s ∈ f ∧ t ∈ f := ⟨fun h => ⟨mem_of_superset h inter_subset_left, mem_of_superset h inter_subset_right⟩, @@ -153,27 +102,12 @@ theorem inter_mem_iff {s t : Set α} : s ∩ t ∈ f ↔ s ∈ f ∧ t ∈ f := theorem diff_mem {s t : Set α} (hs : s ∈ f) (ht : tᶜ ∈ f) : s \ t ∈ f := inter_mem hs ht -theorem univ_mem' (h : ∀ a, a ∈ s) : s ∈ f := - mem_of_superset univ_mem fun x _ => h x - -theorem mp_mem (hs : s ∈ f) (h : { x | x ∈ s → x ∈ t } ∈ f) : t ∈ f := - mem_of_superset (inter_mem hs h) fun _ ⟨h₁, h₂⟩ => h₂ h₁ - theorem congr_sets (h : { x | x ∈ s ↔ x ∈ t } ∈ f) : s ∈ f ↔ t ∈ f := ⟨fun hs => mp_mem hs (mem_of_superset h fun _ => Iff.mp), fun hs => mp_mem hs (mem_of_superset h fun _ => Iff.mpr)⟩ -/-- Override `sets` field of a filter to provide better definitional equality. -/ -protected def copy (f : Filter α) (S : Set (Set α)) (hmem : ∀ s, s ∈ S ↔ s ∈ f) : Filter α where - sets := S - univ_sets := (hmem _).2 univ_mem - sets_of_superset h hsub := (hmem _).2 <| mem_of_superset ((hmem _).1 h) hsub - inter_sets h₁ h₂ := (hmem _).2 <| inter_mem ((hmem _).1 h₁) ((hmem _).1 h₂) - lemma copy_eq {S} (hmem : ∀ s, s ∈ S ↔ s ∈ f) : f.copy S hmem = f := Filter.ext hmem -@[simp] lemma mem_copy {S hmem} : s ∈ f.copy S hmem ↔ s ∈ S := Iff.rfl - @[simp] theorem biInter_mem {β : Type v} {s : β → Set α} {is : Set β} (hf : is.Finite) : (⋂ i ∈ is, s i) ∈ f ↔ ∀ i ∈ is, s i ∈ f := @@ -217,100 +151,17 @@ theorem forall_in_swap {β : Type*} {p : Set α → β → Prop} : end Filter -namespace Mathlib.Tactic - -open Lean Meta Elab Tactic - -/-- -`filter_upwards [h₁, ⋯, hₙ]` replaces a goal of the form `s ∈ f` and terms -`h₁ : t₁ ∈ f, ⋯, hₙ : tₙ ∈ f` with `∀ x, x ∈ t₁ → ⋯ → x ∈ tₙ → x ∈ s`. -The list is an optional parameter, `[]` being its default value. - -`filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ` is a short form for -`{ filter_upwards [h₁, ⋯, hₙ], intros a₁ a₂ ⋯ aₖ }`. - -`filter_upwards [h₁, ⋯, hₙ] using e` is a short form for -`{ filter_upwards [h1, ⋯, hn], exact e }`. - -Combining both shortcuts is done by writing `filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ using e`. -Note that in this case, the `aᵢ` terms can be used in `e`. --/ -syntax (name := filterUpwards) "filter_upwards" (" [" term,* "]")? - (" with" (ppSpace colGt term:max)*)? (" using " term)? : tactic - -elab_rules : tactic -| `(tactic| filter_upwards $[[$[$args],*]]? $[with $wth*]? $[using $usingArg]?) => do - let config : ApplyConfig := {newGoals := ApplyNewGoals.nonDependentOnly} - for e in args.getD #[] |>.reverse do - let goal ← getMainGoal - replaceMainGoal <| ← goal.withContext <| runTermElab do - let m ← mkFreshExprMVar none - let lem ← Term.elabTermEnsuringType - (← ``(Filter.mp_mem $e $(← Term.exprToSyntax m))) (← goal.getType) - goal.assign lem - return [m.mvarId!] - liftMetaTactic fun goal => do - goal.apply (← mkConstWithFreshMVarLevels ``Filter.univ_mem') config - evalTactic <|← `(tactic| dsimp (config := {zeta := false}) only [Set.mem_setOf_eq]) - if let some l := wth then - evalTactic <|← `(tactic| intro $[$l]*) - if let some e := usingArg then - evalTactic <|← `(tactic| exact $e) - -end Mathlib.Tactic namespace Filter variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type*} {ι : Sort x} -section Principal - -/-- The principal filter of `s` is the collection of all supersets of `s`. -/ -def principal (s : Set α) : Filter α where - sets := { t | s ⊆ t } - univ_sets := subset_univ s - sets_of_superset hx := Subset.trans hx - inter_sets := subset_inter - -@[inherit_doc] -scoped notation "𝓟" => Filter.principal - -@[simp] theorem mem_principal {s t : Set α} : s ∈ 𝓟 t ↔ t ⊆ s := Iff.rfl - theorem mem_principal_self (s : Set α) : s ∈ 𝓟 s := Subset.rfl -end Principal - -open Filter - -section Join - -/-- The join of a filter of filters is defined by the relation `s ∈ join f ↔ {t | s ∈ t} ∈ f`. -/ -def join (f : Filter (Filter α)) : Filter α where - sets := { s | { t : Filter α | s ∈ t } ∈ f } - univ_sets := by simp only [mem_setOf_eq, univ_sets, ← Filter.mem_sets, setOf_true] - sets_of_superset hx xy := mem_of_superset hx fun f h => mem_of_superset h xy - inter_sets hx hy := mem_of_superset (inter_mem hx hy) fun f ⟨h₁, h₂⟩ => inter_mem h₁ h₂ - -@[simp] -theorem mem_join {s : Set α} {f : Filter (Filter α)} : s ∈ join f ↔ { t | s ∈ t } ∈ f := - Iff.rfl - -end Join - section Lattice variable {f g : Filter α} {s t : Set α} -instance : PartialOrder (Filter α) where - le f g := ∀ ⦃U : Set α⦄, U ∈ g → U ∈ f - le_antisymm a b h₁ h₂ := filter_eq <| Subset.antisymm h₂ h₁ - le_refl a := Subset.rfl - le_trans a b c h₁ h₂ := Subset.trans h₂ h₁ - -theorem le_def : f ≤ g ↔ ∀ x ∈ g, x ∈ f := - Iff.rfl - protected theorem not_le : ¬f ≤ g ↔ ∃ s ∈ g, s ∉ f := by simp_rw [le_def, not_forall, exists_prop] /-- `GenerateSets g s`: `s` is in the filter closure of `g`. -/ @@ -378,23 +229,6 @@ def giGenerate (α : Type*) : choice s hs := Filter.mkOfClosure s (le_antisymm hs <| le_generate_iff.1 <| le_rfl) choice_eq _ _ := mkOfClosure_sets -/-- The infimum of filters is the filter generated by intersections - of elements of the two filters. -/ -instance : Inf (Filter α) := - ⟨fun f g : Filter α => - { sets := { s | ∃ a ∈ f, ∃ b ∈ g, s = a ∩ b } - univ_sets := ⟨_, univ_mem, _, univ_mem, by simp⟩ - sets_of_superset := by - rintro x y ⟨a, ha, b, hb, rfl⟩ xy - refine - ⟨a ∪ y, mem_of_superset ha subset_union_left, b ∪ y, - mem_of_superset hb subset_union_left, ?_⟩ - rw [← inter_union_distrib_right, union_eq_self_of_subset_left xy] - inter_sets := by - rintro x y ⟨a, ha, b, hb, rfl⟩ ⟨c, hc, d, hd, rfl⟩ - refine ⟨a ∩ c, inter_mem ha hc, b ∩ d, inter_mem hb hd, ?_⟩ - ac_rfl }⟩ - theorem mem_inf_iff {f g : Filter α} {s : Set α} : s ∈ f ⊓ g ↔ ∃ t₁ ∈ f, ∃ t₂ ∈ g, s = t₁ ∩ t₂ := Iff.rfl @@ -417,19 +251,6 @@ theorem mem_inf_iff_superset {f g : Filter α} {s : Set α} : ⟨fun ⟨t₁, h₁, t₂, h₂, Eq⟩ => ⟨t₁, h₁, t₂, h₂, Eq ▸ Subset.rfl⟩, fun ⟨_, h₁, _, h₂, sub⟩ => mem_inf_of_inter h₁ h₂ sub⟩ -instance : Top (Filter α) := - ⟨{ sets := { s | ∀ x, x ∈ s } - univ_sets := fun x => mem_univ x - sets_of_superset := fun hx hxy a => hxy (hx a) - inter_sets := fun hx hy _ => mem_inter (hx _) (hy _) }⟩ - -theorem mem_top_iff_forall {s : Set α} : s ∈ (⊤ : Filter α) ↔ ∀ x, x ∈ s := - Iff.rfl - -@[simp] -theorem mem_top {s : Set α} : s ∈ (⊤ : Filter α) ↔ s = univ := by - rw [mem_top_iff_forall, eq_univ_iff_forall] - section CompleteLattice /- We lift the complete lattice along the Galois connection `generate` / `sets`. Unfortunately, @@ -452,16 +273,6 @@ instance : Inhabited (Filter α) := ⟨⊥⟩ end CompleteLattice -/-- A filter is `NeBot` if it is not equal to `⊥`, or equivalently the empty set does not belong to -the filter. Bourbaki include this assumption in the definition of a filter but we prefer to have a -`CompleteLattice` structure on `Filter _`, so we use a typeclass argument in lemmas instead. -/ -class NeBot (f : Filter α) : Prop where - /-- The filter is nontrivial: `f ≠ ⊥` or equivalently, `∅ ∉ f`. -/ - ne' : f ≠ ⊥ - -theorem neBot_iff {f : Filter α} : NeBot f ↔ f ≠ ⊥ := - ⟨fun h => h.1, fun h => ⟨h⟩⟩ - theorem NeBot.ne {f : Filter α} (hf : NeBot f) : f ≠ ⊥ := hf.ne' @[simp] theorem not_neBot {f : Filter α} : ¬f.NeBot ↔ f = ⊥ := neBot_iff.not_left @@ -506,10 +317,6 @@ theorem generate_iUnion {s : ι → Set (Set α)} : Filter.generate (⋃ i, s i) = ⨅ i, Filter.generate (s i) := (giGenerate α).gc.l_iSup -@[simp] -theorem mem_bot {s : Set α} : s ∈ (⊥ : Filter α) := - trivial - @[simp] theorem mem_sup {f g : Filter α} {s : Set α} : s ∈ f ⊔ g ↔ s ∈ f ∧ s ∈ g := Iff.rfl @@ -950,14 +757,6 @@ theorem join_mono {f₁ f₂ : Filter (Filter α)} (h : f₁ ≤ f₂) : join f /-! ### Eventually -/ -/-- `f.Eventually p` or `∀ᶠ x in f, p x` mean that `{x | p x} ∈ f`. E.g., `∀ᶠ x in atTop, p x` -means that `p` holds true for sufficiently large `x`. -/ -protected def Eventually (p : α → Prop) (f : Filter α) : Prop := - { x | p x } ∈ f - -@[inherit_doc Filter.Eventually] -notation3 "∀ᶠ "(...)" in "f", "r:(scoped p => Filter.Eventually p f) => r - theorem eventually_iff {f : Filter α} {P : α → Prop} : (∀ᶠ x in f, P x) ↔ { x | P x } ∈ f := Iff.rfl @@ -1106,14 +905,6 @@ theorem eventually_inf_principal {f : Filter α} {p : α → Prop} {s : Set α} /-! ### Frequently -/ -/-- `f.Frequently p` or `∃ᶠ x in f, p x` mean that `{x | ¬p x} ∉ f`. E.g., `∃ᶠ x in atTop, p x` -means that there exist arbitrarily large `x` for which `p` holds true. -/ -protected def Frequently (p : α → Prop) (f : Filter α) : Prop := - ¬∀ᶠ x in f, ¬p x - -@[inherit_doc Filter.Frequently] -notation3 "∃ᶠ "(...)" in "f", "r:(scoped p => Filter.Frequently p f) => r - theorem Eventually.frequently {f : Filter α} [NeBot f] {p : α → Prop} (h : ∀ᶠ x in f, p x) : ∃ᶠ x in f, p x := compl_not_mem h @@ -1266,17 +1057,9 @@ theorem Eventually.choice {r : α → β → Prop} {l : Filter α} [l.NeBot] (h ### Relation “eventually equal” -/ -/-- Two functions `f` and `g` are *eventually equal* along a filter `l` if the set of `x` such that -`f x = g x` belongs to `l`. -/ -def EventuallyEq (l : Filter α) (f g : α → β) : Prop := - ∀ᶠ x in l, f x = g x - section EventuallyEq variable {l : Filter α} {f g : α → β} -@[inherit_doc] -notation:50 f " =ᶠ[" l:50 "] " g:50 => EventuallyEq l f g - theorem EventuallyEq.eventually (h : f =ᶠ[l] g) : ∀ᶠ x in l, f x = g x := h @[simp] lemma eventuallyEq_top : f =ᶠ[⊤] g ↔ f = g := by simp [EventuallyEq, funext_iff] @@ -1449,13 +1232,6 @@ section LE variable [LE β] {l : Filter α} -/-- A function `f` is eventually less than or equal to a function `g` at a filter `l`. -/ -def EventuallyLE (l : Filter α) (f g : α → β) : Prop := - ∀ᶠ x in l, f x ≤ g x - -@[inherit_doc] -notation:50 f " ≤ᶠ[" l:50 "] " g:50 => EventuallyLE l f g - theorem EventuallyLE.congr {f f' g g' : α → β} (H : f ≤ᶠ[l] g) (hf : f =ᶠ[l] f') (hg : g =ᶠ[l] g') : f' ≤ᶠ[l] g' := H.mp <| hg.mp <| hf.mono fun x hf hg H => by rwa [hf, hg] at H @@ -1654,13 +1430,6 @@ end EventuallyEq section Map -/-- The forward map of a filter -/ -def map (m : α → β) (f : Filter α) : Filter β where - sets := preimage m ⁻¹' f.sets - univ_sets := univ_mem - sets_of_superset hs st := mem_of_superset hs <| preimage_mono st - inter_sets hs ht := inter_mem hs ht - @[simp] theorem map_principal {s : Set α} {f : α → β} : map f (𝓟 s) = 𝓟 (Set.image f s) := Filter.ext fun _ => image_subset_iff.symm @@ -1725,20 +1494,6 @@ end Map section Comap -/-- The inverse map of a filter. A set `s` belongs to `Filter.comap m f` if either of the following -equivalent conditions hold. - -1. There exists a set `t ∈ f` such that `m ⁻¹' t ⊆ s`. This is used as a definition. -2. The set `kernImage m s = {y | ∀ x, m x = y → x ∈ s}` belongs to `f`, see `Filter.mem_comap'`. -3. The set `(m '' sᶜ)ᶜ` belongs to `f`, see `Filter.mem_comap_iff_compl` and -`Filter.compl_mem_comap`. -/ -def comap (m : α → β) (f : Filter β) : Filter α where - sets := { s | ∃ t ∈ f, m ⁻¹' t ⊆ s } - univ_sets := ⟨univ, univ_mem, by simp only [subset_univ, preimage_univ]⟩ - sets_of_superset := fun ⟨a', ha', ma'a⟩ ab => ⟨a', ha', ma'a.trans ab⟩ - inter_sets := fun ⟨a', ha₁, ha₂⟩ ⟨b', hb₁, hb₂⟩ => - ⟨a' ∩ b', inter_mem ha₁ hb₁, inter_subset_inter ha₂ hb₂⟩ - variable {f : α → β} {l : Filter β} {p : α → Prop} {s : Set α} theorem mem_comap' : s ∈ comap f l ↔ { y | ∀ ⦃x⦄, f x = y → x ∈ s } ∈ l := @@ -1809,37 +1564,6 @@ theorem compl_mem_kernMap {s : Set β} : sᶜ ∈ kernMap m f ↔ ∃ t, tᶜ end KernMap -/-- The monadic bind operation on filter is defined the usual way in terms of `map` and `join`. - -Unfortunately, this `bind` does not result in the expected applicative. See `Filter.seq` for the -applicative instance. -/ -def bind (f : Filter α) (m : α → Filter β) : Filter β := - join (map m f) - -/-- The applicative sequentiation operation. This is not induced by the bind operation. -/ -def seq (f : Filter (α → β)) (g : Filter α) : Filter β where - sets := { s | ∃ u ∈ f, ∃ t ∈ g, ∀ m ∈ u, ∀ x ∈ t, (m : α → β) x ∈ s } - univ_sets := ⟨univ, univ_mem, univ, univ_mem, fun _ _ _ _ => trivial⟩ - sets_of_superset := fun ⟨t₀, t₁, h₀, h₁, h⟩ hst => - ⟨t₀, t₁, h₀, h₁, fun _ hx _ hy => hst <| h _ hx _ hy⟩ - inter_sets := fun ⟨t₀, ht₀, t₁, ht₁, ht⟩ ⟨u₀, hu₀, u₁, hu₁, hu⟩ => - ⟨t₀ ∩ u₀, inter_mem ht₀ hu₀, t₁ ∩ u₁, inter_mem ht₁ hu₁, fun _ ⟨hx₀, hx₁⟩ _ ⟨hy₀, hy₁⟩ => - ⟨ht _ hx₀ _ hy₀, hu _ hx₁ _ hy₁⟩⟩ - -/-- `pure x` is the set of sets that contain `x`. It is equal to `𝓟 {x}` but -with this definition we have `s ∈ pure a` defeq `a ∈ s`. -/ -instance : Pure Filter := - ⟨fun x => - { sets := { s | x ∈ s } - inter_sets := And.intro - sets_of_superset := fun hs hst => hst hs - univ_sets := trivial }⟩ - -instance : Bind Filter := - ⟨@Filter.bind⟩ - -instance : Functor Filter where map := @Filter.map - instance : LawfulFunctor (Filter : Type u → Type u) where id_map _ := map_id comp_map _ _ _ := map_map.symm @@ -2596,12 +2320,6 @@ end Bind /-! ### Limits -/ -/-- `Filter.Tendsto` is the generic "limit of a function" predicate. - `Tendsto f l₁ l₂` asserts that for every `l₂` neighborhood `a`, - the `f`-preimage of `a` is an `l₁` neighborhood. -/ -def Tendsto (f : α → β) (l₁ : Filter α) (l₂ : Filter β) := - l₁.map f ≤ l₂ - theorem tendsto_def {f : α → β} {l₁ : Filter α} {l₂ : Filter β} : Tendsto f l₁ l₂ ↔ ∀ s ∈ l₂, f ⁻¹' s ∈ l₁ := Iff.rfl @@ -2638,6 +2356,12 @@ theorem Tendsto.frequently_map {l₁ : Filter α} {l₂ : Filter β} {p : α → @[simp] theorem tendsto_bot {f : α → β} {l : Filter β} : Tendsto f ⊥ l := by simp [Tendsto] +theorem Tendsto.of_neBot_imp {f : α → β} {la : Filter α} {lb : Filter β} + (h : NeBot la → Tendsto f la lb) : Tendsto f la lb := by + rcases eq_or_neBot la with rfl | hla + · exact tendsto_bot + · exact h hla + @[simp] theorem tendsto_top {f : α → β} {l : Filter α} : Tendsto f l ⊤ := le_top theorem le_map_of_right_inverse {mab : α → β} {mba : β → α} {f : Filter α} {g : Filter β} @@ -2915,21 +2639,6 @@ alias ⟨_, Set.InjOn.filter_map_Iic⟩ := Filter.filter_injOn_Iic_iff_injOn namespace Filter -/-- Construct a filter from a property that is stable under finite unions. -A set `s` belongs to `Filter.comk p _ _ _` iff its complement satisfies the predicate `p`. -This constructor is useful to define filters like `Filter.cofinite`. -/ -def comk (p : Set α → Prop) (he : p ∅) (hmono : ∀ t, p t → ∀ s ⊆ t, p s) - (hunion : ∀ s, p s → ∀ t, p t → p (s ∪ t)) : Filter α where - sets := {t | p tᶜ} - univ_sets := by simpa - sets_of_superset := fun ht₁ ht => hmono _ ht₁ _ (compl_subset_compl.2 ht) - inter_sets := fun ht₁ ht₂ => by simp [compl_inter, hunion _ ht₁ _ ht₂] - -@[simp] -lemma mem_comk {p : Set α → Prop} {he hmono hunion s} : - s ∈ comk p he hmono hunion ↔ p sᶜ := - .rfl - lemma compl_mem_comk {p : Set α → Prop} {he hmono hunion s} : sᶜ ∈ comk p he hmono hunion ↔ p s := by simp diff --git a/Mathlib/Order/Filter/CardinalInter.lean b/Mathlib/Order/Filter/CardinalInter.lean index df6c37ffccbb7..def8ba80b0a80 100644 --- a/Mathlib/Order/Filter/CardinalInter.lean +++ b/Mathlib/Order/Filter/CardinalInter.lean @@ -5,7 +5,7 @@ Authors: Josha Dekker -/ import Mathlib.Order.Filter.Basic import Mathlib.Order.Filter.CountableInter -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Cofinality /-! diff --git a/Mathlib/Order/Filter/Cocardinal.lean b/Mathlib/Order/Filter/Cocardinal.lean index ede785eb18061..b0fed85fce86e 100644 --- a/Mathlib/Order/Filter/Cocardinal.lean +++ b/Mathlib/Order/Filter/Cocardinal.lean @@ -6,7 +6,7 @@ Authors: Josha Dekker import Mathlib.Order.Filter.Cofinite import Mathlib.Order.Filter.CountableInter import Mathlib.Order.Filter.CardinalInter -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Cardinal.Cofinality import Mathlib.Order.Filter.Bases diff --git a/Mathlib/Order/Filter/Cofinite.lean b/Mathlib/Order/Filter/Cofinite.lean index 03cc4bdf98814..94c269c447ffa 100644 --- a/Mathlib/Order/Filter/Cofinite.lean +++ b/Mathlib/Order/Filter/Cofinite.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Jeremy Avigad, Yury Kudryashov -/ import Mathlib.Order.Filter.AtTopBot +import Mathlib.Order.Filter.Ker import Mathlib.Order.Filter.Pi /-! diff --git a/Mathlib/Order/Filter/Curry.lean b/Mathlib/Order/Filter/Curry.lean index 561f48bd033b3..7f91d3cc76ef9 100644 --- a/Mathlib/Order/Filter/Curry.lean +++ b/Mathlib/Order/Filter/Curry.lean @@ -49,13 +49,6 @@ namespace Filter variable {α β γ : Type*} -/-- This filter is characterized by `Filter.eventually_curry_iff`: -`(∀ᶠ (x : α × β) in f.curry g, p x) ↔ ∀ᶠ (x : α) in f, ∀ᶠ (y : β) in g, p (x, y)`. Useful -in adding quantifiers to the middle of `Tendsto`s. See -`hasFDerivAt_of_tendstoUniformlyOnFilter`. -/ -def curry (f : Filter α) (g : Filter β) : Filter (α × β) := - bind f fun a ↦ map (a, ·) g - theorem eventually_curry_iff {f : Filter α} {g : Filter β} {p : α × β → Prop} : (∀ᶠ x : α × β in f.curry g, p x) ↔ ∀ᶠ x : α in f, ∀ᶠ y : β in g, p (x, y) := Iff.rfl diff --git a/Mathlib/Order/Filter/Defs.lean b/Mathlib/Order/Filter/Defs.lean new file mode 100644 index 0000000000000..cd23371bb3f2f --- /dev/null +++ b/Mathlib/Order/Filter/Defs.lean @@ -0,0 +1,378 @@ +/- +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, Jeremy Avigad +-/ +import Mathlib.Data.Set.Basic +import Mathlib.Order.SetNotation + +/-! +# Definitions about filters + +A *filter* on a type `α` is a collection of sets of `α` which contains the whole `α`, +is upwards-closed, and is stable under intersection. Filters are mostly used to +abstract two related kinds of ideas: +* *limits*, including finite or infinite limits of sequences, finite or infinite limits of functions + at a point or at infinity, etc... +* *things happening eventually*, including things happening for large enough `n : ℕ`, or near enough + a point `x`, or for close enough pairs of points, or things happening almost everywhere in the + sense of measure theory. Dually, filters can also express the idea of *things happening often*: + for arbitrarily large `n`, or at a point in any neighborhood of given a point etc... + +## Main definitions + +* `Filter` : filters on a set; +* `Filter.principal`, `𝓟 s` : filter of all sets containing a given set; +* `Filter.map`, `Filter.comap` : operations on filters; +* `Filter.Tendsto` : limit with respect to filters; +* `Filter.Eventually` : `f.Eventually p` means `{x | p x} ∈ f`; +* `Filter.Frequently` : `f.Frequently p` means `{x | ¬p x} ∉ f`; +* `filter_upwards [h₁, ..., hₙ]` : + a tactic that takes a list of proofs `hᵢ : sᵢ ∈ f`, + and replaces a goal `s ∈ f` with `∀ x, x ∈ s₁ → ... → x ∈ sₙ → x ∈ s`; +* `Filter.NeBot f` : a utility class stating that `f` is a non-trivial filter. + +## Notations + +* `∀ᶠ x in f, p x` : `f.Eventually p`; +* `∃ᶠ x in f, p x` : `f.Frequently p`; +* `f =ᶠ[l] g` : `∀ᶠ x in l, f x = g x`; +* `f ≤ᶠ[l] g` : `∀ᶠ x in l, f x ≤ g x`; +* `𝓟 s` : `Filter.Principal s`, localized in `Filter`. + +## Implementation Notes + +Important note: Bourbaki requires that a filter on `X` cannot contain all sets of `X`, +which we do *not* require. +This gives `Filter X` better formal properties, +in particular a bottom element `⊥` for its lattice structure, +at the cost of including the assumption `[NeBot f]` in a number of lemmas and definitions. + +## References + +* [N. Bourbaki, *General Topology*][bourbaki1966] +-/ + +open Set + +/-- A filter `F` on a type `α` is a collection of sets of `α` which contains the whole `α`, +is upwards-closed, and is stable under intersection. We do not forbid this collection to be +all sets of `α`. -/ +structure Filter (α : Type*) where + /-- The set of sets that belong to the filter. -/ + sets : Set (Set α) + /-- The set `Set.univ` belongs to any filter. -/ + univ_sets : Set.univ ∈ sets + /-- If a set belongs to a filter, then its superset belongs to the filter as well. -/ + sets_of_superset {x y} : x ∈ sets → x ⊆ y → y ∈ sets + /-- If two sets belong to a filter, then their intersection belongs to the filter as well. -/ + inter_sets {x y} : x ∈ sets → y ∈ sets → x ∩ y ∈ sets + +namespace Filter + +variable {α β : Type*} {f g : Filter α} {s t : Set α} + +theorem filter_eq : ∀ {f g : Filter α}, f.sets = g.sets → f = g + | ⟨_, _, _, _⟩, ⟨_, _, _, _⟩, rfl => rfl + +/-- If `F` is a filter on `α`, and `U` a subset of `α` then we can write `U ∈ F` as on paper. -/ +instance instMembership : Membership (Set α) (Filter α) := ⟨fun F U => U ∈ F.sets⟩ + +@[ext] +protected theorem ext (h : ∀ s, s ∈ f ↔ s ∈ g) : f = g := filter_eq <| Set.ext h + +@[simp] +protected theorem mem_mk {t : Set (Set α)} {h₁ h₂ h₃} : s ∈ mk t h₁ h₂ h₃ ↔ s ∈ t := + Iff.rfl + +@[simp] +protected theorem mem_sets : s ∈ f.sets ↔ s ∈ f := + Iff.rfl + +@[simp] +theorem univ_mem : univ ∈ f := + f.univ_sets + +theorem mem_of_superset {x y : Set α} (hx : x ∈ f) (hxy : x ⊆ y) : y ∈ f := + f.sets_of_superset hx hxy + +theorem univ_mem' (h : ∀ a, a ∈ s) : s ∈ f := + mem_of_superset univ_mem fun x _ => h x + +theorem inter_mem (hs : s ∈ f) (ht : t ∈ f) : s ∩ t ∈ f := + f.inter_sets hs ht + +theorem mp_mem (hs : s ∈ f) (h : { x | x ∈ s → x ∈ t } ∈ f) : t ∈ f := + mem_of_superset (inter_mem hs h) fun _ ⟨h₁, h₂⟩ => h₂ h₁ + +/-- Override `sets` field of a filter to provide better definitional equality. -/ +protected def copy (f : Filter α) (S : Set (Set α)) (hmem : ∀ s, s ∈ S ↔ s ∈ f) : Filter α where + sets := S + univ_sets := (hmem _).2 univ_mem + sets_of_superset h hsub := (hmem _).2 <| mem_of_superset ((hmem _).1 h) hsub + inter_sets h₁ h₂ := (hmem _).2 <| inter_mem ((hmem _).1 h₁) ((hmem _).1 h₂) + +@[simp] theorem mem_copy {S hmem} : s ∈ f.copy S hmem ↔ s ∈ S := Iff.rfl + +/-- Construct a filter from a property that is stable under finite unions. +A set `s` belongs to `Filter.comk p _ _ _` iff its complement satisfies the predicate `p`. +This constructor is useful to define filters like `Filter.cofinite`. -/ +def comk (p : Set α → Prop) (he : p ∅) (hmono : ∀ t, p t → ∀ s ⊆ t, p s) + (hunion : ∀ s, p s → ∀ t, p t → p (s ∪ t)) : Filter α where + sets := {t | p tᶜ} + univ_sets := by simpa + sets_of_superset := fun ht₁ ht => hmono _ ht₁ _ (compl_subset_compl.2 ht) + inter_sets := fun ht₁ ht₂ => by simp [compl_inter, hunion _ ht₁ _ ht₂] + +@[simp] +lemma mem_comk {p : Set α → Prop} {he hmono hunion s} : + s ∈ comk p he hmono hunion ↔ p sᶜ := + .rfl + +/-- The principal filter of `s` is the collection of all supersets of `s`. -/ +def principal (s : Set α) : Filter α where + sets := { t | s ⊆ t } + univ_sets := subset_univ s + sets_of_superset hx := Subset.trans hx + inter_sets := subset_inter + +@[inherit_doc] +scoped notation "𝓟" => Filter.principal + +@[simp] theorem mem_principal : s ∈ 𝓟 t ↔ t ⊆ s := Iff.rfl + +/-- The *kernel* of a filter is the intersection of all its sets. -/ +def ker (f : Filter α) : Set α := ⋂₀ f.sets + +/-- The join of a filter of filters is defined by the relation `s ∈ join f ↔ {t | s ∈ t} ∈ f`. -/ +def join (f : Filter (Filter α)) : Filter α where + sets := { s | { t : Filter α | s ∈ t } ∈ f } + univ_sets := by simp only [mem_setOf_eq, univ_mem, setOf_true] + sets_of_superset hx xy := mem_of_superset hx fun f h => mem_of_superset h xy + inter_sets hx hy := mem_of_superset (inter_mem hx hy) fun f ⟨h₁, h₂⟩ => inter_mem h₁ h₂ + +@[simp] +theorem mem_join {s : Set α} {f : Filter (Filter α)} : s ∈ join f ↔ { t | s ∈ t } ∈ f := + Iff.rfl + +instance : PartialOrder (Filter α) where + le f g := ∀ ⦃U : Set α⦄, U ∈ g → U ∈ f + le_antisymm a b h₁ h₂ := filter_eq <| Subset.antisymm h₂ h₁ + le_refl a := Subset.rfl + le_trans a b c h₁ h₂ := Subset.trans h₂ h₁ + +theorem le_def : f ≤ g ↔ ∀ x ∈ g, x ∈ f := + Iff.rfl + +instance : Top (Filter α) := + ⟨{ sets := { s | ∀ x, x ∈ s } + univ_sets := fun x => mem_univ x + sets_of_superset := fun hx hxy a => hxy (hx a) + inter_sets := fun hx hy _ => mem_inter (hx _) (hy _) }⟩ + +theorem mem_top_iff_forall {s : Set α} : s ∈ (⊤ : Filter α) ↔ ∀ x, x ∈ s := + Iff.rfl + +@[simp] +theorem mem_top {s : Set α} : s ∈ (⊤ : Filter α) ↔ s = univ := by + rw [mem_top_iff_forall, eq_univ_iff_forall] + +instance : Bot (Filter α) where + bot := + { sets := univ + univ_sets := trivial + sets_of_superset := fun _ _ ↦ trivial + inter_sets := fun _ _ ↦ trivial } + +@[simp] +theorem mem_bot {s : Set α} : s ∈ (⊥ : Filter α) := + trivial + +/-- The infimum of filters is the filter generated by intersections + of elements of the two filters. -/ +instance : Inf (Filter α) := + ⟨fun f g : Filter α => + { sets := { s | ∃ a ∈ f, ∃ b ∈ g, s = a ∩ b } + univ_sets := ⟨_, univ_mem, _, univ_mem, by simp⟩ + sets_of_superset := by + rintro x y ⟨a, ha, b, hb, rfl⟩ xy + refine ⟨a ∪ y, mem_of_superset ha subset_union_left, b ∪ y, + mem_of_superset hb subset_union_left, ?_⟩ + rw [← inter_union_distrib_right, union_eq_self_of_subset_left xy] + inter_sets := by + rintro x y ⟨a, ha, b, hb, rfl⟩ ⟨c, hc, d, hd, rfl⟩ + refine ⟨a ∩ c, inter_mem ha hc, b ∩ d, inter_mem hb hd, ?_⟩ + ac_rfl }⟩ + +/-- The supremum of two filters is the filter that contains sets that belong to both filters. -/ +instance : Sup (Filter α) where + sup f g := + { sets := {s | s ∈ f ∧ s ∈ g} + univ_sets := ⟨univ_mem, univ_mem⟩ + sets_of_superset := fun h₁ h₂ ↦ ⟨mem_of_superset h₁.1 h₂, mem_of_superset h₁.2 h₂⟩ + inter_sets := fun h₁ h₂ ↦ ⟨inter_mem h₁.1 h₂.1, inter_mem h₁.2 h₂.2⟩ } + +/-- A filter is `NeBot` if it is not equal to `⊥`, or equivalently the empty set does not belong to +the filter. Bourbaki include this assumption in the definition of a filter but we prefer to have a +`CompleteLattice` structure on `Filter _`, so we use a typeclass argument in lemmas instead. -/ +class NeBot (f : Filter α) : Prop where + /-- The filter is nontrivial: `f ≠ ⊥` or equivalently, `∅ ∉ f`. -/ + ne' : f ≠ ⊥ + +theorem neBot_iff {f : Filter α} : NeBot f ↔ f ≠ ⊥ := + ⟨fun h => h.1, fun h => ⟨h⟩⟩ + +/-- `f.Eventually p` or `∀ᶠ x in f, p x` mean that `{x | p x} ∈ f`. E.g., `∀ᶠ x in atTop, p x` +means that `p` holds true for sufficiently large `x`. -/ +protected def Eventually (p : α → Prop) (f : Filter α) : Prop := + { x | p x } ∈ f + +@[inherit_doc Filter.Eventually] +notation3 "∀ᶠ "(...)" in "f", "r:(scoped p => Filter.Eventually p f) => r + +/-- `f.Frequently p` or `∃ᶠ x in f, p x` mean that `{x | ¬p x} ∉ f`. E.g., `∃ᶠ x in atTop, p x` +means that there exist arbitrarily large `x` for which `p` holds true. -/ +protected def Frequently (p : α → Prop) (f : Filter α) : Prop := + ¬∀ᶠ x in f, ¬p x + +@[inherit_doc Filter.Frequently] +notation3 "∃ᶠ "(...)" in "f", "r:(scoped p => Filter.Frequently p f) => r + +/-- Two functions `f` and `g` are *eventually equal* along a filter `l` if the set of `x` such that +`f x = g x` belongs to `l`. -/ +def EventuallyEq (l : Filter α) (f g : α → β) : Prop := + ∀ᶠ x in l, f x = g x + +@[inherit_doc] +notation:50 f " =ᶠ[" l:50 "] " g:50 => EventuallyEq l f g + +/-- A function `f` is eventually less than or equal to a function `g` at a filter `l`. -/ +def EventuallyLE [LE β] (l : Filter α) (f g : α → β) : Prop := + ∀ᶠ x in l, f x ≤ g x + +@[inherit_doc] +notation:50 f " ≤ᶠ[" l:50 "] " g:50 => EventuallyLE l f g + +/-- The forward map of a filter -/ +def map (m : α → β) (f : Filter α) : Filter β where + sets := preimage m ⁻¹' f.sets + univ_sets := univ_mem + sets_of_superset hs st := mem_of_superset hs fun _x hx ↦ st hx + inter_sets hs ht := inter_mem hs ht + +/-- `Filter.Tendsto` is the generic "limit of a function" predicate. + `Tendsto f l₁ l₂` asserts that for every `l₂` neighborhood `a`, + the `f`-preimage of `a` is an `l₁` neighborhood. -/ +def Tendsto (f : α → β) (l₁ : Filter α) (l₂ : Filter β) := + l₁.map f ≤ l₂ + +/-- The inverse map of a filter. A set `s` belongs to `Filter.comap m f` if either of the following +equivalent conditions hold. + +1. There exists a set `t ∈ f` such that `m ⁻¹' t ⊆ s`. This is used as a definition. +2. The set `kernImage m s = {y | ∀ x, m x = y → x ∈ s}` belongs to `f`, see `Filter.mem_comap'`. +3. The set `(m '' sᶜ)ᶜ` belongs to `f`, see `Filter.mem_comap_iff_compl` and +`Filter.compl_mem_comap`. -/ +def comap (m : α → β) (f : Filter β) : Filter α where + sets := { s | ∃ t ∈ f, m ⁻¹' t ⊆ s } + univ_sets := ⟨univ, univ_mem, subset_univ _⟩ + sets_of_superset := fun ⟨a', ha', ma'a⟩ ab => ⟨a', ha', ma'a.trans ab⟩ + inter_sets := fun ⟨a', ha₁, ha₂⟩ ⟨b', hb₁, hb₂⟩ => + ⟨a' ∩ b', inter_mem ha₁ hb₁, inter_subset_inter ha₂ hb₂⟩ + +/-- Product of filters. This is the filter generated by cartesian products +of elements of the component filters. -/ +protected def prod (f : Filter α) (g : Filter β) : Filter (α × β) := + f.comap Prod.fst ⊓ g.comap Prod.snd + +/-- Coproduct of filters. -/ +protected def coprod (f : Filter α) (g : Filter β) : Filter (α × β) := + f.comap Prod.fst ⊔ g.comap Prod.snd + +instance instSProd : SProd (Filter α) (Filter β) (Filter (α × β)) where + sprod := Filter.prod + +theorem prod_eq_inf (f : Filter α) (g : Filter β) : f ×ˢ g = f.comap Prod.fst ⊓ g.comap Prod.snd := + rfl + +/-- The monadic bind operation on filter is defined the usual way in terms of `map` and `join`. + +Unfortunately, this `bind` does not result in the expected applicative. See `Filter.seq` for the +applicative instance. -/ +def bind (f : Filter α) (m : α → Filter β) : Filter β := + join (map m f) + +/-- The applicative sequentiation operation. This is not induced by the bind operation. -/ +def seq (f : Filter (α → β)) (g : Filter α) : Filter β where + sets := { s | ∃ u ∈ f, ∃ t ∈ g, ∀ m ∈ u, ∀ x ∈ t, (m : α → β) x ∈ s } + univ_sets := ⟨univ, univ_mem, univ, univ_mem, fun _ _ _ _ => trivial⟩ + sets_of_superset := fun ⟨t₀, t₁, h₀, h₁, h⟩ hst => + ⟨t₀, t₁, h₀, h₁, fun _ hx _ hy => hst <| h _ hx _ hy⟩ + inter_sets := fun ⟨t₀, ht₀, t₁, ht₁, ht⟩ ⟨u₀, hu₀, u₁, hu₁, hu⟩ => + ⟨t₀ ∩ u₀, inter_mem ht₀ hu₀, t₁ ∩ u₁, inter_mem ht₁ hu₁, fun _ ⟨hx₀, hx₁⟩ _ ⟨hy₀, hy₁⟩ => + ⟨ht _ hx₀ _ hy₀, hu _ hx₁ _ hy₁⟩⟩ + +/-- This filter is characterized by `Filter.eventually_curry_iff`: +`(∀ᶠ (x : α × β) in f.curry g, p x) ↔ ∀ᶠ (x : α) in f, ∀ᶠ (y : β) in g, p (x, y)`. Useful +in adding quantifiers to the middle of `Tendsto`s. See +`hasFDerivAt_of_tendstoUniformlyOnFilter`. -/ +def curry (f : Filter α) (g : Filter β) : Filter (α × β) := + bind f fun a ↦ map (a, ·) g + +/-- `pure x` is the set of sets that contain `x`. It is equal to `𝓟 {x}` but +with this definition we have `s ∈ pure a` defeq `a ∈ s`. -/ +instance : Pure Filter := + ⟨fun x => + { sets := { s | x ∈ s } + inter_sets := And.intro + sets_of_superset := fun hs hst => hst hs + univ_sets := trivial }⟩ + +instance : Bind Filter := + ⟨@Filter.bind⟩ + +instance : Functor Filter where map := @Filter.map + +end Filter + +namespace Mathlib.Tactic + +open Lean Meta Elab Tactic + +/-- +`filter_upwards [h₁, ⋯, hₙ]` replaces a goal of the form `s ∈ f` and terms +`h₁ : t₁ ∈ f, ⋯, hₙ : tₙ ∈ f` with `∀ x, x ∈ t₁ → ⋯ → x ∈ tₙ → x ∈ s`. +The list is an optional parameter, `[]` being its default value. + +`filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ` is a short form for +`{ filter_upwards [h₁, ⋯, hₙ], intros a₁ a₂ ⋯ aₖ }`. + +`filter_upwards [h₁, ⋯, hₙ] using e` is a short form for +`{ filter_upwards [h1, ⋯, hn], exact e }`. + +Combining both shortcuts is done by writing `filter_upwards [h₁, ⋯, hₙ] with a₁ a₂ ⋯ aₖ using e`. +Note that in this case, the `aᵢ` terms can be used in `e`. +-/ +syntax (name := filterUpwards) "filter_upwards" (" [" term,* "]")? + (" with" (ppSpace colGt term:max)*)? (" using " term)? : tactic + +elab_rules : tactic +| `(tactic| filter_upwards $[[$[$args],*]]? $[with $wth*]? $[using $usingArg]?) => do + let config : ApplyConfig := {newGoals := ApplyNewGoals.nonDependentOnly} + for e in args.getD #[] |>.reverse do + let goal ← getMainGoal + replaceMainGoal <| ← goal.withContext <| runTermElab do + let m ← mkFreshExprMVar none + let lem ← Term.elabTermEnsuringType + (← ``(Filter.mp_mem $e $(← Term.exprToSyntax m))) (← goal.getType) + goal.assign lem + return [m.mvarId!] + liftMetaTactic fun goal => do + goal.apply (← mkConstWithFreshMVarLevels ``Filter.univ_mem') config + evalTactic <|← `(tactic| dsimp (config := {zeta := false}) only [Set.mem_setOf_eq]) + if let some l := wth then + evalTactic <|← `(tactic| intro $[$l]*) + if let some e := usingArg then + evalTactic <|← `(tactic| exact $e) + +end Mathlib.Tactic diff --git a/Mathlib/Order/Filter/Germ/Basic.lean b/Mathlib/Order/Filter/Germ/Basic.lean index dee43bb2b8c71..ec0c18e57cedf 100644 --- a/Mathlib/Order/Filter/Germ/Basic.lean +++ b/Mathlib/Order/Filter/Germ/Basic.lean @@ -118,7 +118,7 @@ def IsConstant {l : Filter α} (P : Germ l β) : Prop := exact fun f g b hfg hf ↦ (hfg.symm).trans hf theorem isConstant_coe {l : Filter α} {b} (h : ∀ x', f x' = b) : (↑f : Germ l β).IsConstant := - ⟨b, Eventually.of_forall (fun x ↦ h x)⟩ + ⟨b, Eventually.of_forall h⟩ @[simp] theorem isConstant_coe_const {l : Filter α} {b : β} : (fun _ : α ↦ b : Germ l β).IsConstant := by diff --git a/Mathlib/Order/Filter/Ker.lean b/Mathlib/Order/Filter/Ker.lean index 29f0a9d1d3129..84ab8db20e0cf 100644 --- a/Mathlib/Order/Filter/Ker.lean +++ b/Mathlib/Order/Filter/Ker.lean @@ -21,9 +21,6 @@ namespace Filter variable {ι : Sort*} {α β : Type*} {f g : Filter α} {s : Set α} {a : α} -/-- The *kernel* of a filter is the intersection of all its sets. -/ -def ker (f : Filter α) : Set α := ⋂₀ f.sets - lemma ker_def (f : Filter α) : f.ker = ⋂ s ∈ f, s := sInter_eq_biInter @[simp] lemma mem_ker : a ∈ f.ker ↔ ∀ s ∈ f, a ∈ s := mem_sInter diff --git a/Mathlib/Order/Filter/Lift.lean b/Mathlib/Order/Filter/Lift.lean index d292896c54051..95e8d4708a1be 100644 --- a/Mathlib/Order/Filter/Lift.lean +++ b/Mathlib/Order/Filter/Lift.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl -/ import Mathlib.Order.Filter.Bases +import Mathlib.Order.Filter.Prod import Mathlib.Order.ConditionallyCompleteLattice.Basic /-! diff --git a/Mathlib/Order/Filter/NAry.lean b/Mathlib/Order/Filter/NAry.lean index 881c3b3ed2461..747639ad50753 100644 --- a/Mathlib/Order/Filter/NAry.lean +++ b/Mathlib/Order/Filter/NAry.lean @@ -29,8 +29,8 @@ open Filter namespace Filter variable {α α' β β' γ γ' δ δ' ε ε' : Type*} {m : α → β → γ} {f f₁ f₂ : Filter α} - {g g₁ g₂ : Filter β} {h h₁ h₂ : Filter γ} {s s₁ s₂ : Set α} {t t₁ t₂ : Set β} {u : Set γ} - {v : Set δ} {a : α} {b : β} {c : γ} + {g g₁ g₂ : Filter β} {h : Filter γ} {s : Set α} {t : Set β} {u : Set γ} + {a : α} {b : β} /-- The image of a binary function `m : α → β → γ` as a function `Filter α → Filter β → Filter γ`. Mathematically this should be thought of as the image of the corresponding function `α × β → γ`. -/ @@ -51,7 +51,7 @@ theorem map_prod_eq_map₂ (m : α → β → γ) (f : Filter α) (g : Filter β theorem map_prod_eq_map₂' (m : α × β → γ) (f : Filter α) (g : Filter β) : Filter.map m (f ×ˢ g) = map₂ (fun a b => m (a, b)) f g := - map_prod_eq_map₂ (curry m) f g + map_prod_eq_map₂ m.curry f g @[simp] theorem map₂_mk_eq_prod (f : Filter α) (g : Filter β) : map₂ Prod.mk f g = f ×ˢ g := by @@ -145,7 +145,7 @@ theorem map₂_map_right (m : α → γ → δ) (n : β → γ) : @[simp] theorem map₂_curry (m : α × β → γ) (f : Filter α) (g : Filter β) : - map₂ (curry m) f g = (f ×ˢ g).map m := + map₂ m.curry f g = (f ×ˢ g).map m := (map_prod_eq_map₂' _ _ _).symm @[simp] diff --git a/Mathlib/Order/Filter/Prod.lean b/Mathlib/Order/Filter/Prod.lean index 4cf3233718cf7..b2af14e42295d 100644 --- a/Mathlib/Order/Filter/Prod.lean +++ b/Mathlib/Order/Filter/Prod.lean @@ -46,17 +46,6 @@ section Prod variable {s : Set α} {t : Set β} {f : Filter α} {g : Filter β} -/-- Product of filters. This is the filter generated by cartesian products -of elements of the component filters. -/ -protected def prod (f : Filter α) (g : Filter β) : Filter (α × β) := - f.comap Prod.fst ⊓ g.comap Prod.snd - -instance instSProd : SProd (Filter α) (Filter β) (Filter (α × β)) where - sprod := Filter.prod - -theorem prod_eq_inf (f : Filter α) (g : Filter β) : f ×ˢ g = f.comap Prod.fst ⊓ g.comap Prod.snd := - rfl - theorem prod_mem_prod (hs : s ∈ f) (ht : t ∈ g) : s ×ˢ t ∈ f ×ˢ g := inter_mem_inf (preimage_mem_comap hs) (preimage_mem_comap ht) @@ -69,6 +58,10 @@ theorem mem_prod_iff {s : Set (α × β)} {f : Filter α} {g : Filter β} : · rintro ⟨t₁, ht₁, t₂, ht₂, h⟩ exact mem_inf_of_inter (preimage_mem_comap ht₁) (preimage_mem_comap ht₂) h +@[simp] +theorem compl_diagonal_mem_prod {l₁ l₂ : Filter α} : (diagonal α)ᶜ ∈ l₁ ×ˢ l₂ ↔ Disjoint l₁ l₂ := by + simp only [mem_prod_iff, Filter.disjoint_iff, prod_subset_compl_diagonal_iff_disjoint] + @[simp] theorem prod_mem_prod_iff [f.NeBot] [g.NeBot] : s ×ˢ t ∈ f ×ˢ g ↔ s ∈ f ∧ t ∈ g := ⟨fun h => @@ -436,10 +429,6 @@ section Coprod variable {f : Filter α} {g : Filter β} -/-- Coproduct of filters. -/ -protected def coprod (f : Filter α) (g : Filter β) : Filter (α × β) := - f.comap Prod.fst ⊔ g.comap Prod.snd - theorem coprod_eq_prod_top_sup_top_prod (f : Filter α) (g : Filter β) : Filter.coprod f g = f ×ˢ ⊤ ⊔ ⊤ ×ˢ g := by rw [prod_top, top_prod] diff --git a/Mathlib/Order/Filter/Ultrafilter.lean b/Mathlib/Order/Filter/Ultrafilter.lean index 3d1ae9a87f5fc..6f238409f1d35 100644 --- a/Mathlib/Order/Filter/Ultrafilter.lean +++ b/Mathlib/Order/Filter/Ultrafilter.lean @@ -465,4 +465,8 @@ theorem ofComapInfPrincipal_eq_of_map (h : m '' s ∈ g) : (ofComapInfPrincipal _ ≤ ↑g ⊓ (𝓟 <| m '' s) := inf_le_inf_right _ map_comap_le _ = ↑g := inf_of_le_left (le_principal_iff.mpr h) +theorem eq_of_le_pure {X : Type _} {α : Filter X} (hα : α.NeBot) {x y : X} + (hx : α ≤ pure x) (hy : α ≤ pure y) : x = y := + Filter.pure_injective (hα.le_pure_iff.mp hx ▸ hα.le_pure_iff.mp hy) + end Ultrafilter diff --git a/Mathlib/Order/Heyting/Basic.lean b/Mathlib/Order/Heyting/Basic.lean index 913803105f8c0..199354c730cff 100644 --- a/Mathlib/Order/Heyting/Basic.lean +++ b/Mathlib/Order/Heyting/Basic.lean @@ -589,7 +589,7 @@ end GeneralizedCoheytingAlgebra section HeytingAlgebra -variable [HeytingAlgebra α] {a b c : α} +variable [HeytingAlgebra α] {a b : α} @[simp] theorem himp_bot (a : α) : a ⇨ ⊥ = aᶜ := @@ -760,7 +760,7 @@ end HeytingAlgebra section CoheytingAlgebra -variable [CoheytingAlgebra α] {a b c : α} +variable [CoheytingAlgebra α] {a b : α} @[simp] theorem top_sdiff' (a : α) : ⊤ \ a = ¬a := @@ -983,7 +983,7 @@ protected abbrev Function.Injective.generalizedHeytingAlgebra [Sup α] [Inf α] exact le_top, le_himp_iff := fun a b c => by change f _ ≤ _ ↔ f _ ≤ _ - erw [map_himp, map_inf, le_himp_iff] } + rw [map_himp, map_inf, le_himp_iff] } -- See note [reducible non-instances] /-- Pullback a `GeneralizedCoheytingAlgebra` along an injection. -/ @@ -1001,7 +1001,7 @@ protected abbrev Function.Injective.generalizedCoheytingAlgebra [Sup α] [Inf α exact bot_le, sdiff_le_iff := fun a b c => by change f _ ≤ _ ↔ f _ ≤ _ - erw [map_sdiff, map_sup, sdiff_le_iff] } + rw [map_sdiff, map_sup, sdiff_le_iff] } -- See note [reducible non-instances] /-- Pullback a `HeytingAlgebra` along an injection. -/ @@ -1017,7 +1017,7 @@ protected abbrev Function.Injective.heytingAlgebra [Sup α] [Inf α] [Top α] [B change f _ ≤ _ rw [map_bot] exact bot_le, - himp_bot := fun a => hf <| by erw [map_himp, map_compl, map_bot, himp_bot] } + himp_bot := fun a => hf <| by rw [map_himp, map_compl, map_bot, himp_bot] } -- See note [reducible non-instances] /-- Pullback a `CoheytingAlgebra` along an injection. -/ @@ -1033,7 +1033,7 @@ protected abbrev Function.Injective.coheytingAlgebra [Sup α] [Inf α] [Top α] change f _ ≤ _ rw [map_top] exact le_top, - top_sdiff := fun a => hf <| by erw [map_sdiff, map_hnot, map_top, top_sdiff'] } + top_sdiff := fun a => hf <| by rw [map_sdiff, map_hnot, map_top, top_sdiff'] } -- See note [reducible non-instances] /-- Pullback a `BiheytingAlgebra` along an injection. -/ diff --git a/Mathlib/Order/Heyting/Hom.lean b/Mathlib/Order/Heyting/Hom.lean index 358a7b6215806..6b0940817f6d3 100644 --- a/Mathlib/Order/Heyting/Hom.lean +++ b/Mathlib/Order/Heyting/Hom.lean @@ -190,7 +190,6 @@ theorem map_compl (a : α) : f aᶜ = (f a)ᶜ := by rw [← himp_bot, ← himp_ @[simp] theorem map_bihimp (a b : α) : f (a ⇔ b) = f a ⇔ f b := by simp_rw [bihimp, map_inf, map_himp] --- TODO: `map_bihimp` end HeytingAlgebra section CoheytingAlgebra diff --git a/Mathlib/Order/Heyting/Regular.lean b/Mathlib/Order/Heyting/Regular.lean index ed41e246a1c47..98043e41c3ecf 100644 --- a/Mathlib/Order/Heyting/Regular.lean +++ b/Mathlib/Order/Heyting/Regular.lean @@ -76,7 +76,7 @@ protected theorem IsRegular.disjoint_compl_right_iff (hb : IsRegular b) : abbrev _root_.BooleanAlgebra.ofRegular (h : ∀ a : α, IsRegular (a ⊔ aᶜ)) : BooleanAlgebra α := have : ∀ a : α, IsCompl a aᶜ := fun a => ⟨disjoint_compl_right, - codisjoint_iff.2 <| by erw [← (h a), compl_sup, inf_compl_eq_bot, compl_bot]⟩ + codisjoint_iff.2 <| by rw [← (h a), compl_sup, inf_compl_eq_bot, compl_bot]⟩ { ‹HeytingAlgebra α›, GeneralizedHeytingAlgebra.toDistribLattice with himp_eq := fun a b => diff --git a/Mathlib/Order/Hom/Basic.lean b/Mathlib/Order/Hom/Basic.lean index 5f4bd78be7ae1..96b44c3f6a264 100644 --- a/Mathlib/Order/Hom/Basic.lean +++ b/Mathlib/Order/Hom/Basic.lean @@ -111,7 +111,8 @@ abbrev OrderHomClass (F : Type*) (α β : outParam Type*) [LE α] [LE β] [FunLi /-- `OrderIsoClass F α β` states that `F` is a type of order isomorphisms. You should extend this class when you extend `OrderIso`. -/ -class OrderIsoClass (F α β : Type*) [LE α] [LE β] [EquivLike F α β] : Prop where +class OrderIsoClass (F : Type*) (α β : outParam Type*) [LE α] [LE β] [EquivLike F α β] : + Prop where /-- An order isomorphism respects `≤`. -/ map_le_map_iff (f : F) {a b : α} : f a ≤ f b ↔ a ≤ b @@ -914,7 +915,7 @@ open Set section LE -variable [LE α] [LE β] [LE γ] +variable [LE α] [LE β] --@[simp] Porting note (#10618): simp can prove it theorem le_iff_le (e : α ≃o β) {x y : α} : e x ≤ e y ↔ x ≤ y := @@ -928,7 +929,7 @@ theorem symm_apply_le (e : α ≃o β) {x : α} {y : β} : e.symm y ≤ x ↔ y end LE -variable [Preorder α] [Preorder β] [Preorder γ] +variable [Preorder α] [Preorder β] protected theorem monotone (e : α ≃o β) : Monotone e := e.toOrderEmbedding.monotone @@ -1052,7 +1053,7 @@ end Equiv namespace StrictMono variable [LinearOrder α] [Preorder β] -variable (f : α → β) (h_mono : StrictMono f) (h_surj : Function.Surjective f) +variable (f : α → β) (h_mono : StrictMono f) /-- A strictly monotone function with a right inverse is an order isomorphism. -/ @[simps (config := .asFn)] @@ -1171,6 +1172,13 @@ theorem coe_toDualTopEquiv_eq [LE α] : (WithBot.toDualTopEquiv : WithBot αᵒᵈ → (WithTop α)ᵒᵈ) = toDual ∘ WithBot.ofDual := funext fun _ => rfl +/-- The coercion `α → WithBot α` bundled as monotone map. -/ +@[simps] +def coeOrderHom {α : Type*} [Preorder α] : α ↪o WithBot α where + toFun := (↑) + inj' := WithBot.coe_injective + map_rel_iff' := WithBot.coe_le_coe + end WithBot namespace WithTop @@ -1202,6 +1210,13 @@ theorem coe_toDualBotEquiv [LE α] : (WithTop.toDualBotEquiv : WithTop αᵒᵈ → (WithBot α)ᵒᵈ) = toDual ∘ WithTop.ofDual := funext fun _ => rfl +/-- The coercion `α → WithTop α` bundled as monotone map. -/ +@[simps] +def coeOrderHom {α : Type*} [Preorder α] : α ↪o WithTop α where + toFun := (↑) + inj' := WithTop.coe_injective + map_rel_iff' := WithTop.coe_le_coe + end WithTop namespace OrderIso diff --git a/Mathlib/Order/Hom/Bounded.lean b/Mathlib/Order/Hom/Bounded.lean index 971df11a1b4ff..92fa0698730b3 100644 --- a/Mathlib/Order/Hom/Bounded.lean +++ b/Mathlib/Order/Hom/Bounded.lean @@ -59,14 +59,16 @@ section /-- `TopHomClass F α β` states that `F` is a type of `⊤`-preserving morphisms. You should extend this class when you extend `TopHom`. -/ -class TopHomClass (F α β : Type*) [Top α] [Top β] [FunLike F α β] : Prop where +class TopHomClass (F : Type*) (α β : outParam Type*) [Top α] [Top β] [FunLike F α β] : + Prop where /-- A `TopHomClass` morphism preserves the top element. -/ map_top (f : F) : f ⊤ = ⊤ /-- `BotHomClass F α β` states that `F` is a type of `⊥`-preserving morphisms. You should extend this class when you extend `BotHom`. -/ -class BotHomClass (F α β : Type*) [Bot α] [Bot β] [FunLike F α β] : Prop where +class BotHomClass (F : Type*) (α β : outParam Type*) [Bot α] [Bot β] [FunLike F α β] : + Prop where /-- A `BotHomClass` morphism preserves the bottom element. -/ map_bot (f : F) : f ⊥ = ⊥ diff --git a/Mathlib/Order/Hom/Set.lean b/Mathlib/Order/Hom/Set.lean index 5017a61157aee..382a2354e4f5d 100644 --- a/Mathlib/Order/Hom/Set.lean +++ b/Mathlib/Order/Hom/Set.lean @@ -5,6 +5,7 @@ Authors: Johan Commelin -/ import Mathlib.Order.Hom.Basic import Mathlib.Logic.Equiv.Set +import Mathlib.Data.Set.Monotone import Mathlib.Data.Set.Image import Mathlib.Order.WellFounded @@ -15,13 +16,13 @@ import Mathlib.Order.WellFounded open OrderDual -variable {F α β γ δ : Type*} +variable {α β : Type*} namespace OrderIso section LE -variable [LE α] [LE β] [LE γ] +variable [LE α] [LE β] theorem range_eq (e : α ≃o β) : Set.range e = Set.univ := e.surjective.range_eq @@ -57,7 +58,7 @@ end LE open Set -variable [Preorder α] [Preorder β] [Preorder γ] +variable [Preorder α] /-- Order isomorphism between two equal sets. -/ def setCongr (s t : Set α) (h : s = t) : diff --git a/Mathlib/Order/InitialSeg.lean b/Mathlib/Order/InitialSeg.lean index 83ab64a3e5d24..cfc294fcbe01c 100644 --- a/Mathlib/Order/InitialSeg.lean +++ b/Mathlib/Order/InitialSeg.lean @@ -1,12 +1,12 @@ /- Copyright (c) 2017 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Mario Carneiro, Floris van Doorn +Authors: Mario Carneiro, Floris van Doorn, Violeta Hernández Palacios -/ +import Mathlib.Data.Sum.Order import Mathlib.Logic.Equiv.Set import Mathlib.Order.RelIso.Set import Mathlib.Order.WellFounded -import Mathlib.Data.Sum.Order /-! # Initial and principal segments @@ -21,12 +21,18 @@ This file defines initial and principal segments. segment, i.e., an interval of the form `(-∞, top)` for some element `top`. It is denoted by `r ≺i s`. +The lemmas `Ordinal.type_le_iff` and `Ordinal.type_lt_iff` tell us that `≼i` corresponds to the `≤` +relation on ordinals, while `≺i` corresponds to the `<` relation. This prompts us to think of +`PrincipalSeg` as a "strict" version of `InitialSeg`. + ## Notations These notations belong to the `InitialSeg` locale. * `r ≼i s`: the type of initial segment embeddings of `r` into `s`. * `r ≺i s`: the type of principal segment embeddings of `r` into `s`. +* `α ≤i β` is an abbreviation for `(· < ·) ≼i (· < ·)`. +* `α InitialSeg +/-- An `InitialSeg` between the `<` relations of two types. -/ +notation:25 α:24 " ≤i " β:25 => @InitialSeg α β (· < ·) (· < ·) + namespace InitialSeg instance : Coe (r ≼i s) (r ↪r s) := @@ -71,6 +78,24 @@ instance : FunLike (r ≼i s) α β where instance : EmbeddingLike (r ≼i s) α β where injective' f := f.inj' +/-- An initial segment embedding between the `<` relations of two partial orders is an order +embedding. -/ +def toOrderEmbedding [PartialOrder α] [PartialOrder β] (f : α ≤i β) : α ↪o β := + f.orderEmbeddingOfLTEmbedding + +@[simp] +theorem toOrderEmbedding_apply [PartialOrder α] [PartialOrder β] (f : α ≤i β) (x : α) : + f.toOrderEmbedding x = f x := + rfl + +@[simp] +theorem coe_toOrderEmbedding [PartialOrder α] [PartialOrder β] (f : α ≤i β) : + (f.toOrderEmbedding : α → β) = f := + rfl + +instance [PartialOrder α] [PartialOrder β] : OrderHomClass (α ≤i β) α β where + map_rel f := f.toOrderEmbedding.map_rel_iff.2 + @[ext] lemma ext {f g : r ≼i s} (h : ∀ x, f x = g x) : f = g := DFunLike.ext f g h @@ -87,6 +112,9 @@ alias init := mem_range_of_rel theorem map_rel_iff {a b : α} (f : r ≼i s) : s (f a) (f b) ↔ r a b := f.map_rel_iff' +theorem inj (f : r ≼i s) {a b : α} : f a = f b ↔ a = b := + f.toRelEmbedding.inj + theorem exists_eq_iff_rel (f : r ≼i s) {a : α} {b : β} : s b (f a) ↔ ∃ a', f a' = b ∧ r a' a := ⟨fun h => by rcases f.mem_range_of_rel h with ⟨a', rfl⟩ @@ -158,16 +186,19 @@ theorem antisymm_symm [IsWellOrder α r] [IsWellOrder β s] (f : r ≼i s) (g : RelIso.coe_fn_injective rfl theorem eq_or_principal [IsWellOrder β s] (f : r ≼i s) : - Surjective f ∨ ∃ b, ∀ x, s x b ↔ ∃ y, f y = x := - or_iff_not_imp_right.2 fun h b => - Acc.recOn (IsWellFounded.wf.apply b : Acc s b) fun x _ IH => - not_forall_not.1 fun hn => - h - ⟨x, fun y => - ⟨IH _, fun ⟨a, e⟩ => by - rw [← e] - exact (trichotomous _ _).resolve_right - (not_or_intro (hn a) fun hl => not_exists.2 hn (f.mem_range_of_rel hl))⟩⟩ + Surjective f ∨ ∃ b, ∀ x, x ∈ Set.range f ↔ s x b := by + apply or_iff_not_imp_right.2 + intro h b + push_neg at h + apply IsWellFounded.induction s b + intro x IH + obtain ⟨y, ⟨hy, hs⟩ | ⟨hy, hs⟩⟩ := h x + · obtain (rfl | h) := (trichotomous y x).resolve_left hs + · exact hy + · obtain ⟨z, rfl⟩ := hy + exact f.mem_range_of_rel h + · obtain ⟨z, rfl⟩ := IH y hs + cases hy (Set.mem_range_self z) /-- Restrict the codomain of an initial segment -/ def codRestrict (p : Set β) (f : r ≼i s) (H : ∀ a, f a ∈ p) : r ≼i Subrel s p := @@ -216,15 +247,16 @@ embeddings are called principal segments -/ structure PrincipalSeg {α β : Type*} (r : α → α → Prop) (s : β → β → Prop) extends r ↪r s where /-- The supremum of the principal segment -/ top : β - /-- The image of the order embedding is the set of elements `b` such that `s b top` -/ - down' : ∀ b, s b top ↔ ∃ a, toRelEmbedding a = b + /-- The range of the order embedding is the set of elements `b` such that `s b top` -/ + mem_range_iff_rel' : ∀ b, b ∈ Set.range toRelEmbedding ↔ s b top -- Porting note: deleted `scoped[InitialSeg]` -/-- If `r` is a relation on `α` and `s` in a relation on `β`, then `f : r ≺i s` is an order -embedding whose range is an open interval `(-∞, top)` for some element `top` of `β`. Such order -embeddings are called principal segments -/ +@[inherit_doc] infixl:25 " ≺i " => PrincipalSeg +/-- A `PrincipalSeg` between the `<` relations of two types. -/ +notation:25 α:24 " @PrincipalSeg α β (· < ·) (· < ·) + namespace PrincipalSeg instance : CoeOut (r ≺i s) (r ↪r s) := @@ -237,15 +269,22 @@ instance : CoeFun (r ≺i s) fun _ => α → β := theorem coe_fn_mk (f : r ↪r s) (t o) : (@PrincipalSeg.mk _ _ r s f t o : α → β) = f := rfl +theorem mem_range_iff_rel (f : r ≺i s) : ∀ {b : β}, b ∈ Set.range f ↔ s b f.top := + f.mem_range_iff_rel' _ + +@[deprecated mem_range_iff_rel (since := "2024-10-07")] theorem down (f : r ≺i s) : ∀ {b : β}, s b f.top ↔ ∃ a, f a = b := - f.down' _ + f.mem_range_iff_rel.symm theorem lt_top (f : r ≺i s) (a : α) : s (f a) f.top := - f.down.2 ⟨_, rfl⟩ + f.mem_range_iff_rel.1 ⟨_, rfl⟩ + +theorem mem_range_of_rel_top (f : r ≺i s) {b : β} (h : s b f.top) : b ∈ Set.range f := + f.mem_range_iff_rel.2 h theorem mem_range_of_rel [IsTrans β s] (f : r ≺i s) {a : α} {b : β} (h : s b (f a)) : b ∈ Set.range f := - f.down.1 <| _root_.trans h <| f.lt_top _ + f.mem_range_of_rel_top <| _root_.trans h <| f.lt_top _ @[deprecated mem_range_of_rel (since := "2024-09-21")] alias init := mem_range_of_rel @@ -267,8 +306,7 @@ alias init_iff := exists_eq_iff_rel /-- A principal segment is the same as a non-surjective initial segment. -/ noncomputable def _root_.InitialSeg.toPrincipalSeg [IsWellOrder β s] (f : r ≼i s) (hf : ¬ Surjective f) : r ≺i s := - letI H := f.eq_or_principal.resolve_left hf - ⟨f, Classical.choose H, Classical.choose_spec H⟩ + ⟨f, _, Classical.choose_spec (f.eq_or_principal.resolve_left hf)⟩ @[simp] theorem _root_.InitialSeg.toPrincipalSeg_apply [IsWellOrder β s] (f : r ≼i s) @@ -286,8 +324,7 @@ instance (r : α → α → Prop) [IsWellOrder α r] : IsEmpty (r ≺i r) := /-- Composition of a principal segment with an initial segment, as a principal segment -/ def ltLe (f : r ≺i s) (g : s ≼i t) : r ≺i t := ⟨@RelEmbedding.trans _ _ _ r s t f g, g f.top, fun a => by - simp only [g.exists_eq_iff_rel, PrincipalSeg.down, exists_and_left.symm, exists_swap, - RelEmbedding.trans_apply, exists_eq_right', InitialSeg.coe_coe_fn]⟩ + simp [g.exists_eq_iff_rel, ← PrincipalSeg.mem_range_iff_rel, exists_swap, ← exists_and_left]⟩ @[simp] theorem lt_le_apply (f : r ≺i s) (g : s ≼i t) (a : α) : (f.ltLe g) a = g (f a) := @@ -313,17 +350,17 @@ theorem trans_top [IsTrans γ t] (f : r ≺i s) (g : s ≺i t) : (f.trans g).top /-- Composition of an order isomorphism with a principal segment, as a principal segment -/ def equivLT (f : r ≃r s) (g : s ≺i t) : r ≺i t := ⟨@RelEmbedding.trans _ _ _ r s t f g, g.top, fun c => - suffices (∃ a : β, g a = c) ↔ ∃ a : α, g (f a) = c by simpa [PrincipalSeg.down] + suffices (∃ a, g a = c) ↔ ∃ a, g (f a) = c by simp [← PrincipalSeg.mem_range_iff_rel] ⟨fun ⟨b, h⟩ => ⟨f.symm b, by simp only [h, RelIso.apply_symm_apply]⟩, fun ⟨a, h⟩ => ⟨f a, h⟩⟩⟩ /-- Composition of a principal segment with an order isomorphism, as a principal segment -/ -def ltEquiv {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} (f : PrincipalSeg r s) - (g : s ≃r t) : PrincipalSeg r t := +def ltEquiv {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} (f : r ≺i s) (g : s ≃r t) : + r ≺i t := ⟨@RelEmbedding.trans _ _ _ r s t f g, g f.top, by intro x - rw [← g.apply_symm_apply x, g.map_rel_iff, f.down', exists_congr] - intro y; exact ⟨congr_arg g, fun h => g.toEquiv.bijective.1 h⟩⟩ + rw [← g.apply_symm_apply x, g.map_rel_iff, ← f.mem_range_iff_rel] + exact exists_congr <| fun _ ↦ ⟨fun h => g.toEquiv.bijective.1 h, congr_arg g⟩⟩ @[simp] theorem equivLT_apply (f : r ≃r s) (g : s ≺i t) (a : α) : (equivLT f g) a = g (f a) := @@ -341,7 +378,7 @@ instance [IsWellOrder β s] : Subsingleton (r ≺i s) := rw [@Subsingleton.elim _ _ (f : r ≼i s) g] have et : f.top = g.top := by refine extensional_of_trichotomous_of_irrefl s fun x => ?_ - simp only [PrincipalSeg.down, ef] + simp only [← PrincipalSeg.mem_range_iff_rel, ef] cases f cases g have := RelEmbedding.coe_fn_injective ef; congr ⟩ @@ -349,14 +386,17 @@ instance [IsWellOrder β s] : Subsingleton (r ≺i s) := theorem top_eq [IsWellOrder γ t] (e : r ≃r s) (f : r ≺i t) (g : s ≺i t) : f.top = g.top := by rw [Subsingleton.elim f (PrincipalSeg.equivLT e g)]; rfl -theorem topLTTop {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} [IsWellOrder γ t] - (f : PrincipalSeg r s) (g : PrincipalSeg s t) (h : PrincipalSeg r t) : t h.top g.top := by +theorem top_rel_top {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} [IsWellOrder γ t] + (f : r ≺i s) (g : s ≺i t) (h : r ≺i t) : t h.top g.top := by rw [Subsingleton.elim h (f.trans g)] apply PrincipalSeg.lt_top +@[deprecated top_rel_top (since := "2024-10-10")] +alias topLTTop := top_rel_top + /-- Any element of a well order yields a principal segment -/ def ofElement {α : Type*} (r : α → α → Prop) (a : α) : Subrel r { b | r b a } ≺i r := - ⟨Subrel.relEmbedding _ _, a, fun _ => ⟨fun h => ⟨⟨_, h⟩, rfl⟩, fun ⟨⟨_, h⟩, rfl⟩ => h⟩⟩ + ⟨Subrel.relEmbedding _ _, a, fun _ => ⟨fun ⟨⟨_, h⟩, rfl⟩ => h, fun h => ⟨⟨_, h⟩, rfl⟩⟩⟩ -- This lemma was always bad, but the linter only noticed after lean4#2644 @[simp, nolint simpNF] @@ -372,7 +412,7 @@ theorem ofElement_top {α : Type*} (r : α → α → Prop) (a : α) : (ofElemen noncomputable def subrelIso (f : r ≺i s) : Subrel s {b | s b f.top} ≃r r := RelIso.symm { toEquiv := ((Equiv.ofInjective f f.injective).trans (Equiv.setCongr - (funext fun _ ↦ propext f.down.symm))), + (funext fun _ ↦ propext f.mem_range_iff_rel))), map_rel_iff' := f.map_rel_iff } -- This lemma was always bad, but the linter only noticed after lean4#2644 @@ -386,15 +426,12 @@ theorem apply_subrelIso (f : r ≺i s) (b : {b | s b f.top}) : -- This lemma was always bad, but the linter only noticed after lean4#2644 @[simp, nolint simpNF] -theorem subrelIso_apply (f : r ≺i s) (a : α) : - f.subrelIso ⟨f a, f.down.mpr ⟨a, rfl⟩⟩ = a := +theorem subrelIso_apply (f : r ≺i s) (a : α) : f.subrelIso ⟨f a, f.lt_top a⟩ = a := Equiv.ofInjective_symm_apply f.injective _ /-- Restrict the codomain of a principal segment -/ def codRestrict (p : Set β) (f : r ≺i s) (H : ∀ a, f a ∈ p) (H₂ : f.top ∈ p) : r ≺i Subrel s p := - ⟨RelEmbedding.codRestrict p f H, ⟨f.top, H₂⟩, fun ⟨_, _⟩ => - f.down.trans <| - exists_congr fun a => show (⟨f a, H a⟩ : p).1 = _ ↔ _ from ⟨Subtype.eq, congr_arg _⟩⟩ + ⟨RelEmbedding.codRestrict p f H, ⟨f.top, H₂⟩, fun ⟨_, _⟩ => by simp [← f.mem_range_iff_rel]⟩ @[simp] theorem codRestrict_apply (p) (f : r ≺i s) (H H₂ a) : codRestrict p f H H₂ a = ⟨f a, H a⟩ := @@ -408,7 +445,7 @@ theorem codRestrict_top (p) (f : r ≺i s) (H H₂) : (codRestrict p f H H₂).t def ofIsEmpty (r : α → α → Prop) [IsEmpty α] {b : β} (H : ∀ b', ¬s b' b) : r ≺i s := { RelEmbedding.ofIsEmpty r s with top := b - down' := by simp [H] } + mem_range_iff_rel' := by simp [H] } @[simp] theorem ofIsEmpty_top (r : α → α → Prop) [IsEmpty α] {b : β} (H : ∀ b', ¬s b' b) : @@ -435,7 +472,7 @@ theorem wellFounded_iff_wellFounded_subrel {β : Type*} {s : β → β → Prop} ⟨fun wf b => ⟨fun b' => ((PrincipalSeg.ofElement _ b).acc b').mpr (wf.apply b')⟩, fun wf => ⟨fun b => Acc.intro _ fun b' hb' => ?_⟩⟩ let f := PrincipalSeg.ofElement s b - obtain ⟨b', rfl⟩ := f.down.mp ((PrincipalSeg.ofElement_top s b).symm ▸ hb' : s b' f.top) + obtain ⟨b', rfl⟩ := f.mem_range_of_rel_top ((PrincipalSeg.ofElement_top s b).symm ▸ hb') exact (f.acc b').mp ((wf b).apply b') theorem wellFounded_iff_principalSeg.{u} {β : Type u} {s : β → β → Prop} [IsTrans β s] : @@ -456,17 +493,14 @@ noncomputable def ltOrEq [IsWellOrder β s] (f : r ≼i s) : (r ≺i s) ⊕ (r · exact Sum.inr (RelIso.ofSurjective f h) · exact Sum.inl (f.toPrincipalSeg h) -theorem ltOrEq_apply_left [IsWellOrder β s] (f : r ≼i s) (g : r ≺i s) (a : α) : - g a = f a := +theorem ltOrEq_apply_left [IsWellOrder β s] (f : r ≼i s) (g : r ≺i s) (a : α) : g a = f a := @InitialSeg.eq α β r s _ g f a -theorem ltOrEq_apply_right [IsWellOrder β s] (f : r ≼i s) (g : r ≃r s) (a : α) : - g a = f a := +theorem ltOrEq_apply_right [IsWellOrder β s] (f : r ≼i s) (g : r ≃r s) (a : α) : g a = f a := InitialSeg.eq (InitialSeg.ofIso g) f a /-- Composition of an initial segment taking values in a well order and a principal segment. -/ -noncomputable def leLT [IsWellOrder β s] [IsTrans γ t] (f : r ≼i s) (g : s ≺i t) : - r ≺i t := +noncomputable def leLT [IsWellOrder β s] [IsTrans γ t] (f : r ≼i s) (g : s ≺i t) : r ≺i t := match f.ltOrEq with | Sum.inl f' => f'.trans g | Sum.inr f' => PrincipalSeg.equivLT f' g @@ -474,9 +508,10 @@ noncomputable def leLT [IsWellOrder β s] [IsTrans γ t] (f : r ≼i s) (g : s @[simp] theorem leLT_apply [IsWellOrder β s] [IsTrans γ t] (f : r ≼i s) (g : s ≺i t) (a : α) : (f.leLT g) a = g (f a) := by - delta InitialSeg.leLT; cases' f.ltOrEq with f' f' - · simp only [PrincipalSeg.trans_apply, f.ltOrEq_apply_left] - · simp only [PrincipalSeg.equivLT_apply, f.ltOrEq_apply_right] + rw [InitialSeg.leLT] + obtain f' | f' := f.ltOrEq + · rw [PrincipalSeg.trans_apply, f.ltOrEq_apply_left] + · rw [PrincipalSeg.equivLT_apply, f.ltOrEq_apply_right] end InitialSeg @@ -547,3 +582,80 @@ noncomputable def InitialSeg.total (r s) [IsWellOrder α r] [IsWellOrder β s] : attribute [nolint simpNF] PrincipalSeg.ofElement_apply PrincipalSeg.subrelIso_symm_apply PrincipalSeg.apply_subrelIso PrincipalSeg.subrelIso_apply + +/-! ### Initial or principal segments with `<` -/ + +namespace InitialSeg + +variable [PartialOrder β] {a a' : α} {b : β} + +theorem mem_range_of_le [Preorder α] (f : α ≤i β) (h : b ≤ f a) : b ∈ Set.range f := by + obtain rfl | hb := h.eq_or_lt + exacts [⟨a, rfl⟩, f.mem_range_of_rel hb] + +-- TODO: this would follow immediately if we had a `RelEmbeddingClass` +@[simp] +theorem le_iff_le [PartialOrder α] (f : α ≤i β) : f a ≤ f a' ↔ a ≤ a' := + f.toOrderEmbedding.le_iff_le + +-- TODO: this would follow immediately if we had a `RelEmbeddingClass` +@[simp] +theorem lt_iff_lt [PartialOrder α] (f : α ≤i β) : f a < f a' ↔ a < a' := + f.toOrderEmbedding.lt_iff_lt + +theorem monotone [PartialOrder α] (f : α ≤i β) : Monotone f := + f.toOrderEmbedding.monotone + +theorem strictMono [PartialOrder α] (f : α ≤i β) : StrictMono f := + f.toOrderEmbedding.strictMono + +theorem le_apply_iff [LinearOrder α] (f : α ≤i β) : b ≤ f a ↔ ∃ c ≤ a, f c = b := by + constructor + · intro h + obtain ⟨c, hc⟩ := f.mem_range_of_le h + refine ⟨c, ?_, hc⟩ + rwa [← hc, f.le_iff_le] at h + · rintro ⟨c, hc, rfl⟩ + exact f.monotone hc + +theorem lt_apply_iff [LinearOrder α] (f : α ≤i β) : b < f a ↔ ∃ a' < a, f a' = b := by + constructor + · intro h + obtain ⟨c, hc⟩ := f.mem_range_of_rel h + refine ⟨c, ?_, hc⟩ + rwa [← hc, f.lt_iff_lt] at h + · rintro ⟨c, hc, rfl⟩ + exact f.strictMono hc + +end InitialSeg + +namespace PrincipalSeg + +variable [PartialOrder β] {a a' : α} {b : β} + +theorem mem_range_of_le [Preorder α] (f : α - -- Porting note: mathlib3 proof finished from here as follows: - -- (It can probably be restored after https://github.com/leanprover-community/mathlib4/pull/856) - -- ac_rfl - -- all_goals - -- solve_by_elim (config := { max_depth := 5 }) [min_le_of_left_le, min_le_of_right_le, - -- le_max_of_le_left, le_max_of_le_right, le_refl] - simp [min_le_of_left_le, min_le_of_right_le, le_max_of_le_left, le_max_of_le_right, le_refl, - min_assoc, max_comm] - + rw [Ioc_union_Ioc, Ioc_union_Ioc] + · ac_rfl + all_goals + solve_by_elim (config := { maxDepth := 5 }) [min_le_of_left_le, min_le_of_right_le, + le_max_of_le_left, le_max_of_le_right, le_refl] end LinearOrder /-! diff --git a/Mathlib/Order/Interval/Set/UnorderedInterval.lean b/Mathlib/Order/Interval/Set/UnorderedInterval.lean index 8c14071911f3d..ea241a7fbf3dc 100644 --- a/Mathlib/Order/Interval/Set/UnorderedInterval.lean +++ b/Mathlib/Order/Interval/Set/UnorderedInterval.lean @@ -44,7 +44,7 @@ namespace Set section Lattice -variable [Lattice α] [Lattice β] {a a₁ a₂ b b₁ b₂ c x : α} +variable [Lattice α] [Lattice β] {a a₁ a₂ b b₁ b₂ x : α} /-- `uIcc a b` is the set of elements lying between `a` and `b`, with `a` and `b` included. Note that we define it more generally in a lattice as `Set.Icc (a ⊓ b) (a ⊔ b)`. In a product type, @@ -134,7 +134,7 @@ open Interval section DistribLattice -variable [DistribLattice α] {a a₁ a₂ b b₁ b₂ c x : α} +variable [DistribLattice α] {a b c : α} lemma eq_of_mem_uIcc_of_mem_uIcc (ha : a ∈ [[b, c]]) (hb : b ∈ [[a, c]]) : a = b := eq_of_inf_eq_sup_eq (inf_congr_right ha.1 hb.1) <| sup_congr_right ha.2 hb.2 @@ -155,7 +155,7 @@ section LinearOrder variable [LinearOrder α] section Lattice -variable [Lattice β] {f : α → β} {s : Set α} {a b : α} +variable [Lattice β] {f : α → β} {a b : α} lemma _root_.MonotoneOn.mapsTo_uIcc (hf : MonotoneOn f (uIcc a b)) : MapsTo f (uIcc a b) (uIcc (f a) (f b)) := by @@ -187,7 +187,7 @@ lemma _root_.Antitone.image_uIcc_subset (hf : Antitone f) : f '' uIcc a b ⊆ uI end Lattice -variable [LinearOrder β] {f : α → β} {s : Set α} {a a₁ a₂ b b₁ b₂ c d x : α} +variable [LinearOrder β] {f : α → β} {s : Set α} {a a₁ a₂ b b₁ b₂ c : α} theorem Icc_min_max : Icc (min a b) (max a b) = [[a, b]] := rfl diff --git a/Mathlib/Order/Irreducible.lean b/Mathlib/Order/Irreducible.lean index ecc3744d96ae4..12ebc35f11d80 100644 --- a/Mathlib/Order/Irreducible.lean +++ b/Mathlib/Order/Irreducible.lean @@ -251,7 +251,7 @@ end SemilatticeInf section DistribLattice -variable [DistribLattice α] {a b c : α} +variable [DistribLattice α] {a : α} @[simp] theorem supPrime_iff_supIrred : SupPrime a ↔ SupIrred a := diff --git a/Mathlib/Order/KrullDimension.lean b/Mathlib/Order/KrullDimension.lean index 86ed7e2ce6e89..4631e6250c4ba 100644 --- a/Mathlib/Order/KrullDimension.lean +++ b/Mathlib/Order/KrullDimension.lean @@ -174,6 +174,8 @@ variable {α β : Type*} variable [Preorder α] [Preorder β] +lemma LTSeries.length_le_krullDim (p : LTSeries α) : p.length ≤ krullDim α := le_sSup ⟨_, rfl⟩ + lemma krullDim_nonneg_of_nonempty [Nonempty α] : 0 ≤ krullDim α := le_sSup ⟨⟨0, fun _ ↦ @Nonempty.some α inferInstance, fun f ↦ f.elim0⟩, rfl⟩ @@ -214,6 +216,14 @@ lemma krullDim_eq_zero_of_unique [Unique α] : krullDim α = 0 := by by_contra r exact ne_of_lt (q.step ⟨0, not_le.mp r⟩) <| Subsingleton.elim _ _ +lemma krullDim_nonpos_of_subsingleton [Subsingleton α] : krullDim α ≤ 0 := by + by_cases hα : Nonempty α + · have := uniqueOfSubsingleton (Classical.choice hα) + exact le_of_eq krullDim_eq_zero_of_unique + · have := not_nonempty_iff.mp hα + exact le_of_lt <| lt_of_eq_of_lt krullDim_eq_bot_of_isEmpty <| + Batteries.compareOfLessAndEq_eq_lt.mp rfl + lemma krullDim_le_of_strictComono_and_surj (f : α → β) (hf : ∀ ⦃a b⦄, f a < f b → a < b) (hf' : Function.Surjective f) : krullDim β ≤ krullDim α := diff --git a/Mathlib/Order/Lattice.lean b/Mathlib/Order/Lattice.lean index 76070c79b4151..8383d090d9c12 100644 --- a/Mathlib/Order/Lattice.lean +++ b/Mathlib/Order/Lattice.lean @@ -528,7 +528,7 @@ def Lattice.mk' {α : Type*} [Sup α] [Inf α] (sup_comm : ∀ a b : α, a ⊔ b section Lattice -variable [Lattice α] {a b c d : α} +variable [Lattice α] {a b c : α} theorem inf_le_sup : a ⊓ b ≤ a ⊔ b := inf_le_left.trans le_sup_left diff --git a/Mathlib/Order/Max.lean b/Mathlib/Order/Max.lean index b355050f7aea9..36518a3cb4aa5 100644 --- a/Mathlib/Order/Max.lean +++ b/Mathlib/Order/Max.lean @@ -158,7 +158,7 @@ theorem NoMaxOrder.not_acc [LT α] [NoMaxOrder α] (a : α) : ¬Acc (· > ·) a section LE -variable [LE α] {a b : α} +variable [LE α] {a : α} /-- `a : α` is a bottom element of `α` if it is less than or equal to any other element of `α`. This predicate is roughly an unbundled version of `OrderBot`, except that a preorder may have @@ -356,7 +356,7 @@ end PartialOrder section Prod -variable [Preorder α] [Preorder β] {a a₁ a₂ : α} {b b₁ b₂ : β} {x y : α × β} +variable [Preorder α] [Preorder β] {a : α} {b : β} {x : α × β} theorem IsBot.prod_mk (ha : IsBot a) (hb : IsBot b) : IsBot (a, b) := fun _ => ⟨ha _, hb _⟩ diff --git a/Mathlib/Order/Minimal.lean b/Mathlib/Order/Minimal.lean index 728087a7dbdf4..688801c79c497 100644 --- a/Mathlib/Order/Minimal.lean +++ b/Mathlib/Order/Minimal.lean @@ -10,13 +10,8 @@ import Mathlib.Order.Interval.Set.Basic /-! # Minimality and Maximality -This file defines minimality and maximality of an element with respect to a predicate `P` on -an ordered type `α`. - -## Main declarations - -* `Minimal P x`: `x` is minimal satisfying `P`. -* `Maximal P x`: `x` is maximal satisfying `P`. +This file proves basic facts about minimality and maximality +of an element with respect to a predicate `P` on an ordered type `α`. ## Implementation Details @@ -52,24 +47,6 @@ section LE variable [LE α] -/-- `Minimal P x` means that `x` is a minimal element satisfying `P`. -/ -def Minimal (P : α → Prop) (x : α) : Prop := P x ∧ ∀ ⦃y⦄, P y → y ≤ x → x ≤ y - -/-- `Maximal P x` means that `x` is a maximal element satisfying `P`. -/ -def Maximal (P : α → Prop) (x : α) : Prop := P x ∧ ∀ ⦃y⦄, P y → x ≤ y → y ≤ x - -lemma Minimal.prop (h : Minimal P x) : P x := - h.1 - -lemma Maximal.prop (h : Maximal P x) : P x := - h.1 - -lemma Minimal.le_of_le (h : Minimal P x) (hy : P y) (hle : y ≤ x) : x ≤ y := - h.2 hy hle - -lemma Maximal.le_of_ge (h : Maximal P x) (hy : P y) (hge : x ≤ y) : y ≤ x := - h.2 hy hge - @[simp] theorem minimal_toDual : Minimal (fun x ↦ P (ofDual x)) (toDual x) ↔ Maximal P x := Iff.rfl @@ -621,15 +598,17 @@ theorem map_maximal_mem (f : s ≃o t) (hx : Maximal (· ∈ s) x) : def mapSetOfMinimal (f : s ≃o t) : {x | Minimal (· ∈ s) x} ≃o {x | Minimal (· ∈ t) x} where toFun x := ⟨f ⟨x, x.2.1⟩, f.map_minimal_mem x.2⟩ invFun x := ⟨f.symm ⟨x, x.2.1⟩, f.symm.map_minimal_mem x.2⟩ - left_inv x := Subtype.ext (by apply congr_arg Subtype.val <| f.left_inv ⟨x, x.2.1⟩) - right_inv x := Subtype.ext (by apply congr_arg Subtype.val <| f.right_inv ⟨x, x.2.1⟩) - map_rel_iff' {_ _} := f.map_rel_iff + left_inv x := Subtype.ext (congr_arg Subtype.val <| f.left_inv ⟨x, x.2.1⟩ :) + right_inv x := Subtype.ext (congr_arg Subtype.val <| f.right_inv ⟨x, x.2.1⟩ :) + map_rel_iff' := f.map_rel_iff /-- If two sets are order isomorphic, their maximals are also order isomorphic. -/ def mapSetOfMaximal (f : s ≃o t) : {x | Maximal (· ∈ s) x} ≃o {x | Maximal (· ∈ t) x} where toFun x := ⟨f ⟨x, x.2.1⟩, f.map_maximal_mem x.2⟩ invFun x := ⟨f.symm ⟨x, x.2.1⟩, f.symm.map_maximal_mem x.2⟩ - __ := (show OrderDual.ofDual ⁻¹' s ≃o OrderDual.ofDual ⁻¹' t from f.dual).mapSetOfMinimal + left_inv x := Subtype.ext (congr_arg Subtype.val <| f.left_inv ⟨x, x.2.1⟩ :) + right_inv x := Subtype.ext (congr_arg Subtype.val <| f.right_inv ⟨x, x.2.1⟩ :) + map_rel_iff' := f.map_rel_iff /-- If two sets are antitonically order isomorphic, their minimals/maximals are too. -/ def setOfMinimalIsoSetOfMaximal (f : s ≃o tᵒᵈ) : diff --git a/Mathlib/Order/ModularLattice.lean b/Mathlib/Order/ModularLattice.lean index 6dfc3e2db07ba..7b2b7f77ae7f8 100644 --- a/Mathlib/Order/ModularLattice.lean +++ b/Mathlib/Order/ModularLattice.lean @@ -218,6 +218,10 @@ theorem sup_lt_sup_of_lt_of_inf_le_inf (hxy : x < y) (hinf : y ⊓ z ≤ x ⊓ z theorem inf_lt_inf_of_lt_of_sup_le_sup (hxy : x < y) (hinf : y ⊔ z ≤ x ⊔ z) : x ⊓ z < y ⊓ z := sup_lt_sup_of_lt_of_inf_le_inf (α := αᵒᵈ) hxy hinf +theorem strictMono_inf_prod_sup : StrictMono fun x ↦ (x ⊓ z, x ⊔ z) := fun _x _y hxy ↦ + ⟨⟨inf_le_inf_right _ hxy.le, sup_le_sup_right hxy.le _⟩, + fun ⟨inf_le, sup_le⟩ ↦ (sup_lt_sup_of_lt_of_inf_le_inf hxy inf_le).not_le sup_le⟩ + /-- A generalization of the theorem that if `N` is a submodule of `M` and `N` and `M / N` are both Artinian, then `M` is Artinian. -/ theorem wellFounded_lt_exact_sequence {β γ : Type*} [PartialOrder β] [Preorder γ] @@ -225,16 +229,9 @@ theorem wellFounded_lt_exact_sequence {β γ : Type*} [PartialOrder β] [Preorde (f₁ : β → α) (f₂ : α → β) (g₁ : γ → α) (g₂ : α → γ) (gci : GaloisCoinsertion f₁ f₂) (gi : GaloisInsertion g₂ g₁) (hf : ∀ a, f₁ (f₂ a) = a ⊓ K) (hg : ∀ a, g₁ (g₂ a) = a ⊔ K) : WellFoundedLT α := - ⟨Subrelation.wf - (@fun A B hAB => - show Prod.Lex (· < ·) (· < ·) (f₂ A, g₂ A) (f₂ B, g₂ B) by - simp only [Prod.lex_def, lt_iff_le_not_le, ← gci.l_le_l_iff, ← gi.u_le_u_iff, hf, hg, - le_antisymm_iff] - simp only [gci.l_le_l_iff, gi.u_le_u_iff, ← lt_iff_le_not_le, ← le_antisymm_iff] - rcases lt_or_eq_of_le (inf_le_inf_right K (le_of_lt hAB)) with h | h - · exact Or.inl h - · exact Or.inr ⟨h, sup_lt_sup_of_lt_of_inf_le_inf hAB (le_of_eq h.symm)⟩) - (InvImage.wf _ (h₁.wf.prod_lex h₂.wf))⟩ + StrictMono.wellFoundedLT (f := fun A ↦ (f₂ A, g₂ A)) fun A B hAB ↦ by + simp only [Prod.le_def, lt_iff_le_not_le, ← gci.l_le_l_iff, ← gi.u_le_u_iff, hf, hg] + exact strictMono_inf_prod_sup hAB /-- A generalization of the theorem that if `N` is a submodule of `M` and `N` and `M / N` are both Noetherian, then `M` is Noetherian. -/ @@ -261,7 +258,7 @@ def infIccOrderIsoIccSup (a b : α) : Set.Icc (a ⊓ b) a ≃o Set.Icc b (a ⊔ (by change a ⊓ ↑x ⊔ b = ↑x rw [inf_comm, inf_sup_assoc_of_le _ x.prop.1, inf_eq_left.2 x.prop.2]) - map_rel_iff' := @fun x y => by + map_rel_iff' {x y} := by simp only [Subtype.mk_le_mk, Equiv.coe_fn_mk, le_sup_right] rw [← Subtype.coe_le_coe] refine ⟨fun h => ?_, fun h => sup_le_sup_right h _⟩ diff --git a/Mathlib/Order/Monotone/Basic.lean b/Mathlib/Order/Monotone/Basic.lean index 3292cce1aeeec..bafac4b6ac367 100644 --- a/Mathlib/Order/Monotone/Basic.lean +++ b/Mathlib/Order/Monotone/Basic.lean @@ -66,7 +66,6 @@ open Function OrderDual universe u v w variable {ι : Type*} {α : Type u} {β : Type v} {γ : Type w} {δ : Type*} {π : ι → Type*} - {r : α → α → Prop} section MonotoneDef @@ -1025,7 +1024,7 @@ theorem Subtype.strictMono_coe [Preorder α] (t : Set α) : section Preorder -variable [Preorder α] [Preorder β] [Preorder γ] [Preorder δ] {f : α → γ} {g : β → δ} {a b : α} +variable [Preorder α] [Preorder β] [Preorder γ] [Preorder δ] {f : α → γ} {g : β → δ} theorem monotone_fst : Monotone (@Prod.fst α β) := fun _ _ ↦ And.left @@ -1074,7 +1073,7 @@ theorem const_strictMono [Nonempty β] : StrictMono (const β : α → β → α end Function section apply -variable {ι α : Type*} {β : ι → Type*} [∀ i, Preorder (β i)] [Preorder α] {f : α → ∀ i, β i} +variable {β : ι → Type*} [∀ i, Preorder (β i)] [Preorder α] {f : α → ∀ i, β i} lemma monotone_iff_apply₂ : Monotone f ↔ ∀ i, Monotone (f · i) := by simp [Monotone, Pi.le_def, @forall_swap ι] diff --git a/Mathlib/Order/Monotone/Extension.lean b/Mathlib/Order/Monotone/Extension.lean index 7d56c6bba761f..6576bde8e49da 100644 --- a/Mathlib/Order/Monotone/Extension.lean +++ b/Mathlib/Order/Monotone/Extension.lean @@ -16,7 +16,6 @@ monotone extension to the whole space. open Set variable {α β : Type*} [LinearOrder α] [ConditionallyCompleteLinearOrder β] {f : α → β} {s : Set α} - {a b : α} /-- If a function is monotone and is bounded on a set `s`, then it admits a monotone extension to the whole space. -/ diff --git a/Mathlib/Order/Monotone/Monovary.lean b/Mathlib/Order/Monotone/Monovary.lean index 4c25c914b2698..9dcfecb90a91f 100644 --- a/Mathlib/Order/Monotone/Monovary.lean +++ b/Mathlib/Order/Monotone/Monovary.lean @@ -31,7 +31,7 @@ variable {ι ι' α β γ : Type*} section Preorder -variable [Preorder α] [Preorder β] [Preorder γ] {f : ι → α} {f' : α → γ} {g : ι → β} {g' : β → γ} +variable [Preorder α] [Preorder β] [Preorder γ] {f : ι → α} {f' : α → γ} {g : ι → β} {s t : Set ι} /-- `f` monovaries with `g` if `g i < g j` implies `f i ≤ f j`. -/ @@ -282,7 +282,7 @@ end Preorder section LinearOrder -variable [Preorder α] [LinearOrder β] [Preorder γ] {f : ι → α} {f' : α → γ} {g : ι → β} {g' : β → γ} +variable [Preorder α] [LinearOrder β] [Preorder γ] {f : ι → α} {g : ι → β} {g' : β → γ} {s : Set ι} theorem MonovaryOn.comp_monotoneOn_right (h : MonovaryOn f g s) (hg : MonotoneOn g' (g '' s)) : diff --git a/Mathlib/Order/OrdContinuous.lean b/Mathlib/Order/OrdContinuous.lean index 1af016fa24c89..ac0e1eab6eac1 100644 --- a/Mathlib/Order/OrdContinuous.lean +++ b/Mathlib/Order/OrdContinuous.lean @@ -231,7 +231,7 @@ namespace OrderIso section Preorder -variable [Preorder α] [Preorder β] (e : α ≃o β) {s : Set α} {x : α} +variable [Preorder α] [Preorder β] (e : α ≃o β) protected theorem leftOrdContinuous : LeftOrdContinuous e := fun _ _ hx => ⟨Monotone.mem_upperBounds_image (fun _ _ => e.map_rel_iff.2) hx.1, fun _ hy => diff --git a/Mathlib/Order/OrderIsoNat.lean b/Mathlib/Order/OrderIsoNat.lean index 5eddb07567f64..da0fabb452ad3 100644 --- a/Mathlib/Order/OrderIsoNat.lean +++ b/Mathlib/Order/OrderIsoNat.lean @@ -232,3 +232,20 @@ theorem WellFounded.iSup_eq_monotonicSequenceLimit [CompleteLattice α] · cases' WellFounded.monotone_chain_condition'.1 h a with n hn have : n ∈ {n | ∀ m, n ≤ m → a n = a m} := fun k hk => (a.mono hk).eq_of_not_lt (hn k hk) exact (Nat.sInf_mem ⟨n, this⟩ m hm.le).ge + +theorem exists_covBy_seq_of_wellFoundedLT_wellFoundedGT (α) [Preorder α] + [Nonempty α] [wfl : WellFoundedLT α] [wfg : WellFoundedGT α] : + ∃ a : ℕ → α, IsMin (a 0) ∧ ∃ n, IsMax (a n) ∧ ∀ i < n, a i ⋖ a (i + 1) := by + choose next hnext using exists_covBy_of_wellFoundedLT (α := α) + have hα := Set.nonempty_iff_univ_nonempty.mp ‹_› + classical + let a : ℕ → α := Nat.rec (wfl.wf.min _ hα) fun _n a ↦ if ha : IsMax a then a else next ha + refine ⟨a, isMin_iff_forall_not_lt.mpr fun _ ↦ wfl.wf.not_lt_min _ hα trivial, ?_⟩ + have cov n (hn : ¬ IsMax (a n)) : a n ⋖ a (n + 1) := by + change a n ⋖ if ha : IsMax (a n) then a n else _ + rw [dif_neg hn] + exact hnext hn + have H : ∃ n, IsMax (a n) := by + by_contra! + exact (RelEmbedding.natGT a fun n ↦ (cov n (this n)).1).not_wellFounded_of_decreasing_seq wfg.wf + exact ⟨_, wellFounded_lt.min_mem _ H, fun i h ↦ cov _ fun h' ↦ wellFounded_lt.not_lt_min _ H h' h⟩ diff --git a/Mathlib/Order/RelIso/Basic.lean b/Mathlib/Order/RelIso/Basic.lean index 982bf1b0e6176..ae6e5fc6d18b7 100644 --- a/Mathlib/Order/RelIso/Basic.lean +++ b/Mathlib/Order/RelIso/Basic.lean @@ -58,7 +58,7 @@ satisfy `r a b → s (f a) (f b)`. The relations `r` and `s` are `outParam`s since figuring them out from a goal is a higher-order matching problem that Lean usually can't do unaided. -/ -class RelHomClass (F : Type*) {α β : Type*} (r : outParam <| α → α → Prop) +class RelHomClass (F : Type*) {α β : outParam Type*} (r : outParam <| α → α → Prop) (s : outParam <| β → β → Prop) [FunLike F α β] : Prop where /-- A `RelHomClass` sends related elements to related elements -/ map_rel : ∀ (f : F) {a b}, r a b → s (f a) (f b) @@ -201,7 +201,7 @@ instance : Coe (r ↪r s) (r →r s) := -- TODO: define and instantiate a `RelEmbeddingClass` when `EmbeddingLike` is defined instance : FunLike (r ↪r s) α β where - coe := fun x => x.toFun + coe x := x.toFun coe_injective' f g h := by rcases f with ⟨⟨⟩⟩ rcases g with ⟨⟨⟩⟩ @@ -349,15 +349,15 @@ instance Subtype.wellFoundedGT [LT α] [WellFoundedGT α] (p : α → Prop) : WellFoundedGT (Subtype p) := (Subtype.relEmbedding (· > ·) p).isWellFounded -/-- `Quotient.mk'` as a relation homomorphism between the relation and the lift of a relation. -/ +/-- `Quotient.mk` as a relation homomorphism between the relation and the lift of a relation. -/ @[simps] -def Quotient.mkRelHom [Setoid α] {r : α → α → Prop} +def Quotient.mkRelHom {_ : Setoid α} {r : α → α → Prop} (H : ∀ (a₁ b₁ a₂ b₂ : α), a₁ ≈ a₂ → b₁ ≈ b₂ → r a₁ b₁ = r a₂ b₂) : r →r Quotient.lift₂ r H := - ⟨@Quotient.mk' α _, id⟩ + ⟨Quotient.mk _, id⟩ /-- `Quotient.out` as a relation embedding between the lift of a relation and the relation. -/ @[simps!] -noncomputable def Quotient.outRelEmbedding [Setoid α] {r : α → α → Prop} +noncomputable def Quotient.outRelEmbedding {_ : Setoid α} {r : α → α → Prop} (H : ∀ (a₁ b₁ a₂ b₂ : α), a₁ ≈ a₂ → b₁ ≈ b₂ → r a₁ b₁ = r a₂ b₂) : Quotient.lift₂ r H ↪r r := ⟨Embedding.quotientOut α, by refine @fun x y => Quotient.inductionOn₂ x y fun a b => ?_ @@ -371,7 +371,7 @@ noncomputable def Quotient.out'RelEmbedding {_ : Setoid α} {r : α → α → P { Quotient.outRelEmbedding H with toFun := Quotient.out' } @[simp] -theorem acc_lift₂_iff [Setoid α] {r : α → α → Prop} +theorem acc_lift₂_iff {_ : Setoid α} {r : α → α → Prop} {H : ∀ (a₁ b₁ a₂ b₂ : α), a₁ ≈ a₂ → b₁ ≈ b₂ → r a₁ b₁ = r a₂ b₂} {a} : Acc (Quotient.lift₂ r H) ⟦a⟧ ↔ Acc r a := by constructor @@ -389,7 +389,7 @@ theorem acc_liftOn₂'_iff {s : Setoid α} {r : α → α → Prop} {H} {a} : /-- A relation is well founded iff its lift to a quotient is. -/ @[simp] -theorem wellFounded_lift₂_iff [Setoid α] {r : α → α → Prop} +theorem wellFounded_lift₂_iff {_ : Setoid α} {r : α → α → Prop} {H : ∀ (a₁ b₁ a₂ b₂ : α), a₁ ≈ a₂ → b₁ ≈ b₂ → r a₁ b₁ = r a₂ b₂} : WellFounded (Quotient.lift₂ r H) ↔ WellFounded r := by constructor @@ -536,7 +536,7 @@ instance : CoeOut (r ≃r s) (r ↪r s) := -- TODO: define and instantiate a `RelIsoClass` when `EquivLike` is defined instance : FunLike (r ≃r s) α β where - coe := fun x => x + coe x := x coe_injective' := Equiv.coe_fn_injective.comp toEquiv_injective -- TODO: define and instantiate a `RelIsoClass` when `EquivLike` is defined diff --git a/Mathlib/Order/RelIso/Set.lean b/Mathlib/Order/RelIso/Set.lean index fbf5dd9ac208e..961b9773f5912 100644 --- a/Mathlib/Order/RelIso/Set.lean +++ b/Mathlib/Order/RelIso/Set.lean @@ -19,8 +19,7 @@ open Function universe u v w -variable {α β γ δ : Type*} {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} - {u : δ → δ → Prop} +variable {α β : Type*} {r : α → α → Prop} {s : β → β → Prop} namespace RelHomClass @@ -92,8 +91,6 @@ theorem RelEmbedding.codRestrict_apply (p) (f : r ↪r s) (H a) : section image -variable {α β : Type*} {r : α → α → Prop} {s : β → β → Prop} - theorem RelIso.image_eq_preimage_symm (e : r ≃r s) (t : Set α) : e '' t = e.symm ⁻¹' t := e.toEquiv.image_eq_preimage t diff --git a/Mathlib/Order/SuccPred/Archimedean.lean b/Mathlib/Order/SuccPred/Archimedean.lean index 6a225c713afdc..0db5ba2b12320 100644 --- a/Mathlib/Order/SuccPred/Archimedean.lean +++ b/Mathlib/Order/SuccPred/Archimedean.lean @@ -234,6 +234,39 @@ lemma SuccOrder.forall_ne_bot_iff simp only [Function.iterate_succ', Function.comp_apply] apply h +section IsLeast + +-- TODO: generalize to PartialOrder and `DirectedOn` after #16272 +lemma BddAbove.exists_isGreatest_of_nonempty {X : Type*} [LinearOrder X] [SuccOrder X] + [IsSuccArchimedean X] {S : Set X} (hS : BddAbove S) (hS' : S.Nonempty) : + ∃ x, IsGreatest S x := by + obtain ⟨m, hm⟩ := hS + obtain ⟨n, hn⟩ := hS' + by_cases hm' : m ∈ S + · exact ⟨_, hm', hm⟩ + have hn' := hm hn + revert hn hm hm' + refine Succ.rec ?_ ?_ hn' + · simp (config := {contextual := true}) + intro m _ IH hm hn hm' + rw [mem_upperBounds] at IH hm + simp_rw [Order.le_succ_iff_eq_or_le] at hm + replace hm : ∀ x ∈ S, x ≤ m := by + intro x hx + refine (hm x hx).resolve_left ?_ + rintro rfl + exact hm' hx + by_cases hmS : m ∈ S + · exact ⟨m, hmS, hm⟩ + · exact IH hm hn hmS + +lemma BddBelow.exists_isLeast_of_nonempty {X : Type*} [LinearOrder X] [PredOrder X] + [IsPredArchimedean X] {S : Set X} (hS : BddBelow S) (hS' : S.Nonempty) : + ∃ x, IsLeast S x := + hS.dual.exists_isGreatest_of_nonempty hS' + +end IsLeast + section OrderIso variable {X Y : Type*} [PartialOrder X] [PartialOrder Y] diff --git a/Mathlib/Order/SuccPred/Basic.lean b/Mathlib/Order/SuccPred/Basic.lean index d8d173cca893a..43142cc9da386 100644 --- a/Mathlib/Order/SuccPred/Basic.lean +++ b/Mathlib/Order/SuccPred/Basic.lean @@ -24,7 +24,7 @@ order... Maximal elements don't have a sensible successor. Thus the naïve typeclass ```lean -class NaiveSuccOrder (α : Type*) [Preorder α] := +class NaiveSuccOrder (α : Type*) [Preorder α] where (succ : α → α) (succ_le_iff : ∀ {a b}, succ a ≤ b ↔ a < b) (lt_succ_iff : ∀ {a b}, a < succ b ↔ a ≤ b) @@ -927,7 +927,7 @@ lemma gc_pred_succ : GaloisConnection (pred : α → α) succ := fun _ _ ↦ pre end Preorder -variable [PartialOrder α] [SuccOrder α] [PredOrder α] {a b : α} +variable [PartialOrder α] [SuccOrder α] [PredOrder α] {a : α} @[simp] theorem succ_pred_of_not_isMin (h : ¬IsMin a) : succ (pred a) = a := diff --git a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean index b2e2b120664d7..e758ae8c0f2f4 100644 --- a/Mathlib/Order/SuccPred/LinearLocallyFinite.lean +++ b/Mathlib/Order/SuccPred/LinearLocallyFinite.lean @@ -194,12 +194,13 @@ variable [SuccOrder ι] [IsSuccArchimedean ι] [PredOrder ι] {i0 i : ι} the range of `toZ`. -/ def toZ (i0 i : ι) : ℤ := dite (i0 ≤ i) (fun hi ↦ Nat.find (exists_succ_iterate_of_le hi)) fun hi ↦ - -Nat.find (exists_pred_iterate_of_le (not_le.mp hi).le) + -Nat.find (exists_pred_iterate_of_le (α := ι) (not_le.mp hi).le) theorem toZ_of_ge (hi : i0 ≤ i) : toZ i0 i = Nat.find (exists_succ_iterate_of_le hi) := dif_pos hi -theorem toZ_of_lt (hi : i < i0) : toZ i0 i = -Nat.find (exists_pred_iterate_of_le hi.le) := +theorem toZ_of_lt (hi : i < i0) : + toZ i0 i = -Nat.find (exists_pred_iterate_of_le (α := ι) hi.le) := dif_neg (not_le.mpr hi) @[simp] @@ -310,8 +311,8 @@ theorem toZ_mono {i j : ι} (h_le : i ≤ j) : toZ i0 i ≤ toZ i0 j := by · exact le_of_not_le h · exact absurd h_le (not_le.mpr (hj.trans_le hi)) · exact (toZ_neg hi).le.trans (toZ_nonneg hj) - · let m := Nat.find (exists_pred_iterate_of_le h_le) - have hm : pred^[m] j = i := Nat.find_spec (exists_pred_iterate_of_le h_le) + · let m := Nat.find (exists_pred_iterate_of_le (α := ι) h_le) + have hm : pred^[m] j = i := Nat.find_spec (exists_pred_iterate_of_le (α := ι) h_le) have hj_eq : i = pred^[(-toZ i0 j).toNat + m] i0 := by rw [← hm, add_comm] nth_rw 1 [← iterate_pred_toZ j hj] diff --git a/Mathlib/Order/SymmDiff.lean b/Mathlib/Order/SymmDiff.lean index 8805a9c3184ad..fa8d23d3aa081 100644 --- a/Mathlib/Order/SymmDiff.lean +++ b/Mathlib/Order/SymmDiff.lean @@ -82,7 +82,7 @@ theorem symmDiff_eq_Xor' (p q : Prop) : p ∆ q = Xor' p q := @[simp] theorem bihimp_iff_iff {p q : Prop} : p ⇔ q ↔ (p ↔ q) := - (iff_iff_implies_and_implies _ _).symm.trans Iff.comm + iff_iff_implies_and_implies.symm.trans Iff.comm @[simp] theorem Bool.symmDiff_eq_xor : ∀ p q : Bool, p ∆ q = xor p q := by decide diff --git a/Mathlib/Order/Synonym.lean b/Mathlib/Order/Synonym.lean index 1ff3b4dca5241..35decae0e1c87 100644 --- a/Mathlib/Order/Synonym.lean +++ b/Mathlib/Order/Synonym.lean @@ -34,7 +34,7 @@ This file is similar to `Algebra.Group.TypeTags`. -/ -variable {α β γ : Type*} +variable {α : Type*} /-! ### Order dual -/ @@ -170,6 +170,18 @@ theorem toLex_inj {a b : α} : toLex a = toLex b ↔ a = b := theorem ofLex_inj {a b : Lex α} : ofLex a = ofLex b ↔ a = b := Iff.rfl +instance (α : Type*) [BEq α] : BEq (Lex α) where + beq a b := ofLex a == ofLex b + +instance (α : Type*) [BEq α] [LawfulBEq α] : LawfulBEq (Lex α) := + inferInstanceAs (LawfulBEq α) + +instance (α : Type*) [DecidableEq α] : DecidableEq (Lex α) := + inferInstanceAs (DecidableEq α) + +instance (α : Type*) [Inhabited α] : Inhabited (Lex α) := + inferInstanceAs (Inhabited α) + /-- A recursor for `Lex`. Use as `induction x`. -/ @[elab_as_elim, induction_eliminator, cases_eliminator] protected def Lex.rec {β : Lex α → Sort*} (h : ∀ a, β (toLex a)) : ∀ a, β a := fun a => h (ofLex a) diff --git a/Mathlib/Order/ULift.lean b/Mathlib/Order/ULift.lean index b3fa9d2fcbc4c..05f7ece9dd38b 100644 --- a/Mathlib/Order/ULift.lean +++ b/Mathlib/Order/ULift.lean @@ -14,6 +14,8 @@ the corresponding `Prod` instances. namespace ULift +open Batteries + universe v u variable {α : Type u} @@ -28,6 +30,11 @@ instance [LT α] : LT (ULift.{v} α) where lt x y := x.down < y.down @[simp] theorem up_lt [LT α] {a b : α} : up a < up b ↔ a < b := Iff.rfl @[simp] theorem down_lt [LT α] {a b : ULift α} : down a < down b ↔ a < b := Iff.rfl +instance [BEq α] : BEq (ULift.{v} α) where beq x y := x.down == y.down + +@[simp] theorem up_beq [BEq α] (a b : α) : (up a == up b) = (a == b) := rfl +@[simp] theorem down_beq [BEq α] (a b : ULift α) : (down a == down b) = (a == b) := rfl + instance [Ord α] : Ord (ULift.{v} α) where compare x y := compare x.down y.down @[simp] theorem up_compare [Ord α] (a b : α) : compare (up a) (up b) = compare a b := rfl @@ -54,6 +61,25 @@ instance [HasCompl α] : HasCompl (ULift.{v} α) where compl x := up <| x.down @[simp] theorem up_compl [HasCompl α] (a : α) : up (aᶜ) = (up a)ᶜ := rfl @[simp] theorem down_compl [HasCompl α] (a : ULift α) : down aᶜ = (down a)ᶜ := rfl +instance [Ord α] [inst : OrientedOrd α] : OrientedOrd (ULift.{v} α) where + symm _ _ := inst.symm .. + +instance [Ord α] [inst : TransOrd α] : TransOrd (ULift.{v} α) where + le_trans := inst.le_trans + +instance [BEq α] [Ord α] [inst : BEqOrd α] : BEqOrd (ULift.{v} α) where + cmp_iff_beq := inst.cmp_iff_beq + +instance [LT α] [Ord α] [inst : LTOrd α] : LTOrd (ULift.{v} α) where + cmp_iff_lt := inst.cmp_iff_lt + +instance [LE α] [Ord α] [inst : LEOrd α] : LEOrd (ULift.{v} α) where + cmp_iff_le := inst.cmp_iff_le + +instance [LE α] [LT α] [BEq α] [Ord α] [inst : LawfulOrd α] : LawfulOrd (ULift.{v} α) where + cmp_iff_lt := inst.cmp_iff_lt + cmp_iff_le := inst.cmp_iff_le + instance [Preorder α] : Preorder (ULift.{v} α) := Preorder.lift ULift.down diff --git a/Mathlib/Order/WellFounded.lean b/Mathlib/Order/WellFounded.lean index 613d28890f078..1c5e905b8da09 100644 --- a/Mathlib/Order/WellFounded.lean +++ b/Mathlib/Order/WellFounded.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jeremy Avigad, Mario Carneiro -/ import Mathlib.Data.Set.Function -import Mathlib.Order.Bounds.Basic +import Mathlib.Order.Bounds.Defs /-! # Well-founded relations diff --git a/Mathlib/Order/WithBot.lean b/Mathlib/Order/WithBot.lean index e9c5896a6d456..c0f4154f4b647 100644 --- a/Mathlib/Order/WithBot.lean +++ b/Mathlib/Order/WithBot.lean @@ -933,7 +933,7 @@ lemma ge_of_forall_gt_iff_ge [LinearOrder α] [DenselyOrdered α] [NoMinOrder α section LE -variable [LE α] {a b : α} +variable [LE α] theorem toDual_le_iff {a : WithBot α} {b : WithTop αᵒᵈ} : WithBot.toDual a ≤ b ↔ WithTop.ofDual b ≤ a := @@ -963,7 +963,7 @@ end LE section LT -variable [LT α] {a b : α} +variable [LT α] theorem toDual_lt_iff {a : WithBot α} {b : WithTop αᵒᵈ} : WithBot.toDual a < b ↔ WithTop.ofDual b < a := @@ -1088,7 +1088,7 @@ alias ⟨_, _root_.StrictMono.withTop_map⟩ := strictMono_map_iff 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] + rw [← toDual_le_toDual_iff, toDual_map, toDual_map, WithBot.map_le_iff, toDual_le_toDual_iff] simp [mono_iff] theorem coe_untop'_le (a : WithTop α) (b : α) : a.untop' b ≤ a := diff --git a/Mathlib/Probability/CondCount.lean b/Mathlib/Probability/CondCount.lean deleted file mode 100644 index 1ea9812d6c2f6..0000000000000 --- a/Mathlib/Probability/CondCount.lean +++ /dev/null @@ -1,186 +0,0 @@ -/- -Copyright (c) 2022 Kexing Ying. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kexing Ying, Bhavik Mehta --/ -import Mathlib.Probability.ConditionalProbability -import Mathlib.MeasureTheory.Measure.Count - -/-! -# Classical probability - -The classical formulation of probability states that the probability of an event occurring in a -finite probability space is the ratio of that event to all possible events. -This notion can be expressed with measure theory using -the counting measure. In particular, given the sets `s` and `t`, we define the probability of `t` -occurring in `s` to be `|s|⁻¹ * |s ∩ t|`. With this definition, we recover the probability over -the entire sample space when `s = Set.univ`. - -Classical probability is often used in combinatorics and we prove some useful lemmas in this file -for that purpose. - -## Main definition - -* `ProbabilityTheory.condCount`: given a set `s`, `condCount s` is the counting measure - conditioned on `s`. This is a probability measure when `s` is finite and nonempty. - -## Notes - -The original aim of this file is to provide a measure theoretic method of describing the -probability an element of a set `s` satisfies some predicate `P`. Our current formulation still -allow us to describe this by abusing the definitional equality of sets and predicates by simply -writing `condCount s P`. We should avoid this however as none of the lemmas are written for -predicates. --/ - - -noncomputable section - -open ProbabilityTheory - -open MeasureTheory MeasurableSpace - -namespace ProbabilityTheory - -variable {Ω : Type*} [MeasurableSpace Ω] - -/-- Given a set `s`, `condCount s` is the counting measure conditioned on `s`. In particular, -`condCount s t` is the proportion of `s` that is contained in `t`. - -This is a probability measure when `s` is finite and nonempty and is given by -`ProbabilityTheory.condCount_isProbabilityMeasure`. -/ -def condCount (s : Set Ω) : Measure Ω := - Measure.count[|s] - -instance {s : Set Ω} : IsZeroOrProbabilityMeasure (condCount s) := by - unfold condCount; infer_instance - -@[simp] -theorem condCount_empty_meas : (condCount ∅ : Measure Ω) = 0 := by simp [condCount] - -theorem condCount_empty {s : Set Ω} : condCount s ∅ = 0 := by simp - -theorem finite_of_condCount_ne_zero {s t : Set Ω} (h : condCount s t ≠ 0) : s.Finite := by - by_contra hs' - simp [condCount, cond, Measure.count_apply_infinite hs'] at h - -theorem condCount_univ [Fintype Ω] {s : Set Ω} : - condCount Set.univ s = Measure.count s / Fintype.card Ω := by - rw [condCount, cond_apply _ MeasurableSet.univ, ← ENNReal.div_eq_inv_mul, Set.univ_inter] - congr - rw [← Finset.coe_univ, Measure.count_apply, Finset.univ.tsum_subtype' fun _ => (1 : ENNReal)] - · simp [Finset.card_univ] - · exact (@Finset.coe_univ Ω _).symm ▸ MeasurableSet.univ - -variable [MeasurableSingletonClass Ω] - -theorem condCount_isProbabilityMeasure {s : Set Ω} (hs : s.Finite) (hs' : s.Nonempty) : - IsProbabilityMeasure (condCount s) := by - apply cond_isProbabilityMeasure_of_finite - · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h - · exact (Measure.count_apply_lt_top.2 hs).ne - -theorem condCount_singleton (ω : Ω) (t : Set Ω) [Decidable (ω ∈ t)] : - condCount {ω} t = if ω ∈ t then 1 else 0 := by - rw [condCount, cond_apply _ (measurableSet_singleton ω), Measure.count_singleton, inv_one, - one_mul] - split_ifs - · rw [(by simpa : ({ω} : Set Ω) ∩ t = {ω}), Measure.count_singleton] - · rw [(by simpa : ({ω} : Set Ω) ∩ t = ∅), Measure.count_empty] - -variable {s t u : Set Ω} - -theorem condCount_inter_self (hs : s.Finite) : condCount s (s ∩ t) = condCount s t := by - rw [condCount, cond_inter_self _ hs.measurableSet] - -theorem condCount_self (hs : s.Finite) (hs' : s.Nonempty) : condCount s s = 1 := by - rw [condCount, cond_apply _ hs.measurableSet, Set.inter_self, ENNReal.inv_mul_cancel] - · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h - · exact (Measure.count_apply_lt_top.2 hs).ne - -theorem condCount_eq_one_of (hs : s.Finite) (hs' : s.Nonempty) (ht : s ⊆ t) : - condCount s t = 1 := by - haveI := condCount_isProbabilityMeasure hs hs' - refine eq_of_le_of_not_lt prob_le_one ?_ - rw [not_lt, ← condCount_self hs hs'] - exact measure_mono ht - -theorem pred_true_of_condCount_eq_one (h : condCount s t = 1) : s ⊆ t := by - have hsf := finite_of_condCount_ne_zero (by rw [h]; exact one_ne_zero) - rw [condCount, cond_apply _ hsf.measurableSet, mul_comm] at h - replace h := ENNReal.eq_inv_of_mul_eq_one_left h - rw [inv_inv, Measure.count_apply_finite _ hsf, Measure.count_apply_finite _ (hsf.inter_of_left _), - Nat.cast_inj] at h - suffices s ∩ t = s by exact this ▸ fun x hx => hx.2 - rw [← @Set.Finite.toFinset_inj _ _ _ (hsf.inter_of_left _) hsf] - exact Finset.eq_of_subset_of_card_le (Set.Finite.toFinset_mono s.inter_subset_left) h.ge - -theorem condCount_eq_zero_iff (hs : s.Finite) : condCount s t = 0 ↔ s ∩ t = ∅ := by - simp [condCount, cond_apply _ hs.measurableSet, Measure.count_apply_eq_top, Set.not_infinite.2 hs, - Measure.count_apply_finite _ (hs.inter_of_left _)] - -theorem condCount_of_univ (hs : s.Finite) (hs' : s.Nonempty) : condCount s Set.univ = 1 := - condCount_eq_one_of hs hs' s.subset_univ - -theorem condCount_inter (hs : s.Finite) : - condCount s (t ∩ u) = condCount (s ∩ t) u * condCount s t := by - by_cases hst : s ∩ t = ∅ - · rw [hst, condCount_empty_meas, Measure.coe_zero, Pi.zero_apply, zero_mul, - condCount_eq_zero_iff hs, ← Set.inter_assoc, hst, Set.empty_inter] - rw [condCount, condCount, cond_apply _ hs.measurableSet, cond_apply _ hs.measurableSet, - cond_apply _ (hs.inter_of_left _).measurableSet, mul_comm _ (Measure.count (s ∩ t)), - ← mul_assoc, mul_comm _ (Measure.count (s ∩ t)), ← mul_assoc, ENNReal.mul_inv_cancel, one_mul, - mul_comm, Set.inter_assoc] - · rwa [← Measure.count_eq_zero_iff] at hst - · exact (Measure.count_apply_lt_top.2 <| hs.inter_of_left _).ne - -theorem condCount_inter' (hs : s.Finite) : - condCount s (t ∩ u) = condCount (s ∩ u) t * condCount s u := by - rw [← Set.inter_comm] - exact condCount_inter hs - -theorem condCount_union (hs : s.Finite) (htu : Disjoint t u) : - condCount s (t ∪ u) = condCount s t + condCount s u := by - rw [condCount, cond_apply _ hs.measurableSet, cond_apply _ hs.measurableSet, - cond_apply _ hs.measurableSet, Set.inter_union_distrib_left, measure_union, mul_add] - exacts [htu.mono inf_le_right inf_le_right, (hs.inter_of_left _).measurableSet] - -theorem condCount_compl (t : Set Ω) (hs : s.Finite) (hs' : s.Nonempty) : - condCount s t + condCount s tᶜ = 1 := by - rw [← condCount_union hs disjoint_compl_right, Set.union_compl_self, - (condCount_isProbabilityMeasure hs hs').measure_univ] - -theorem condCount_disjoint_union (hs : s.Finite) (ht : t.Finite) (hst : Disjoint s t) : - condCount s u * condCount (s ∪ t) s + condCount t u * condCount (s ∪ t) t = - condCount (s ∪ t) u := by - rcases s.eq_empty_or_nonempty with (rfl | hs') <;> rcases t.eq_empty_or_nonempty with (rfl | ht') - · simp - · simp [condCount_self ht ht'] - · simp [condCount_self hs hs'] - rw [condCount, condCount, condCount, cond_apply _ hs.measurableSet, - cond_apply _ ht.measurableSet, cond_apply _ (hs.union ht).measurableSet, - cond_apply _ (hs.union ht).measurableSet, cond_apply _ (hs.union ht).measurableSet] - conv_lhs => - rw [Set.union_inter_cancel_left, Set.union_inter_cancel_right, - mul_comm (Measure.count (s ∪ t))⁻¹, mul_comm (Measure.count (s ∪ t))⁻¹, ← mul_assoc, - ← mul_assoc, mul_comm _ (Measure.count s), mul_comm _ (Measure.count t), ← mul_assoc, - ← mul_assoc] - rw [ENNReal.mul_inv_cancel, ENNReal.mul_inv_cancel, one_mul, one_mul, ← add_mul, ← measure_union, - Set.union_inter_distrib_right, mul_comm] - exacts [hst.mono inf_le_left inf_le_left, (ht.inter_of_left _).measurableSet, - Measure.count_ne_zero ht', (Measure.count_apply_lt_top.2 ht).ne, Measure.count_ne_zero hs', - (Measure.count_apply_lt_top.2 hs).ne] - -/-- A version of the law of total probability for counting probabilities. -/ -theorem condCount_add_compl_eq (u t : Set Ω) (hs : s.Finite) : - condCount (s ∩ u) t * condCount s u + condCount (s ∩ uᶜ) t * condCount s uᶜ = - condCount s t := by - -- Porting note: The original proof used `conv_rhs`. However, that tactic timed out. - have : condCount s t = (condCount (s ∩ u) t * condCount (s ∩ u ∪ s ∩ uᶜ) (s ∩ u) + - condCount (s ∩ uᶜ) t * condCount (s ∩ u ∪ s ∩ uᶜ) (s ∩ uᶜ)) := by - rw [condCount_disjoint_union (hs.inter_of_left _) (hs.inter_of_left _) - (disjoint_compl_right.mono inf_le_right inf_le_right), Set.inter_union_compl] - rw [this] - simp [condCount_inter_self hs] - -end ProbabilityTheory diff --git a/Mathlib/Probability/ConditionalExpectation.lean b/Mathlib/Probability/ConditionalExpectation.lean index 66719c1935974..18a5ab72ec167 100644 --- a/Mathlib/Probability/ConditionalExpectation.lean +++ b/Mathlib/Probability/ConditionalExpectation.lean @@ -58,11 +58,11 @@ theorem condexp_indep_eq (hle₁ : m₁ ≤ m) (hle₂ : m₂ ≤ m) [SigmaFinit · have heq₁ : (fun f : lpMeas E ℝ m₁ 1 μ => ∫ x, (f : Ω → E) x ∂μ) = (fun f : Lp E 1 μ => ∫ x, f x ∂μ) ∘ Submodule.subtypeL _ := by refine funext fun f => integral_congr_ae ?_ - simp_rw [Submodule.coe_subtypeL', Submodule.coeSubtype]; norm_cast + simp_rw [Submodule.coe_subtypeL', Submodule.coe_subtype]; norm_cast have heq₂ : (fun f : lpMeas E ℝ m₁ 1 μ => ∫ x in s, (f : Ω → E) x ∂μ) = (fun f : Lp E 1 μ => ∫ x in s, f x ∂μ) ∘ Submodule.subtypeL _ := by refine funext fun f => integral_congr_ae (ae_restrict_of_ae ?_) - simp_rw [Submodule.coe_subtypeL', Submodule.coeSubtype] + simp_rw [Submodule.coe_subtypeL', Submodule.coe_subtype] exact Eventually.of_forall fun _ => (by trivial) refine isClosed_eq (Continuous.const_smul ?_ _) ?_ · rw [heq₁] diff --git a/Mathlib/Probability/Distributions/Gamma.lean b/Mathlib/Probability/Distributions/Gamma.lean index 0548d04bfd3c0..562c9b3c3b6f9 100644 --- a/Mathlib/Probability/Distributions/Gamma.lean +++ b/Mathlib/Probability/Distributions/Gamma.lean @@ -30,8 +30,8 @@ open MeasureTheory Real Set Filter Topology lemma lintegral_Iic_eq_lintegral_Iio_add_Icc {y z : ℝ} (f : ℝ → ℝ≥0∞) (hzy : z ≤ y) : ∫⁻ x in Iic y, f x = (∫⁻ x in Iio z, f x) + ∫⁻ x in Icc z y, f x := by rw [← Iio_union_Icc_eq_Iic hzy, lintegral_union measurableSet_Icc] - rw [Set.disjoint_iff] - rintro x ⟨h1 : x < _, h2, _⟩ + simp_rw [Set.disjoint_iff_forall_ne, mem_Iio, mem_Icc] + intros linarith namespace ProbabilityTheory @@ -49,8 +49,9 @@ 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 - r ^ a / (Gamma a) * x ^ (a-1) * exp (-(r * x)) else 0) := rfl + 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] diff --git a/Mathlib/Probability/Distributions/Pareto.lean b/Mathlib/Probability/Distributions/Pareto.lean new file mode 100644 index 0000000000000..abc5e6e63621a --- /dev/null +++ b/Mathlib/Probability/Distributions/Pareto.lean @@ -0,0 +1,147 @@ +/- +Copyright (c) 2024 Alvan Caleb Arulandu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Alvan Caleb Arulandu +-/ +import Mathlib.Probability.Notation +import Mathlib.Probability.CDF +import Mathlib.Analysis.SpecialFunctions.ImproperIntegrals + +/-! # Pareto distributions over ℝ + +Define the Pareto measure over the reals. + +## Main definitions +* `paretoPDFReal`: the function `t r x ↦ r * t ^ r * x ^ -(r + 1)` + for `t ≤ x` or `0` else, which is the probability density function of a Pareto distribution with + scale `t` and shape `r` (when `ht : 0 < t` and `hr : 0 < r`). +* `paretoPDF`: `ℝ≥0∞`-valued pdf, + `paretoPDF t r = ENNReal.ofReal (paretoPDFReal t r)`. +* `paretoMeasure`: a Pareto measure on `ℝ`, parametrized by its scale `t` and shape `r`. +* `paretoCDFReal`: the CDF given by the definition of CDF in `ProbabilityTheory.CDF` applied to the + Pareto measure. +-/ + +open scoped ENNReal NNReal + +open MeasureTheory Real Set Filter Topology + +namespace ProbabilityTheory +variable {t r x : ℝ} + +section ParetoPDF + +/-- The pdf of the Pareto distribution depending on its scale `t` and rate `r`. -/ +noncomputable def paretoPDFReal (t r x : ℝ) : ℝ := + if t ≤ x then r * t ^ r * x ^ (-(r + 1)) else 0 + +/-- The pdf of the Pareto distribution, as a function valued in `ℝ≥0∞`. -/ +noncomputable def paretoPDF (t r x : ℝ) : ℝ≥0∞ := + ENNReal.ofReal (paretoPDFReal t r x) + +lemma paretoPDF_eq (t r x : ℝ) : + paretoPDF t r x = ENNReal.ofReal (if t ≤ x then r * t ^ r * x ^ (-(r + 1)) else 0) := rfl + +lemma paretoPDF_of_lt (hx : x < t) : paretoPDF t r x = 0 := by + simp only [paretoPDF_eq, if_neg (not_le.mpr hx), ENNReal.ofReal_zero] + +lemma paretoPDF_of_le (hx : t ≤ x) : + paretoPDF t r x = ENNReal.ofReal (r * t ^ r * x ^ (-(r + 1))) := by + simp only [paretoPDF_eq, if_pos hx] + +/-- The Lebesgue integral of the Pareto pdf over reals `≤ t` equals `0`. -/ +lemma lintegral_paretoPDF_of_le (hx : x ≤ t) : + ∫⁻ y in Iio x, paretoPDF t r y = 0 := by + rw [setLIntegral_congr_fun (g := fun _ ↦ 0) measurableSet_Iio] + · rw [lintegral_zero, ← ENNReal.ofReal_zero] + · simp only [paretoPDF_eq, ge_iff_le, ENNReal.ofReal_eq_zero] + filter_upwards with a (_ : a < _) + rw [if_neg (by linarith)] + +/-- The Pareto pdf is measurable. -/ +@[measurability, fun_prop] +lemma measurable_paretoPDFReal (t r : ℝ) : Measurable (paretoPDFReal t r) := + Measurable.ite measurableSet_Ici ((measurable_id.pow_const _).const_mul _) measurable_const + +/-- The Pareto pdf is strongly measurable. -/ +@[measurability] +lemma stronglyMeasurable_paretoPDFReal (t r : ℝ) : + StronglyMeasurable (paretoPDFReal t r) := + (measurable_paretoPDFReal t r).stronglyMeasurable + +/-- The Pareto pdf is positive for all reals `>= t`. -/ +lemma paretoPDFReal_pos (ht : 0 < t) (hr : 0 < r) (hx : t ≤ x) : + 0 < paretoPDFReal t r x := by + rw [paretoPDFReal, if_pos hx] + have _ : 0 < x := by linarith + positivity + +/-- The Pareto pdf is nonnegative. -/ +lemma paretoPDFReal_nonneg (ht : 0 ≤ t) (hr : 0 ≤ r) (x : ℝ) : + 0 ≤ paretoPDFReal t r x := by + unfold paretoPDFReal + split_ifs with h + · cases le_iff_eq_or_lt.1 ht with + | inl ht0 => + rw [← ht0] at h + positivity + | inr htp => + have := lt_of_lt_of_le htp h + positivity + · positivity + +open Measure + +/-- The pdf of the Pareto distribution integrates to `1`. -/ +@[simp] +lemma lintegral_paretoPDF_eq_one (ht : 0 < t) (hr : 0 < r) : + ∫⁻ x, paretoPDF t r x = 1 := by + have leftSide : ∫⁻ x in Iio t, paretoPDF t r x = 0 := lintegral_paretoPDF_of_le (le_refl t) + have rightSide : ∫⁻ x in Ici t, paretoPDF t r x = + ∫⁻ x in Ici t, ENNReal.ofReal (r * t ^ r * x ^ (-(r + 1))) := + setLIntegral_congr_fun measurableSet_Ici (ae_of_all _ (fun _ ↦ paretoPDF_of_le)) + rw [← ENNReal.toReal_eq_one_iff, ← lintegral_add_compl _ measurableSet_Ici, compl_Ici, + leftSide, rightSide, add_zero, ← integral_eq_lintegral_of_nonneg_ae] + · rw [integral_Ici_eq_integral_Ioi, integral_mul_left, integral_Ioi_rpow_of_lt _ ht] + · field_simp [hr] + rw [mul_assoc, ← rpow_add ht] + simp + linarith + · rw [EventuallyLE, ae_restrict_iff' measurableSet_Ici] + refine ae_of_all _ fun x (hx : t ≤ x) ↦ ?_ + have := lt_of_lt_of_le ht hx + positivity + · apply (measurable_paretoPDFReal t r).aestronglyMeasurable.congr + refine (ae_restrict_iff' measurableSet_Ici).mpr <| ae_of_all _ fun x (hx : t ≤ x) ↦ ?_ + simp_rw [paretoPDFReal, eq_true_intro hx, ite_true] + +end ParetoPDF + +open MeasureTheory + +/-- Measure defined by the Pareto distribution. -/ +noncomputable def paretoMeasure (t r : ℝ) : Measure ℝ := + volume.withDensity (paretoPDF t r) + +lemma isProbabilityMeasure_paretoMeasure (ht : 0 < t) (hr : 0 < r) : + IsProbabilityMeasure (paretoMeasure t r) where + measure_univ := by simp [paretoMeasure, lintegral_paretoPDF_eq_one ht hr] + +section ParetoCDF + +/-- CDF of the Pareto distribution equals the integral of the PDF. -/ +lemma paretoCDFReal_eq_integral (ht : 0 < t) (hr : 0 < r) (x : ℝ) : + cdf (paretoMeasure t r) x = ∫ x in Iic x, paretoPDFReal t r x := by + have : IsProbabilityMeasure (paretoMeasure t r) := isProbabilityMeasure_paretoMeasure ht hr + rw [cdf_eq_toReal, paretoMeasure, withDensity_apply _ measurableSet_Iic] + refine (integral_eq_lintegral_of_nonneg_ae ?_ ?_).symm + · exact ae_of_all _ fun _ ↦ by simp only [Pi.zero_apply, paretoPDFReal_nonneg ht.le hr.le] + · exact (measurable_paretoPDFReal t r).aestronglyMeasurable.restrict + +lemma paretoCDFReal_eq_lintegral (ht : 0 < t) (hr : 0 < r) (x : ℝ) : + cdf (paretoMeasure t r) x = ENNReal.toReal (∫⁻ x in Iic x, paretoPDF t r x) := by + have : IsProbabilityMeasure (paretoMeasure t r) := isProbabilityMeasure_paretoMeasure ht hr + rw [cdf_eq_toReal, paretoMeasure, withDensity_apply _ measurableSet_Iic] + +end ParetoCDF +end ProbabilityTheory diff --git a/Mathlib/Probability/Independence/Conditional.lean b/Mathlib/Probability/Independence/Conditional.lean index 0b5e3f0b6dcaf..6456d37f340cf 100644 --- a/Mathlib/Probability/Independence/Conditional.lean +++ b/Mathlib/Probability/Independence/Conditional.lean @@ -734,7 +734,7 @@ lemma iCondIndepFun.condIndepFun_prod_mk_prod_mk (h_indep : iCondIndepFun m' hm' end iCondIndepFun section Mul -variable {β : Type*} {m : MeasurableSpace β} [Mul β] [MeasurableMul₂ β] {f : ι → Ω → β} +variable {m : MeasurableSpace β} [Mul β] [MeasurableMul₂ β] {f : ι → Ω → β} @[to_additive] lemma iCondIndepFun.indepFun_mul_left (hf_indep : iCondIndepFun m' hm' (fun _ ↦ m) f μ) @@ -758,7 +758,7 @@ lemma iCondIndepFun.indepFun_mul_mul (hf_indep : iCondIndepFun m' hm' (fun _ ↦ end Mul section Div -variable {β : Type*} {m : MeasurableSpace β} [Div β] [MeasurableDiv₂ β] {f : ι → Ω → β} +variable {m : MeasurableSpace β} [Div β] [MeasurableDiv₂ β] {f : ι → Ω → β} @[to_additive] lemma iCondIndepFun.indepFun_div_left (hf_indep : iCondIndepFun m' hm' (fun _ ↦ m) f μ) @@ -782,7 +782,7 @@ lemma iCondIndepFun.indepFun_div_div (hf_indep : iCondIndepFun m' hm' (fun _ ↦ end Div section CommMonoid -variable {β : Type*} {m : MeasurableSpace β} [CommMonoid β] [MeasurableMul₂ β] {f : ι → Ω → β} +variable {m : MeasurableSpace β} [CommMonoid β] [MeasurableMul₂ β] {f : ι → Ω → β} @[to_additive] theorem iCondIndepFun.condIndepFun_finset_prod_of_not_mem diff --git a/Mathlib/Probability/Kernel/Composition.lean b/Mathlib/Probability/Kernel/Composition.lean index 2a16eb0159a62..aa3839f4407e9 100644 --- a/Mathlib/Probability/Kernel/Composition.lean +++ b/Mathlib/Probability/Kernel/Composition.lean @@ -234,7 +234,7 @@ lemma compProd_zero_left (κ : Kernel (α × β) γ) : · rw [Kernel.compProd_of_not_isSFiniteKernel_right _ _ h] @[simp] -lemma compProd_zero_right (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] : +lemma compProd_zero_right (κ : Kernel α β) (γ : Type*) {mγ : MeasurableSpace γ} : κ ⊗ₖ (0 : Kernel (α × β) γ) = 0 := by by_cases h : IsSFiniteKernel κ · ext a s hs @@ -566,7 +566,7 @@ section MapComap /-! ### map, comap -/ -variable {γ δ : Type*} [MeasurableSpace γ] {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} +variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} /-- The pushforward of a kernel along a measurable function. This is an implementation detail, use `map κ f` instead. -/ @@ -580,7 +580,7 @@ open Classical in If the function is not measurable, we use zero instead. This choice of junk value ensures that typeclass inference can infer that the `map` of a kernel satisfying `IsZeroOrMarkovKernel` again satisfies this property. -/ -noncomputable def map (κ : Kernel α β) (f : β → γ) : Kernel α γ := +noncomputable def map [MeasurableSpace γ] (κ : Kernel α β) (f : β → γ) : Kernel α γ := if hf : Measurable f then mapOfMeasurable κ f hf else 0 theorem map_of_not_measurable (κ : Kernel α β) {f : β → γ} (hf : ¬(Measurable f)) : @@ -802,7 +802,7 @@ lemma map_prodMkLeft (γ : Type*) [MeasurableSpace γ] (κ : Kernel α β) (f : rfl · simp [map_of_not_measurable _ hf] -lemma map_prodMkRight (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] (f : β → δ) : +lemma map_prodMkRight (κ : Kernel α β) (γ : Type*) {mγ : MeasurableSpace γ} (f : β → δ) : map (prodMkRight γ κ) f = prodMkRight γ (map κ f) := by by_cases hf : Measurable f · simp only [map, hf, ↓reduceDIte] @@ -832,10 +832,10 @@ instance IsFiniteKernel.swapLeft (κ : Kernel (α × β) γ) [IsFiniteKernel κ] instance IsSFiniteKernel.swapLeft (κ : Kernel (α × β) γ) [IsSFiniteKernel κ] : IsSFiniteKernel (swapLeft κ) := by rw [Kernel.swapLeft]; infer_instance -@[simp] lemma swapLeft_prodMkLeft (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] : +@[simp] lemma swapLeft_prodMkLeft (κ : Kernel α β) (γ : Type*) {_ : MeasurableSpace γ} : swapLeft (prodMkLeft γ κ) = prodMkRight γ κ := rfl -@[simp] lemma swapLeft_prodMkRight (κ : Kernel α β) (γ : Type*) [MeasurableSpace γ] : +@[simp] lemma swapLeft_prodMkRight (κ : Kernel α β) (γ : Type*) {_ : MeasurableSpace γ} : swapLeft (prodMkRight γ κ) = prodMkLeft γ κ := rfl /-- Define a `Kernel α (γ × β)` from a `Kernel α (β × γ)` by taking the map of `Prod.swap`. @@ -1029,7 +1029,7 @@ section Comp /-! ### Composition of two kernels -/ -variable {γ : Type*} {mγ : MeasurableSpace γ} {f : β → γ} {g : γ → α} +variable {γ δ : Type*} {mγ : MeasurableSpace γ} {mδ : MeasurableSpace δ} {f : β → γ} {g : γ → α} /-- Composition of two kernels. -/ noncomputable def comp (η : Kernel β γ) (κ : Kernel α β) : Kernel α γ where @@ -1046,6 +1046,10 @@ theorem comp_apply' (η : Kernel β γ) (κ : Kernel α β) (a : α) {s : Set γ (η ∘ₖ κ) a s = ∫⁻ b, η b s ∂κ a := by rw [comp_apply, Measure.bind_apply hs (Kernel.measurable _)] +@[simp] lemma zero_comp (κ : Kernel α β) : (0 : Kernel β γ) ∘ₖ κ = 0 := by ext; simp [comp_apply] + +@[simp] lemma comp_zero (κ : Kernel β γ) : κ ∘ₖ (0 : Kernel α β) = 0 := by ext; simp [comp_apply] + theorem comp_eq_snd_compProd (η : Kernel β γ) [IsSFiniteKernel η] (κ : Kernel α β) [IsSFiniteKernel κ] : η ∘ₖ κ = snd (κ ⊗ₖ prodMkLeft α η) := by ext a s hs @@ -1085,6 +1089,10 @@ theorem comp_deterministic_eq_comap (κ : Kernel α β) (hg : Measurable g) : simp_rw [comap_apply' _ _ _ s, comp_apply' _ _ _ hs, deterministic_apply hg a, lintegral_dirac' _ (Kernel.measurable_coe κ hs)] +lemma deterministic_comp_deterministic (hf : Measurable f) (hg : Measurable g) : + (deterministic g hg) ∘ₖ (deterministic f hf) = deterministic (g ∘ f) (hg.comp hf) := by + ext; simp [comp_deterministic_eq_comap, comap_apply, deterministic_apply] + lemma const_comp (μ : Measure γ) (κ : Kernel α β) : const β μ ∘ₖ κ = fun a ↦ (κ a) Set.univ • μ := by ext _ _ hs @@ -1096,6 +1104,29 @@ lemma const_comp' (μ : Measure γ) (κ : Kernel α β) [IsMarkovKernel κ] : const β μ ∘ₖ κ = const α μ := by ext; simp_rw [const_comp, measure_univ, one_smul, const_apply] +lemma map_comp (κ : Kernel α β) (η : Kernel β γ) (f : γ → δ) : + (η ∘ₖ κ).map f = (η.map f) ∘ₖ κ := by + by_cases hf : Measurable f + · ext a s hs + rw [map_apply' _ hf _ hs, comp_apply', comp_apply' _ _ _ hs] + · simp_rw [map_apply' _ hf _ hs] + · exact hf hs + · simp [map_of_not_measurable _ hf] + +lemma fst_comp (κ : Kernel α β) (η : Kernel β (γ × δ)) : (η ∘ₖ κ).fst = η.fst ∘ₖ κ := by + simp [fst_eq, map_comp κ η _] + +lemma snd_comp (κ : Kernel α β) (η : Kernel β (γ × δ)) : (η ∘ₖ κ).snd = η.snd ∘ₖ κ := by + simp_rw [snd_eq, map_comp κ η _] + +@[simp] lemma snd_compProd_prodMkLeft + (κ : Kernel α β) (η : Kernel β γ) [IsSFiniteKernel κ] [IsSFiniteKernel η] : + snd (κ ⊗ₖ prodMkLeft α η) = η ∘ₖ κ := by + ext a s hs + rw [snd_apply' _ _ hs, compProd_apply, comp_apply' _ _ _ hs] + · rfl + · exact measurable_snd hs + end Comp section Prod @@ -1158,6 +1189,12 @@ instance IsSFiniteKernel.prod (κ : Kernel α β) (η : Kernel α γ) : snd (κ ×ₖ η) = η := by ext x; simp [snd_apply, prod_apply] +lemma deterministic_prod_deterministic {f : α → β} {g : α → γ} + (hf : Measurable f) (hg : Measurable g) : + deterministic f hf ×ₖ deterministic g hg + = deterministic (fun a ↦ (f a, g a)) (hf.prod_mk hg) := by + ext; simp_rw [prod_apply, deterministic_apply, Measure.dirac_prod_dirac] + end Prod end Kernel end ProbabilityTheory diff --git a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean index 5b8e36ae7d2f4..3655fb84066ea 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CDFToKernel.lean @@ -63,7 +63,8 @@ to `ν` if is measurable, if `fun b ↦ f (a, b) x` is `(ν a)`-integrable for a and for all measurable sets `s : Set β`, `∫ b in s, f (a, b) x ∂(ν a) = (κ a (s ×ˢ Iic x)).toReal`. Also the `ℚ → ℝ` function `f (a, b)` should satisfy the properties of a Sieltjes function for `(ν a)`-almost all `b : β`. -/ -structure IsRatCondKernelCDF (f : α × β → ℚ → ℝ) (κ : Kernel α (β × ℝ)) (ν : Kernel α β) : Prop := +structure IsRatCondKernelCDF (f : α × β → ℚ → ℝ) (κ : Kernel α (β × ℝ)) (ν : Kernel α β) : + Prop where measurable : Measurable f isRatStieltjesPoint_ae (a : α) : ∀ᵐ b ∂(ν a), IsRatStieltjesPoint f (a, b) integrable (a : α) (q : ℚ) : Integrable (fun b ↦ f (a, b) q) (ν a) @@ -222,7 +223,7 @@ lemma integral_stieltjesOfMeasurableRat [IsFiniteKernel κ] (hf : IsRatCondKerne (a : α) (x : ℝ) : ∫ b, stieltjesOfMeasurableRat f hf.measurable (a, b) x ∂(ν a) = (κ a (univ ×ˢ Iic x)).toReal := by - rw [← integral_univ, setIntegral_stieltjesOfMeasurableRat hf _ _ MeasurableSet.univ] + rw [← setIntegral_univ, setIntegral_stieltjesOfMeasurableRat hf _ _ MeasurableSet.univ] end stieltjesOfMeasurableRat @@ -234,7 +235,7 @@ variable {f : α × β → ℚ → ℝ} conditions are the same, but the limit properties of `IsRatCondKernelCDF` are replaced by limits of integrals. -/ structure IsRatCondKernelCDFAux (f : α × β → ℚ → ℝ) (κ : Kernel α (β × ℝ)) (ν : Kernel α β) : - Prop := + Prop where measurable : Measurable f mono' (a : α) {q r : ℚ} (_hqr : q ≤ r) : ∀ᵐ c ∂(ν a), f (a, c) q ≤ f (a, c) r nonneg' (a : α) (q : ℚ) : ∀ᵐ c ∂(ν a), 0 ≤ f (a, c) q @@ -424,7 +425,7 @@ respect to `ν` if it is measurable, tends to 0 at -∞ and to 1 at +∞ for all `fun b ↦ f (a, b) x` is `(ν a)`-integrable for all `a : α` and `x : ℝ` and for all measurable sets `s : Set β`, `∫ b in s, f (a, b) x ∂(ν a) = (κ a (s ×ˢ Iic x)).toReal`. -/ structure IsCondKernelCDF (f : α × β → StieltjesFunction) (κ : Kernel α (β × ℝ)) (ν : Kernel α β) : - Prop := + Prop where measurable (x : ℝ) : Measurable fun p ↦ f p x integrable (a : α) (x : ℝ) : Integrable (fun b ↦ f (a, b) x) (ν a) tendsto_atTop_one (p : α × β) : Tendsto (f p) atTop (𝓝 1) diff --git a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean index 22bfd49d0e410..a5c415461bb5b 100644 --- a/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean +++ b/Mathlib/Probability/Kernel/Disintegration/CondCDF.lean @@ -192,7 +192,7 @@ alias set_integral_preCDF_fst := setIntegral_preCDF_fst lemma integral_preCDF_fst (ρ : Measure (α × ℝ)) (r : ℚ) [IsFiniteMeasure ρ] : ∫ x, (preCDF ρ r x).toReal ∂ρ.fst = (ρ.IicSnd r univ).toReal := by - rw [← integral_univ, setIntegral_preCDF_fst ρ _ MeasurableSet.univ] + rw [← setIntegral_univ, setIntegral_preCDF_fst ρ _ MeasurableSet.univ] lemma integrable_preCDF (ρ : Measure (α × ℝ)) [IsFiniteMeasure ρ] (x : ℚ) : Integrable (fun a ↦ (preCDF ρ x a).toReal) ρ.fst := by diff --git a/Mathlib/Probability/Kernel/Disintegration/Density.lean b/Mathlib/Probability/Kernel/Disintegration/Density.lean index 1e1d4fe17ac12..61538fa7f84ae 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Density.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Density.lean @@ -276,7 +276,7 @@ alias set_integral_densityProcess := setIntegral_densityProcess lemma integral_densityProcess (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (n : ℕ) (a : α) {s : Set β} (hs : MeasurableSet s) : ∫ x, densityProcess κ ν n a x s ∂(ν a) = (κ a (univ ×ˢ s)).toReal := by - rw [← integral_univ, setIntegral_densityProcess hκν _ _ hs MeasurableSet.univ] + rw [← setIntegral_univ, setIntegral_densityProcess hκν _ _ hs MeasurableSet.univ] lemma setIntegral_densityProcess_of_le (hκν : fst κ ≤ ν) [IsFiniteKernel ν] {n m : ℕ} (hnm : n ≤ m) (a : α) {s : Set β} (hs : MeasurableSet s) @@ -576,7 +576,7 @@ alias set_integral_density_of_measurableSet := setIntegral_density_of_measurable lemma integral_density (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (a : α) {s : Set β} (hs : MeasurableSet s) : ∫ x, density κ ν a x s ∂(ν a) = (κ a (univ ×ˢ s)).toReal := by - rw [← integral_univ, setIntegral_density_of_measurableSet hκν 0 a hs MeasurableSet.univ] + rw [← setIntegral_univ, setIntegral_density_of_measurableSet hκν 0 a hs MeasurableSet.univ] lemma setIntegral_density (hκν : fst κ ≤ ν) [IsFiniteKernel ν] (a : α) {s : Set β} (hs : MeasurableSet s) {A : Set γ} (hA : MeasurableSet A) : diff --git a/Mathlib/Probability/Kernel/Disintegration/Integral.lean b/Mathlib/Probability/Kernel/Disintegration/Integral.lean index f712bc83a22b8..026257adcaf92 100644 --- a/Mathlib/Probability/Kernel/Disintegration/Integral.lean +++ b/Mathlib/Probability/Kernel/Disintegration/Integral.lean @@ -146,12 +146,12 @@ end ProbabilityTheory namespace MeasureTheory.Measure -variable {α β Ω : Type*} {mα : MeasurableSpace α} {mβ : MeasurableSpace β} +variable {β Ω : Type*} {mβ : MeasurableSpace β} [MeasurableSpace Ω] [StandardBorelSpace Ω] [Nonempty Ω] section Lintegral -variable [CountableOrCountablyGenerated α β] {ρ : Measure (β × Ω)} [IsFiniteMeasure ρ] +variable {ρ : Measure (β × Ω)} [IsFiniteMeasure ρ] {f : β × Ω → ℝ≥0∞} lemma lintegral_condKernel_mem {s : Set (β × Ω)} (hs : MeasurableSet s) : diff --git a/Mathlib/Probability/Kernel/RadonNikodym.lean b/Mathlib/Probability/Kernel/RadonNikodym.lean index d99f2e27d910e..9e0392d8f287b 100644 --- a/Mathlib/Probability/Kernel/RadonNikodym.lean +++ b/Mathlib/Probability/Kernel/RadonNikodym.lean @@ -402,6 +402,8 @@ lemma rnDeriv_add_singularPart (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFin zero_add, withDensity_rnDeriv_of_subset_compl_mutuallySingularSetSlice (hs.diff hm) (diff_subset_iff.mpr (by simp)), add_comm] +section EqZeroIff + lemma singularPart_eq_zero_iff_apply_eq_zero (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFiniteKernel η] (a : α) : singularPart κ η a = 0 ↔ singularPart κ η a (mutuallySingularSetSlice κ η a) = 0 := by @@ -466,6 +468,8 @@ lemma withDensity_rnDeriv_eq_zero_iff_measure_eq_zero (κ η : Kernel α γ) rw [← h_eq_add] exact withDensity_rnDeriv_eq_zero_iff_apply_eq_zero κ η a +end EqZeroIff + /-- The set of points `a : α` such that `κ a ≪ η a` is measurable. -/ @[measurability] lemma measurableSet_absolutelyContinuous (κ η : Kernel α γ) [IsFiniteKernel κ] [IsFiniteKernel η] : @@ -484,4 +488,65 @@ lemma measurableSet_mutuallySingular (κ η : Kernel α γ) [IsFiniteKernel κ] exact measurable_kernel_prod_mk_left (measurableSet_mutuallySingularSet κ η).compl (measurableSet_singleton 0) +@[simp] +lemma singularPart_self (κ : Kernel α γ) [IsFiniteKernel κ] : κ.singularPart κ = 0 := by + ext : 1; rw [zero_apply, singularPart_eq_zero_iff_absolutelyContinuous] + +section Unique + +variable {ξ : Kernel α γ} {f : α → γ → ℝ≥0∞} [IsFiniteKernel η] + +omit hαγ in +lemma eq_rnDeriv_measure (h : κ = η.withDensity f + ξ) + (hf : Measurable (Function.uncurry f)) (a : α) (hξ : ξ a ⟂ₘ η a) : + f a =ᵐ[η a] ∂(κ a)/∂(η a) := by + have : κ a = ξ a + (η a).withDensity (f a) := by + rw [h, coe_add, Pi.add_apply, η.withDensity_apply hf, add_comm] + exact (κ a).eq_rnDeriv₀ (hf.comp measurable_prod_mk_left).aemeasurable hξ this + +omit hαγ in +lemma eq_singularPart_measure (h : κ = η.withDensity f + ξ) + (hf : Measurable (Function.uncurry f)) (a : α) (hξ : ξ a ⟂ₘ η a) : + ξ a = (κ a).singularPart (η a) := by + have : κ a = ξ a + (η a).withDensity (f a) := by + rw [h, coe_add, Pi.add_apply, η.withDensity_apply hf, add_comm] + exact (κ a).eq_singularPart (hf.comp measurable_prod_mk_left) hξ this + +variable [IsFiniteKernel κ] {a : α} + +lemma rnDeriv_eq_rnDeriv_measure : rnDeriv κ η a =ᵐ[η a] ∂(κ a)/∂(η a) := + eq_rnDeriv_measure (rnDeriv_add_singularPart κ η).symm (measurable_rnDeriv κ η) a + (mutuallySingular_singularPart κ η a) + +lemma singularPart_eq_singularPart_measure : singularPart κ η a = (κ a).singularPart (η a) := + eq_singularPart_measure (rnDeriv_add_singularPart κ η).symm (measurable_rnDeriv κ η) a + (mutuallySingular_singularPart κ η a) + +lemma eq_rnDeriv (h : κ = η.withDensity f + ξ) + (hf : Measurable (Function.uncurry f)) (a : α) (hξ : ξ a ⟂ₘ η a) : + f a =ᵐ[η a] rnDeriv κ η a := + (eq_rnDeriv_measure h hf a hξ).trans rnDeriv_eq_rnDeriv_measure.symm + +lemma eq_singularPart (h : κ = η.withDensity f + ξ) + (hf : Measurable (Function.uncurry f)) (a : α) (hξ : ξ a ⟂ₘ η a) : + ξ a = singularPart κ η a := + (eq_singularPart_measure h hf a hξ).trans singularPart_eq_singularPart_measure.symm + +end Unique + +instance [hκ : IsFiniteKernel κ] [IsFiniteKernel η] : + IsFiniteKernel (withDensity η (rnDeriv κ η)) := by + refine ⟨hκ.bound, hκ.bound_lt_top, fun a ↦ ?_⟩ + rw [Kernel.withDensity_apply', setLIntegral_univ] + swap; · exact measurable_rnDeriv κ η + rw [lintegral_congr_ae rnDeriv_eq_rnDeriv_measure] + exact Measure.lintegral_rnDeriv_le.trans (measure_le_bound _ _ _) + +instance [hκ : IsFiniteKernel κ] [IsFiniteKernel η] : IsFiniteKernel (singularPart κ η) := by + refine ⟨hκ.bound, hκ.bound_lt_top, fun a ↦ ?_⟩ + have h : withDensity η (rnDeriv κ η) a univ + singularPart κ η a univ = κ a univ := by + conv_rhs => rw [← rnDeriv_add_singularPart κ η] + simp + exact (self_le_add_left _ _).trans (h.le.trans (measure_le_bound _ _ _)) + end ProbabilityTheory.Kernel diff --git a/Mathlib/Probability/Martingale/BorelCantelli.lean b/Mathlib/Probability/Martingale/BorelCantelli.lean index fffa57f7af53e..4897ac3d82a8e 100644 --- a/Mathlib/Probability/Martingale/BorelCantelli.lean +++ b/Mathlib/Probability/Martingale/BorelCantelli.lean @@ -39,7 +39,6 @@ open scoped NNReal ENNReal MeasureTheory ProbabilityTheory BigOperators Topology namespace MeasureTheory variable {Ω : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} {ℱ : Filtration ℕ m0} {f : ℕ → Ω → ℝ} - {ω : Ω} /-! ### One sided martingale bound @@ -127,7 +126,7 @@ theorem Submartingale.stoppedValue_leastGE_eLpNorm_le [IsFiniteMeasure μ] (hf : eLpNorm (stoppedValue f (leastGE f r i)) 1 μ ≤ 2 * μ Set.univ * ENNReal.ofReal (r + R) := by refine eLpNorm_one_le_of_le' ((hf.stoppedValue_leastGE r).integrable _) ?_ (norm_stoppedValue_leastGE_le hr hf0 hbdd i) - rw [← integral_univ] + rw [← setIntegral_univ] refine le_trans ?_ ((hf.stoppedValue_leastGE r).setIntegral_le (zero_le _) MeasurableSet.univ) simp_rw [stoppedValue, leastGE, hitting_of_le le_rfl, hf0, integral_zero', le_rfl] diff --git a/Mathlib/Probability/Martingale/Centering.lean b/Mathlib/Probability/Martingale/Centering.lean index a02deed0fd1c2..57697df89952a 100644 --- a/Mathlib/Probability/Martingale/Centering.lean +++ b/Mathlib/Probability/Martingale/Centering.lean @@ -36,7 +36,7 @@ open scoped NNReal ENNReal MeasureTheory ProbabilityTheory namespace MeasureTheory variable {Ω E : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} [NormedAddCommGroup E] - [NormedSpace ℝ E] [CompleteSpace E] {f : ℕ → Ω → E} {ℱ : Filtration ℕ m0} {n : ℕ} + [NormedSpace ℝ E] [CompleteSpace E] {f : ℕ → Ω → E} {ℱ : Filtration ℕ m0} /-- Any `ℕ`-indexed stochastic process can be written as the sum of a martingale and a predictable process. This is the predictable process. See `martingalePart` for the martingale. -/ diff --git a/Mathlib/Probability/Martingale/Convergence.lean b/Mathlib/Probability/Martingale/Convergence.lean index 5cbec74af7d1e..42764ff3c943d 100644 --- a/Mathlib/Probability/Martingale/Convergence.lean +++ b/Mathlib/Probability/Martingale/Convergence.lean @@ -48,7 +48,7 @@ open scoped NNReal ENNReal MeasureTheory ProbabilityTheory Topology namespace MeasureTheory -variable {Ω ι : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} {ℱ : Filtration ℕ m0} +variable {Ω : Type*} {m0 : MeasurableSpace Ω} {μ : Measure Ω} {ℱ : Filtration ℕ m0} variable {a b : ℝ} {f : ℕ → Ω → ℝ} {ω : Ω} {R : ℝ≥0} section AeConvergence @@ -399,8 +399,8 @@ theorem Integrable.tendsto_ae_condexp (hg : Integrable g μ) setIntegral_trim hle stronglyMeasurable_limitProcess htmeas.compl, hgeq, hheq, ← setIntegral_trim hle hgmeas htmeas, ← setIntegral_trim hle stronglyMeasurable_limitProcess htmeas, ← integral_trim hle hgmeas, ← - integral_trim hle stronglyMeasurable_limitProcess, ← integral_univ, - this 0 _ MeasurableSet.univ, integral_univ, ht (measure_lt_top _ _)] + integral_trim hle stronglyMeasurable_limitProcess, ← setIntegral_univ, + this 0 _ MeasurableSet.univ, setIntegral_univ, ht (measure_lt_top _ _)] · rintro f hf hfmeas heq - rw [integral_iUnion (fun n => hle _ (hfmeas n)) hf hg.integrableOn, integral_iUnion (fun n => hle _ (hfmeas n)) hf hlimint.integrableOn] diff --git a/Mathlib/Probability/Martingale/OptionalStopping.lean b/Mathlib/Probability/Martingale/OptionalStopping.lean index fee8f4ea1c1a3..c047618b86b01 100644 --- a/Mathlib/Probability/Martingale/OptionalStopping.lean +++ b/Mathlib/Probability/Martingale/OptionalStopping.lean @@ -144,8 +144,8 @@ theorem maximal_ineq [IsFiniteMeasure μ] (hsub : Submartingale f 𝒢 μ) (hnon (∫ ω in {ω | ↑ε ≤ (range (n+1)).sup' nonempty_range_succ fun k => f k ω}, f n ω ∂μ) + ENNReal.ofReal (∫ ω in {ω | ((range (n+1)).sup' nonempty_range_succ fun k => f k ω) < ↑ε}, f n ω ∂μ) := by - rw [← ENNReal.ofReal_add, ← integral_union] - · rw [← integral_univ] + rw [← ENNReal.ofReal_add, ← setIntegral_union] + · rw [← setIntegral_univ] convert rfl ext ω change (ε : ℝ) ≤ _ ∨ _ < (ε : ℝ) ↔ _ @@ -186,8 +186,8 @@ theorem maximal_ineq [IsFiniteMeasure μ] (hsub : Submartingale f 𝒢 μ) (hnon ((not_le.2 hω) ((le_sup'_iff _).2 ⟨m, mem_range.2 (Nat.lt_succ_of_le hm.2), hεm⟩)) simp_rw [stoppedValue, this, le_rfl] _ = ENNReal.ofReal (∫ ω, stoppedValue f (hitting f {y : ℝ | ↑ε ≤ y} 0 n) ω ∂μ) := by - rw [← ENNReal.ofReal_add, ← integral_union] - · rw [← integral_univ (μ := μ)] + rw [← ENNReal.ofReal_add, ← setIntegral_union] + · rw [← setIntegral_univ (μ := μ)] convert rfl ext ω change _ ↔ (ε : ℝ) ≤ _ ∨ _ < (ε : ℝ) diff --git a/Mathlib/Probability/Martingale/Upcrossing.lean b/Mathlib/Probability/Martingale/Upcrossing.lean index a1694af83142d..3550483556921 100644 --- a/Mathlib/Probability/Martingale/Upcrossing.lean +++ b/Mathlib/Probability/Martingale/Upcrossing.lean @@ -148,7 +148,7 @@ noncomputable def lowerCrossingTime [Preorder ι] [OrderBot ι] [InfSet ι] (a b section variable [Preorder ι] [OrderBot ι] [InfSet ι] -variable {a b : ℝ} {f : ι → Ω → ℝ} {N : ι} {n m : ℕ} {ω : Ω} +variable {a b : ℝ} {f : ι → Ω → ℝ} {N : ι} {n : ℕ} {ω : Ω} @[simp] theorem upperCrossingTime_zero : upperCrossingTime a b f N 0 = ⊥ := @@ -389,7 +389,7 @@ theorem Submartingale.sum_mul_upcrossingStrat_le [IsFiniteMeasure μ] (hf : Subm have h₁ : (0 : ℝ) ≤ μ[∑ k ∈ Finset.range n, (1 - upcrossingStrat a b f N k) * (f (k + 1) - f k)] := by have := (hf.sum_sub_upcrossingStrat_mul a b N).setIntegral_le (zero_le n) MeasurableSet.univ - rw [integral_univ, integral_univ] at this + rw [setIntegral_univ, setIntegral_univ] at this refine le_trans ?_ this simp only [Finset.range_zero, Finset.sum_empty, integral_zero', le_refl] have h₂ : μ[∑ k ∈ Finset.range n, (1 - upcrossingStrat a b f N k) * (f (k + 1) - f k)] = diff --git a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean index ec56f812e2f47..877ecc41e7f9d 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Basic.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Basic.lean @@ -176,7 +176,8 @@ theorem toOuterMeasure_apply_eq_one_iff : p.toOuterMeasure s = 1 ↔ p.support (fun x => Set.indicator_apply_le fun _ => le_rfl) hsa · suffices ∀ (x) (_ : x ∉ s), p x = 0 from _root_.trans (tsum_congr - fun a => (Set.indicator_apply s p a).trans (ite_eq_left_iff.2 <| symm ∘ this a)) p.tsum_coe + fun a => (Set.indicator_apply s p a).trans + (ite_eq_left_iff.2 <| symm ∘ this a)) p.tsum_coe exact fun a ha => (p.apply_eq_zero_iff a).2 <| Set.not_mem_subset h ha @[simp] diff --git a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean index 9ae6765fb79bd..503b97db3cdf2 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Constructions.lean @@ -32,7 +32,7 @@ noncomputable section variable {α β γ : Type*} open scoped Classical -open NNReal ENNReal +open NNReal ENNReal Finset MeasureTheory section Map @@ -82,13 +82,19 @@ variable (s : Set β) theorem toOuterMeasure_map_apply : (p.map f).toOuterMeasure s = p.toOuterMeasure (f ⁻¹' s) := by simp [map, Set.indicator, toOuterMeasure_apply p (f ⁻¹' s)] +variable {mα : MeasurableSpace α} {mβ : MeasurableSpace β} + @[simp] -theorem toMeasure_map_apply [MeasurableSpace α] [MeasurableSpace β] (hf : Measurable f) +theorem toMeasure_map_apply (hf : Measurable f) (hs : MeasurableSet s) : (p.map f).toMeasure s = p.toMeasure (f ⁻¹' s) := by rw [toMeasure_apply_eq_toOuterMeasure_apply _ s hs, toMeasure_apply_eq_toOuterMeasure_apply _ (f ⁻¹' s) (measurableSet_preimage hf hs)] exact toOuterMeasure_map_apply f p s +@[simp] +lemma toMeasure_map (p : PMF α) (hf : Measurable f) : p.toMeasure.map f = (p.map f).toMeasure := by + ext s hs : 1; rw [PMF.toMeasure_map_apply _ _ _ hf hs, Measure.map_apply hf hs] + end Measure end Map @@ -185,6 +191,14 @@ theorem support_ofFintype : (ofFintype f h).support = Function.support f := rfl theorem mem_support_ofFintype_iff (a : α) : a ∈ (ofFintype f h).support ↔ f a ≠ 0 := Iff.rfl +@[simp] +lemma map_ofFintype [Fintype β] (f : α → ℝ≥0∞) (h : ∑ a, f a = 1) (g : α → β) : + (ofFintype f h).map g = ofFintype (fun b ↦ ∑ a with g a = b, f a) + (by simpa [Finset.sum_fiberwise_eq_sum_filter univ univ g f]) := by + ext b : 1 + simp only [sum_filter, eq_comm, map_apply, ofFintype_apply] + exact tsum_eq_sum fun _ h ↦ (h <| mem_univ _).elim + section Measure variable (s : Set α) @@ -247,7 +261,7 @@ theorem support_filter : (p.filter s h).support = s ∩ p.support := Set.ext fun _ => mem_support_filter_iff _ theorem filter_apply_eq_zero_iff (a : α) : (p.filter s h) a = 0 ↔ a ∉ s ∨ a ∉ p.support := by - erw [apply_eq_zero_iff, support_filter, Set.mem_inter_iff, not_and_or] + rw [apply_eq_zero_iff, support_filter, Set.mem_inter_iff, not_and_or] theorem filter_apply_ne_zero_iff (a : α) : (p.filter s h) a ≠ 0 ↔ a ∈ s ∧ a ∈ p.support := by rw [Ne, filter_apply_eq_zero_iff, not_or, Classical.not_not, Classical.not_not] diff --git a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean index 0803f711af0ab..befbc17ee812f 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Integrals.lean @@ -42,7 +42,7 @@ theorem integral_eq_tsum (p : PMF α) (f : α → E) (hf : Integrable f p.toMeas theorem integral_eq_sum [Fintype α] (p : PMF α) (f : α → E) : ∫ a, f a ∂(p.toMeasure) = ∑ a, (p a).toReal • f a := by - rw [integral_fintype _ (.of_finite _ f)] + rw [integral_fintype _ .of_finite] congr with x; congr 2 exact PMF.toMeasure_apply_singleton p x (MeasurableSet.singleton _) diff --git a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean index d137f3c66d02f..31a9cbfa903d1 100644 --- a/Mathlib/Probability/ProbabilityMassFunction/Monad.lean +++ b/Mathlib/Probability/ProbabilityMassFunction/Monad.lean @@ -67,9 +67,11 @@ theorem toOuterMeasure_pure_apply : (pure a).toOuterMeasure s = if a ∈ s then refine (toOuterMeasure_apply (pure a) s).trans ?_ split_ifs with ha · refine (tsum_congr fun b => ?_).trans (tsum_ite_eq a 1) - exact ite_eq_left_iff.2 fun hb => symm (ite_eq_right_iff.2 fun h => (hb <| h.symm ▸ ha).elim) + exact ite_eq_left_iff.2 fun hb => + symm (ite_eq_right_iff.2 fun h => (hb <| h.symm ▸ ha).elim) · refine (tsum_congr fun b => ?_).trans tsum_zero - exact ite_eq_right_iff.2 fun hb => ite_eq_right_iff.2 fun h => (ha <| h ▸ hb).elim + exact ite_eq_right_iff.2 fun hb => + ite_eq_right_iff.2 fun h => (ha <| h ▸ hb).elim variable [MeasurableSpace α] diff --git a/Mathlib/Probability/Process/HittingTime.lean b/Mathlib/Probability/Process/HittingTime.lean index 161d19118807f..4cf0ce22da61f 100644 --- a/Mathlib/Probability/Process/HittingTime.lean +++ b/Mathlib/Probability/Process/HittingTime.lean @@ -260,7 +260,7 @@ theorem isStoppingTime_hitting_isStoppingTime [ConditionallyCompleteLinearOrder section CompleteLattice -variable [CompleteLattice ι] {u : ι → Ω → β} {s : Set β} {f : Filtration ι m} +variable [CompleteLattice ι] {u : ι → Ω → β} {s : Set β} theorem hitting_eq_sInf (ω : Ω) : hitting u s ⊥ ⊤ ω = sInf {i : ι | u i ω ∈ s} := by simp only [hitting, Set.mem_Icc, bot_le, le_top, and_self_iff, exists_true_left, Set.Icc_bot, @@ -276,7 +276,7 @@ end CompleteLattice section ConditionallyCompleteLinearOrderBot variable [ConditionallyCompleteLinearOrderBot ι] [IsWellOrder ι (· < ·)] -variable {u : ι → Ω → β} {s : Set β} {f : Filtration ℕ m} +variable {u : ι → Ω → β} {s : Set β} theorem hitting_bot_le_iff {i n : ι} {ω : Ω} (hx : ∃ j, j ≤ n ∧ u j ω ∈ s) : hitting u s ⊥ n ω ≤ i ↔ ∃ j ≤ i, u j ω ∈ s := by diff --git a/Mathlib/Probability/Process/Stopping.lean b/Mathlib/Probability/Process/Stopping.lean index 0b6419fc37ae6..a68d221da2416 100644 --- a/Mathlib/Probability/Process/Stopping.lean +++ b/Mathlib/Probability/Process/Stopping.lean @@ -805,7 +805,7 @@ end LinearOrder section StoppedValueOfMemFinset -variable {μ : Measure Ω} {τ σ : Ω → ι} {E : Type*} {p : ℝ≥0∞} {u : ι → Ω → E} +variable {μ : Measure Ω} {τ : Ω → ι} {E : Type*} {p : ℝ≥0∞} {u : ι → Ω → E} theorem stoppedValue_eq_of_mem_finset [AddCommMonoid E] {s : Finset ι} (hbdd : ∀ ω, τ ω ∈ s) : stoppedValue u τ = ∑ i ∈ s, Set.indicator {ω | τ ω = i} (u i) := by @@ -956,7 +956,7 @@ section Nat open Filtration -variable {f : Filtration ℕ m} {u : ℕ → Ω → β} {τ π : Ω → ℕ} +variable {u : ℕ → Ω → β} {τ π : Ω → ℕ} theorem stoppedValue_sub_eq_sum [AddCommGroup β] (hle : τ ≤ π) : stoppedValue u π - stoppedValue u τ = fun ω => diff --git a/Mathlib/Probability/StrongLaw.lean b/Mathlib/Probability/StrongLaw.lean index 4b097fac62731..70fe8e747018d 100644 --- a/Mathlib/Probability/StrongLaw.lean +++ b/Mathlib/Probability/StrongLaw.lean @@ -396,7 +396,7 @@ theorem strong_law_aux1 {c : ℝ} (c_one : 1 < c) {ε : ℝ} (εpos : 0 < ε) : set Y := fun n : ℕ => truncation (X n) n set S := fun n => ∑ i ∈ range n, Y i with hS let u : ℕ → ℕ := fun n => ⌊c ^ n⌋₊ - have u_mono : Monotone u := fun i j hij => Nat.floor_mono (pow_le_pow_right c_one.le hij) + have u_mono : Monotone u := fun i j hij => Nat.floor_mono (pow_right_mono₀ c_one.le hij) have I1 : ∀ K, ∑ j ∈ range K, ((j : ℝ) ^ 2)⁻¹ * Var[Y j] ≤ 2 * 𝔼[X 0] := by intro K calc @@ -457,7 +457,7 @@ theorem strong_law_aux1 {c : ℝ} (c_one : 1 < c) {ε : ℝ} (εpos : 0 < ε) : refine zero_lt_one.trans_le ?_ apply Nat.le_floor rw [Nat.cast_one] - apply one_le_pow_of_one_le c_one.le + apply one_le_pow₀ c_one.le _ = ENNReal.ofReal (∑ i ∈ range N, Var[S (u i)] / (u i * ε) ^ 2) := by rw [ENNReal.ofReal_sum_of_nonneg fun i _ => ?_] exact div_nonneg (variance_nonneg _ _) (sq_nonneg _) @@ -563,7 +563,7 @@ theorem strong_law_aux6 {c : ℝ} (c_one : 1 < c) : have H : ∀ n : ℕ, (0 : ℝ) < ⌊c ^ n⌋₊ := by intro n refine zero_lt_one.trans_le ?_ - simp only [Nat.one_le_cast, Nat.one_le_floor_iff, one_le_pow_of_one_le c_one.le n] + simp only [Nat.one_le_cast, Nat.one_le_floor_iff, one_le_pow₀ c_one.le] filter_upwards [strong_law_aux4 X hint hindep hident hnonneg c_one, strong_law_aux5 X hint hident hnonneg] with ω hω h'ω rw [← tendsto_sub_nhds_zero_iff, ← Asymptotics.isLittleO_one_iff ℝ] @@ -603,10 +603,12 @@ identically distributed integrable real-valued random variables, then `∑ i ∈ converges almost surely to `𝔼[X 0]`. We give here the strong version, due to Etemadi, that only requires pairwise independence. Superseded by `strong_law_ae`, which works for random variables taking values in any Banach space. -/ -theorem strong_law_ae_real {Ω : Type*} [MeasureSpace Ω] - (X : ℕ → Ω → ℝ) (hint : Integrable (X 0)) - (hindep : Pairwise fun i j => IndepFun (X i) (X j)) (hident : ∀ i, IdentDistrib (X i) (X 0)) : - ∀ᵐ ω, Tendsto (fun n : ℕ => (∑ i ∈ range n, X i ω) / n) atTop (𝓝 𝔼[X 0]) := by +theorem strong_law_ae_real {Ω : Type*} {m : MeasurableSpace Ω} {μ : Measure Ω} + (X : ℕ → Ω → ℝ) (hint : Integrable (X 0) μ) + (hindep : Pairwise fun i j => IndepFun (X i) (X j) μ) + (hident : ∀ i, IdentDistrib (X i) (X 0) μ μ) : + ∀ᵐ ω ∂μ, Tendsto (fun n : ℕ => (∑ i ∈ range n, X i ω) / n) atTop (𝓝 (μ [X 0])) := by + let mΩ : MeasureSpace Ω := ⟨μ⟩ -- first get rid of the trivial case where the space is not a probability space by_cases h : ∀ᵐ ω, X 0 ω = 0 · have I : ∀ᵐ ω, ∀ i, X i ω = 0 := by @@ -615,7 +617,7 @@ theorem strong_law_ae_real {Ω : Type*} [MeasureSpace Ω] exact (hident i).symm.ae_snd (p := fun x ↦ x = 0) measurableSet_eq h filter_upwards [I] with ω hω simpa [hω] using (integral_eq_zero_of_ae h).symm - have : IsProbabilityMeasure (ℙ : Measure Ω) := + have : IsProbabilityMeasure μ := hint.isProbabilityMeasure_of_indepFun (X 0) (X 1) h (hindep zero_ne_one) -- then consider separately the positive and the negative part, and apply the result -- for nonnegative functions to them. @@ -630,17 +632,17 @@ theorem strong_law_ae_real {Ω : Type*} [MeasureSpace Ω] strong_law_aux7 _ hint.neg_part (fun i j hij => (hindep hij).comp negm negm) (fun i => (hident i).comp negm) fun i ω => le_max_right _ _ filter_upwards [A, B] with ω hωpos hωneg - convert hωpos.sub hωneg using 1 + convert hωpos.sub hωneg using 2 · simp only [pos, neg, ← sub_div, ← sum_sub_distrib, max_zero_sub_max_neg_zero_eq_self, Function.comp_apply] · simp only [← integral_sub hint.pos_part hint.neg_part, max_zero_sub_max_neg_zero_eq_self, - Function.comp_apply] + Function.comp_apply, mΩ] end StrongLawAeReal section StrongLawVectorSpace -variable {Ω : Type*} [MeasureSpace Ω] [IsProbabilityMeasure (ℙ : Measure Ω)] +variable {Ω : Type*} {mΩ : MeasurableSpace Ω} {μ : Measure Ω} [IsProbabilityMeasure μ] {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] [MeasurableSpace E] @@ -650,22 +652,23 @@ open Set TopologicalSpace the composition of the random variables with a simple function satisfies the strong law of large numbers. -/ lemma strong_law_ae_simpleFunc_comp (X : ℕ → Ω → E) (h' : Measurable (X 0)) - (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j))) (hident : ∀ i, IdentDistrib (X i) (X 0)) - (φ : SimpleFunc E E) : ∀ᵐ ω, - Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, φ (X i ω))) atTop (𝓝 𝔼[φ ∘ (X 0)]) := by + (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j) μ)) + (hident : ∀ i, IdentDistrib (X i) (X 0) μ μ) (φ : SimpleFunc E E) : + ∀ᵐ ω ∂μ, + Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, φ (X i ω))) atTop (𝓝 (μ [φ ∘ (X 0)])) := by -- this follows from the one-dimensional version when `φ` takes a single value, and is then -- extended to the general case by linearity. classical - refine SimpleFunc.induction (P := fun ψ ↦ ∀ᵐ ω, - Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, ψ (X i ω))) atTop (𝓝 𝔼[ψ ∘ (X 0)])) ?_ ?_ φ + refine SimpleFunc.induction (P := fun ψ ↦ ∀ᵐ ω ∂μ, + Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, ψ (X i ω))) atTop (𝓝 (μ [ψ ∘ (X 0)]))) ?_ ?_ φ · intro c s hs simp only [SimpleFunc.const_zero, SimpleFunc.coe_piecewise, SimpleFunc.coe_const, SimpleFunc.coe_zero, piecewise_eq_indicator, Function.comp_apply] let F : E → ℝ := indicator s 1 have F_meas : Measurable F := (measurable_indicator_const_iff 1).2 hs let Y : ℕ → Ω → ℝ := fun n ↦ F ∘ (X n) - have : ∀ᵐ (ω : Ω), Tendsto (fun (n : ℕ) ↦ (n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y i ω) - atTop (𝓝 𝔼[Y 0]) := by + have : ∀ᵐ (ω : Ω) ∂μ, Tendsto (fun (n : ℕ) ↦ (n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y i ω) + atTop (𝓝 (μ [Y 0])) := by simp only [Function.const_one, smul_eq_mul, ← div_eq_inv_mul] apply strong_law_ae_real · exact SimpleFunc.integrable_of_isFiniteMeasure @@ -699,9 +702,10 @@ variable [BorelSpace E] assuming measurability in addition to integrability. This is weakened to ae measurability in the full version `ProbabilityTheory.strong_law_ae`. -/ lemma strong_law_ae_of_measurable - (X : ℕ → Ω → E) (hint : Integrable (X 0)) (h' : StronglyMeasurable (X 0)) - (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j))) (hident : ∀ i, IdentDistrib (X i) (X 0)) : - ∀ᵐ ω, Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) atTop (𝓝 𝔼[X 0]) := by + (X : ℕ → Ω → E) (hint : Integrable (X 0) μ) (h' : StronglyMeasurable (X 0)) + (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j) μ)) + (hident : ∀ i, IdentDistrib (X i) (X 0) μ μ) : + ∀ᵐ ω ∂μ, Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) atTop (𝓝 (μ [X 0])) := by /- Choose a simple function `φ` such that `φ (X 0)` approximates well enough `X 0` -- this is possible as `X 0` is strongly measurable. Then `φ (X n)` approximates well `X n`. Then the strong law for `φ (X n)` implies the strong law for `X n`, up to a small @@ -717,12 +721,12 @@ lemma strong_law_ae_of_measurable SimpleFunc.nearestPt (fun k => Nat.casesOn k 0 ((↑) ∘ denseSeq s) : ℕ → E) let Y : ℕ → ℕ → Ω → E := fun k i ↦ (φ k) ∘ (X i) -- strong law for `φ (X n)` - have A : ∀ᵐ ω, ∀ k, - Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, Y k i ω)) atTop (𝓝 𝔼[Y k 0]) := + have A : ∀ᵐ ω ∂μ, ∀ k, + Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, Y k i ω)) atTop (𝓝 (μ [Y k 0])) := ae_all_iff.2 (fun k ↦ strong_law_ae_simpleFunc_comp X h'.measurable hindep hident (φ k)) -- strong law for the error `‖X i - φ (X i)‖` - have B : ∀ᵐ ω, ∀ k, Tendsto (fun n : ℕ ↦ (∑ i ∈ range n, ‖(X i - Y k i) ω‖) / n) - atTop (𝓝 𝔼[(fun ω ↦ ‖(X 0 - Y k 0) ω‖)]) := by + have B : ∀ᵐ ω ∂μ, ∀ k, Tendsto (fun n : ℕ ↦ (∑ i ∈ range n, ‖(X i - Y k i) ω‖) / n) + atTop (𝓝 (μ [(fun ω ↦ ‖(X 0 - Y k 0) ω‖)])) := by apply ae_all_iff.2 (fun k ↦ ?_) let G : ℕ → E → ℝ := fun k x ↦ ‖x - φ k x‖ have G_meas : ∀ k, Measurable (G k) := @@ -745,32 +749,32 @@ lemma strong_law_ae_of_measurable obtain ⟨δ, δpos, hδ⟩ : ∃ δ, 0 < δ ∧ δ + δ + δ < ε := ⟨ε/4, by positivity, by linarith⟩ -- choose `k` large enough so that `φₖ (X 0)` approximates well enough `X 0`, up to the -- precision `δ`. - obtain ⟨k, hk⟩ : ∃ k, ∫ ω, ‖(X 0 - Y k 0) ω‖ < δ := by + obtain ⟨k, hk⟩ : ∃ k, ∫ ω, ‖(X 0 - Y k 0) ω‖ ∂μ < δ := by simp_rw [Pi.sub_apply, norm_sub_rev (X 0 _)] exact ((tendsto_order.1 (tendsto_integral_norm_approxOn_sub h'.measurable hint)).2 δ δpos).exists - have : ‖𝔼[Y k 0] - 𝔼[X 0]‖ < δ := by + have : ‖μ [Y k 0] - μ [X 0]‖ < δ := by rw [norm_sub_rev, ← integral_sub hint] · exact (norm_integral_le_integral_norm _).trans_lt hk · exact ((φ k).comp (X 0) h'.measurable).integrable_of_isFiniteMeasure -- consider `n` large enough for which the above convergences have taken place within `δ`. have I : ∀ᶠ n in atTop, (∑ i ∈ range n, ‖(X i - Y k i) ω‖) / n < δ := (tendsto_order.1 (h'ω k)).2 δ hk - have J : ∀ᶠ (n : ℕ) in atTop, ‖(n : ℝ) ⁻¹ • (∑ i ∈ range n, Y k i ω) - 𝔼[Y k 0]‖ < δ := by + have J : ∀ᶠ (n : ℕ) in atTop, ‖(n : ℝ) ⁻¹ • (∑ i ∈ range n, Y k i ω) - μ [Y k 0]‖ < δ := by specialize hω k rw [tendsto_iff_norm_sub_tendsto_zero] at hω exact (tendsto_order.1 hω).2 δ δpos filter_upwards [I, J] with n hn h'n -- at such an `n`, the strong law is realized up to `ε`. calc - ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, X i ω - 𝔼[X 0]‖ + ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, X i ω - μ [X 0]‖ = ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, (X i ω - Y k i ω) + - ((n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y k i ω - 𝔼[Y k 0]) + (𝔼[Y k 0] - 𝔼[X 0])‖ := by + ((n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y k i ω - μ [Y k 0]) + (μ [Y k 0] - μ [X 0])‖ := by congr simp only [Function.comp_apply, sum_sub_distrib, smul_sub] abel _ ≤ ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, (X i ω - Y k i ω)‖ + - ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y k i ω - 𝔼[Y k 0]‖ + ‖𝔼[Y k 0] - 𝔼[X 0]‖ := + ‖(n : ℝ)⁻¹ • ∑ i ∈ Finset.range n, Y k i ω - μ [Y k 0]‖ + ‖μ [Y k 0] - μ [X 0]‖ := norm_add₃_le _ _ _ _ ≤ (∑ i ∈ Finset.range n, ‖X i ω - Y k i ω‖) / n + δ + δ := by gcongr @@ -783,37 +787,39 @@ lemma strong_law_ae_of_measurable exact hn.le _ < ε := hδ +omit [IsProbabilityMeasure μ] in /-- **Strong law of large numbers**, almost sure version: if `X n` is a sequence of independent identically distributed integrable random variables taking values in a Banach space, then `n⁻¹ • ∑ i ∈ range n, X i` converges almost surely to `𝔼[X 0]`. We give here the strong version, due to Etemadi, that only requires pairwise independence. -/ -theorem strong_law_ae {Ω : Type*} [MeasureSpace Ω] - (X : ℕ → Ω → E) (hint : Integrable (X 0)) - (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j))) (hident : ∀ i, IdentDistrib (X i) (X 0)) : - ∀ᵐ ω, Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) atTop (𝓝 𝔼[X 0]) := by +theorem strong_law_ae (X : ℕ → Ω → E) (hint : Integrable (X 0) μ) + (hindep : Pairwise (fun i j ↦ IndepFun (X i) (X j) μ)) + (hident : ∀ i, IdentDistrib (X i) (X 0) μ μ) : + ∀ᵐ ω ∂μ, Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) atTop (𝓝 (μ [X 0])) := by -- First exclude the trivial case where the space is not a probability space - by_cases h : ∀ᵐ ω, X 0 ω = 0 - · have I : ∀ᵐ ω, ∀ i, X i ω = 0 := by + by_cases h : ∀ᵐ ω ∂μ, X 0 ω = 0 + · have I : ∀ᵐ ω ∂μ, ∀ i, X i ω = 0 := by rw [ae_all_iff] intro i exact (hident i).symm.ae_snd (p := fun x ↦ x = 0) measurableSet_eq h filter_upwards [I] with ω hω simpa [hω] using (integral_eq_zero_of_ae h).symm - have : IsProbabilityMeasure (ℙ : Measure Ω) := + have : IsProbabilityMeasure μ := hint.isProbabilityMeasure_of_indepFun (X 0) (X 1) h (hindep zero_ne_one) -- we reduce to the case of strongly measurable random variables, by using `Y i` which is strongly -- measurable and ae equal to `X i`. - have A : ∀ i, Integrable (X i) := fun i ↦ (hident i).integrable_iff.2 hint + have A : ∀ i, Integrable (X i) μ := fun i ↦ (hident i).integrable_iff.2 hint let Y : ℕ → Ω → E := fun i ↦ (A i).1.mk (X i) - have B : ∀ᵐ ω, ∀ n, X n ω = Y n ω := + have B : ∀ᵐ ω ∂μ, ∀ n, X n ω = Y n ω := ae_all_iff.2 (fun i ↦ AEStronglyMeasurable.ae_eq_mk (A i).1) - have Yint : Integrable (Y 0) := Integrable.congr hint (AEStronglyMeasurable.ae_eq_mk (A 0).1) - have C : ∀ᵐ ω, Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, Y i ω)) atTop (𝓝 𝔼[Y 0]) := by + have Yint : Integrable (Y 0) μ := Integrable.congr hint (AEStronglyMeasurable.ae_eq_mk (A 0).1) + have C : ∀ᵐ ω ∂μ, + Tendsto (fun n : ℕ ↦ (n : ℝ) ⁻¹ • (∑ i ∈ range n, Y i ω)) atTop (𝓝 (μ [Y 0])) := by apply strong_law_ae_of_measurable Y Yint ((A 0).1.stronglyMeasurable_mk) (fun i j hij ↦ IndepFun.ae_eq (hindep hij) (A i).1.ae_eq_mk (A j).1.ae_eq_mk) (fun i ↦ ((A i).1.identDistrib_mk.symm.trans (hident i)).trans (A 0).1.identDistrib_mk) filter_upwards [B, C] with ω h₁ h₂ - have : 𝔼[X 0] = 𝔼[Y 0] := integral_congr_ae (AEStronglyMeasurable.ae_eq_mk (A 0).1) + have : μ [X 0] = μ [Y 0] := integral_congr_ae (AEStronglyMeasurable.ae_eq_mk (A 0).1) rw [this] apply Tendsto.congr (fun n ↦ ?_) h₂ congr with i @@ -823,39 +829,39 @@ end StrongLawVectorSpace section StrongLawLp -variable {Ω : Type*} [MeasureSpace Ω] +variable {Ω : Type*} {mΩ : MeasurableSpace Ω} {μ : Measure Ω} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] [CompleteSpace E] [MeasurableSpace E] [BorelSpace E] /-- **Strong law of large numbers**, Lᵖ version: if `X n` is a sequence of independent identically distributed random variables in Lᵖ, then `n⁻¹ • ∑ i ∈ range n, X i` converges in `Lᵖ` to `𝔼[X 0]`. -/ -theorem strong_law_Lp {p : ℝ≥0∞} (hp : 1 ≤ p) (hp' : p ≠ ∞) (X : ℕ → Ω → E) (hℒp : Memℒp (X 0) p) - (hindep : Pairwise fun i j => IndepFun (X i) (X j)) (hident : ∀ i, IdentDistrib (X i) (X 0)) : - Tendsto (fun (n : ℕ) => eLpNorm (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω) - 𝔼[X 0]) p) +theorem strong_law_Lp {p : ℝ≥0∞} (hp : 1 ≤ p) (hp' : p ≠ ∞) (X : ℕ → Ω → E) + (hℒp : Memℒp (X 0) p μ) (hindep : Pairwise fun i j => IndepFun (X i) (X j) μ) + (hident : ∀ i, IdentDistrib (X i) (X 0) μ μ) : + Tendsto (fun (n : ℕ) => eLpNorm (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω) - μ [X 0]) p μ) atTop (𝓝 0) := by -- First exclude the trivial case where the space is not a probability space - by_cases h : ∀ᵐ ω, X 0 ω = 0 - · have I : ∀ᵐ ω, ∀ i, X i ω = 0 := by + by_cases h : ∀ᵐ ω ∂μ, X 0 ω = 0 + · have I : ∀ᵐ ω ∂μ, ∀ i, X i ω = 0 := by rw [ae_all_iff] intro i exact (hident i).symm.ae_snd (p := fun x ↦ x = 0) measurableSet_eq h - have A (n : ℕ) : eLpNorm (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω) - 𝔼[X 0]) p ℙ = 0 := by + have A (n : ℕ) : eLpNorm (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω) - μ [X 0]) p μ = 0 := by simp only [integral_eq_zero_of_ae h, sub_zero] apply eLpNorm_eq_zero_of_ae_zero filter_upwards [I] with ω hω simp [hω] simp [A] -- Then use ae convergence and uniform integrability - have : IsProbabilityMeasure (ℙ : Measure Ω) := Memℒp.isProbabilityMeasure_of_indepFun + have : IsProbabilityMeasure μ := Memℒp.isProbabilityMeasure_of_indepFun (X 0) (X 1) (zero_lt_one.trans_le hp).ne' hp' hℒp h (hindep zero_ne_one) - have hmeas : ∀ i, AEStronglyMeasurable (X i) ℙ := fun i => + have hmeas : ∀ i, AEStronglyMeasurable (X i) μ := fun i => (hident i).aestronglyMeasurable_iff.2 hℒp.1 - have hint : Integrable (X 0) ℙ := hℒp.integrable hp - have havg : ∀ (n : ℕ), - AEStronglyMeasurable (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) ℙ := by - intro n - exact AEStronglyMeasurable.const_smul (aestronglyMeasurable_sum _ fun i _ => hmeas i) _ + have hint : Integrable (X 0) μ := hℒp.integrable hp + have havg (n : ℕ) : + AEStronglyMeasurable (fun ω => (n : ℝ) ⁻¹ • (∑ i ∈ range n, X i ω)) μ := + AEStronglyMeasurable.const_smul (aestronglyMeasurable_sum _ fun i _ => hmeas i) _ refine tendsto_Lp_finite_of_tendstoInMeasure hp hp' havg (memℒp_const _) ?_ (tendstoInMeasure_of_tendsto_ae havg (strong_law_ae _ hint hindep hident)) rw [(_ : (fun (n : ℕ) ω => (n : ℝ)⁻¹ • (∑ i ∈ range n, X i ω)) diff --git a/Mathlib/Probability/UniformOn.lean b/Mathlib/Probability/UniformOn.lean new file mode 100644 index 0000000000000..8b1de52a5055d --- /dev/null +++ b/Mathlib/Probability/UniformOn.lean @@ -0,0 +1,244 @@ +/- +Copyright (c) 2022 Kexing Ying. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kexing Ying, Bhavik Mehta +-/ +import Mathlib.Probability.ConditionalProbability +import Mathlib.MeasureTheory.Measure.Count + +/-! +# Classical probability + +The classical formulation of probability states that the probability of an event occurring in a +finite probability space is the ratio of that event to all possible events. +This notion can be expressed with measure theory using +the counting measure. In particular, given the sets `s` and `t`, we define the probability of `t` +occurring in `s` to be `|s|⁻¹ * |s ∩ t|`. With this definition, we recover the probability over +the entire sample space when `s = Set.univ`. + +Classical probability is often used in combinatorics and we prove some useful lemmas in this file +for that purpose. + +## Main definition + +* `ProbabilityTheory.uniformOn`: given a set `s`, `uniformOn s` is the counting measure + conditioned on `s`. This is a probability measure when `s` is finite and nonempty. + +## Notes + +The original aim of this file is to provide a measure theoretic method of describing the +probability an element of a set `s` satisfies some predicate `P`. Our current formulation still +allow us to describe this by abusing the definitional equality of sets and predicates by simply +writing `uniformOn s P`. We should avoid this however as none of the lemmas are written for +predicates. +-/ + + +noncomputable section + +open ProbabilityTheory + +open MeasureTheory MeasurableSpace + +namespace ProbabilityTheory + +variable {Ω : Type*} [MeasurableSpace Ω] + +/-- Given a set `s`, `uniformOn s` is the uniform measure on `s`, defined as the counting measure +conditioned by `s`. One should think of `uniformOn s t` as the proportion of `s` that is contained +in `t`. + +This is a probability measure when `s` is finite and nonempty and is given by +`ProbabilityTheory.uniformOn_isProbabilityMeasure`. -/ +def uniformOn (s : Set Ω) : Measure Ω := + Measure.count[|s] + +@[deprecated (since := "2024-10-09")] +noncomputable alias condCount := uniformOn + +instance {s : Set Ω} : IsZeroOrProbabilityMeasure (uniformOn s) := by + unfold uniformOn; infer_instance + +@[simp] +theorem uniformOn_empty_meas : (uniformOn ∅ : Measure Ω) = 0 := by simp [uniformOn] + +@[deprecated (since := "2024-10-09")] +alias condCount_empty_meas := uniformOn_empty_meas + +theorem uniformOn_empty {s : Set Ω} : uniformOn s ∅ = 0 := by simp + +@[deprecated (since := "2024-10-09")] +alias condCount_empty := uniformOn_empty + +theorem finite_of_uniformOn_ne_zero {s t : Set Ω} (h : uniformOn s t ≠ 0) : s.Finite := by + by_contra hs' + simp [uniformOn, cond, Measure.count_apply_infinite hs'] at h + +@[deprecated (since := "2024-10-09")] +alias finite_of_condCount_ne_zero := finite_of_uniformOn_ne_zero + +theorem uniformOn_univ [Fintype Ω] {s : Set Ω} : + uniformOn Set.univ s = Measure.count s / Fintype.card Ω := by + rw [uniformOn, cond_apply _ MeasurableSet.univ, ← ENNReal.div_eq_inv_mul, Set.univ_inter] + congr + rw [← Finset.coe_univ, Measure.count_apply, Finset.univ.tsum_subtype' fun _ => (1 : ENNReal)] + · simp [Finset.card_univ] + · exact (@Finset.coe_univ Ω _).symm ▸ MeasurableSet.univ + +@[deprecated (since := "2024-10-09")] +alias condCount_univ := uniformOn_univ + +variable [MeasurableSingletonClass Ω] + +theorem uniformOn_isProbabilityMeasure {s : Set Ω} (hs : s.Finite) (hs' : s.Nonempty) : + IsProbabilityMeasure (uniformOn s) := by + apply cond_isProbabilityMeasure_of_finite + · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h + · exact (Measure.count_apply_lt_top.2 hs).ne + +@[deprecated (since := "2024-10-09")] +alias condCount_isProbabilityMeasure := uniformOn_isProbabilityMeasure + +theorem uniformOn_singleton (ω : Ω) (t : Set Ω) [Decidable (ω ∈ t)] : + uniformOn {ω} t = if ω ∈ t then 1 else 0 := by + rw [uniformOn, cond_apply _ (measurableSet_singleton ω), Measure.count_singleton, inv_one, + one_mul] + split_ifs + · rw [(by simpa : ({ω} : Set Ω) ∩ t = {ω}), Measure.count_singleton] + · rw [(by simpa : ({ω} : Set Ω) ∩ t = ∅), Measure.count_empty] + +@[deprecated (since := "2024-10-09")] +alias condCount_singleton := uniformOn_singleton + +variable {s t u : Set Ω} + +theorem uniformOn_inter_self (hs : s.Finite) : uniformOn s (s ∩ t) = uniformOn s t := by + rw [uniformOn, cond_inter_self _ hs.measurableSet] + +@[deprecated (since := "2024-10-09")] +alias condCount_inter_self := uniformOn_inter_self + +theorem uniformOn_self (hs : s.Finite) (hs' : s.Nonempty) : uniformOn s s = 1 := by + rw [uniformOn, cond_apply _ hs.measurableSet, Set.inter_self, ENNReal.inv_mul_cancel] + · exact fun h => hs'.ne_empty <| Measure.empty_of_count_eq_zero h + · exact (Measure.count_apply_lt_top.2 hs).ne + +@[deprecated (since := "2024-10-09")] +alias condCount_self := uniformOn_self + +theorem uniformOn_eq_one_of (hs : s.Finite) (hs' : s.Nonempty) (ht : s ⊆ t) : + uniformOn s t = 1 := by + haveI := uniformOn_isProbabilityMeasure hs hs' + refine eq_of_le_of_not_lt prob_le_one ?_ + rw [not_lt, ← uniformOn_self hs hs'] + exact measure_mono ht + +@[deprecated (since := "2024-10-09")] +alias condCount_eq_one_of := uniformOn_eq_one_of + +theorem pred_true_of_uniformOn_eq_one (h : uniformOn s t = 1) : s ⊆ t := by + have hsf := finite_of_uniformOn_ne_zero (by rw [h]; exact one_ne_zero) + rw [uniformOn, cond_apply _ hsf.measurableSet, mul_comm] at h + replace h := ENNReal.eq_inv_of_mul_eq_one_left h + rw [inv_inv, Measure.count_apply_finite _ hsf, Measure.count_apply_finite _ (hsf.inter_of_left _), + Nat.cast_inj] at h + suffices s ∩ t = s by exact this ▸ fun x hx => hx.2 + rw [← @Set.Finite.toFinset_inj _ _ _ (hsf.inter_of_left _) hsf] + exact Finset.eq_of_subset_of_card_le (Set.Finite.toFinset_mono s.inter_subset_left) h.ge + +@[deprecated (since := "2024-10-09")] +alias pred_true_of_condCount_eq_one := pred_true_of_uniformOn_eq_one + +theorem uniformOn_eq_zero_iff (hs : s.Finite) : uniformOn s t = 0 ↔ s ∩ t = ∅ := by + simp [uniformOn, cond_apply _ hs.measurableSet, Measure.count_apply_eq_top, Set.not_infinite.2 hs, + Measure.count_apply_finite _ (hs.inter_of_left _)] + +@[deprecated (since := "2024-10-09")] +alias condCount_eq_zero_iff := uniformOn_eq_zero_iff + +theorem uniformOn_of_univ (hs : s.Finite) (hs' : s.Nonempty) : uniformOn s Set.univ = 1 := + uniformOn_eq_one_of hs hs' s.subset_univ + +@[deprecated (since := "2024-10-09")] +alias condCount_of_univ := uniformOn_of_univ + +theorem uniformOn_inter (hs : s.Finite) : + uniformOn s (t ∩ u) = uniformOn (s ∩ t) u * uniformOn s t := by + by_cases hst : s ∩ t = ∅ + · rw [hst, uniformOn_empty_meas, Measure.coe_zero, Pi.zero_apply, zero_mul, + uniformOn_eq_zero_iff hs, ← Set.inter_assoc, hst, Set.empty_inter] + rw [uniformOn, uniformOn, cond_apply _ hs.measurableSet, cond_apply _ hs.measurableSet, + cond_apply _ (hs.inter_of_left _).measurableSet, mul_comm _ (Measure.count (s ∩ t)), + ← mul_assoc, mul_comm _ (Measure.count (s ∩ t)), ← mul_assoc, ENNReal.mul_inv_cancel, one_mul, + mul_comm, Set.inter_assoc] + · rwa [← Measure.count_eq_zero_iff] at hst + · exact (Measure.count_apply_lt_top.2 <| hs.inter_of_left _).ne + +@[deprecated (since := "2024-10-09")] +alias condCount_inter := uniformOn_inter + +theorem uniformOn_inter' (hs : s.Finite) : + uniformOn s (t ∩ u) = uniformOn (s ∩ u) t * uniformOn s u := by + rw [← Set.inter_comm] + exact uniformOn_inter hs + +@[deprecated (since := "2024-10-09")] +alias condCount_inter' := uniformOn_inter' + +theorem uniformOn_union (hs : s.Finite) (htu : Disjoint t u) : + uniformOn s (t ∪ u) = uniformOn s t + uniformOn s u := by + rw [uniformOn, cond_apply _ hs.measurableSet, cond_apply _ hs.measurableSet, + cond_apply _ hs.measurableSet, Set.inter_union_distrib_left, measure_union, mul_add] + exacts [htu.mono inf_le_right inf_le_right, (hs.inter_of_left _).measurableSet] + +@[deprecated (since := "2024-10-09")] +alias condCount_union := uniformOn_union + +theorem uniformOn_compl (t : Set Ω) (hs : s.Finite) (hs' : s.Nonempty) : + uniformOn s t + uniformOn s tᶜ = 1 := by + rw [← uniformOn_union hs disjoint_compl_right, Set.union_compl_self, + (uniformOn_isProbabilityMeasure hs hs').measure_univ] + +@[deprecated (since := "2024-10-09")] +alias condCount_compl := uniformOn_compl + +theorem uniformOn_disjoint_union (hs : s.Finite) (ht : t.Finite) (hst : Disjoint s t) : + uniformOn s u * uniformOn (s ∪ t) s + uniformOn t u * uniformOn (s ∪ t) t = + uniformOn (s ∪ t) u := by + rcases s.eq_empty_or_nonempty with (rfl | hs') <;> rcases t.eq_empty_or_nonempty with (rfl | ht') + · simp + · simp [uniformOn_self ht ht'] + · simp [uniformOn_self hs hs'] + rw [uniformOn, uniformOn, uniformOn, cond_apply _ hs.measurableSet, + cond_apply _ ht.measurableSet, cond_apply _ (hs.union ht).measurableSet, + cond_apply _ (hs.union ht).measurableSet, cond_apply _ (hs.union ht).measurableSet] + conv_lhs => + rw [Set.union_inter_cancel_left, Set.union_inter_cancel_right, + mul_comm (Measure.count (s ∪ t))⁻¹, mul_comm (Measure.count (s ∪ t))⁻¹, ← mul_assoc, + ← mul_assoc, mul_comm _ (Measure.count s), mul_comm _ (Measure.count t), ← mul_assoc, + ← mul_assoc] + rw [ENNReal.mul_inv_cancel, ENNReal.mul_inv_cancel, one_mul, one_mul, ← add_mul, ← measure_union, + Set.union_inter_distrib_right, mul_comm] + exacts [hst.mono inf_le_left inf_le_left, (ht.inter_of_left _).measurableSet, + Measure.count_ne_zero ht', (Measure.count_apply_lt_top.2 ht).ne, Measure.count_ne_zero hs', + (Measure.count_apply_lt_top.2 hs).ne] + +@[deprecated (since := "2024-10-09")] +alias condCount_disjoint_union := uniformOn_disjoint_union + +/-- A version of the law of total probability for counting probabilities. -/ +theorem uniformOn_add_compl_eq (u t : Set Ω) (hs : s.Finite) : + uniformOn (s ∩ u) t * uniformOn s u + uniformOn (s ∩ uᶜ) t * uniformOn s uᶜ = + uniformOn s t := by + -- Porting note: The original proof used `conv_rhs`. However, that tactic timed out. + have : uniformOn s t = (uniformOn (s ∩ u) t * uniformOn (s ∩ u ∪ s ∩ uᶜ) (s ∩ u) + + uniformOn (s ∩ uᶜ) t * uniformOn (s ∩ u ∪ s ∩ uᶜ) (s ∩ uᶜ)) := by + rw [uniformOn_disjoint_union (hs.inter_of_left _) (hs.inter_of_left _) + (disjoint_compl_right.mono inf_le_right inf_le_right), Set.inter_union_compl] + rw [this] + simp [uniformOn_inter_self hs] + +@[deprecated (since := "2024-10-09")] +alias condCount_add_compl_eq := uniformOn_add_compl_eq + +end ProbabilityTheory diff --git a/Mathlib/RepresentationTheory/Action/Monoidal.lean b/Mathlib/RepresentationTheory/Action/Monoidal.lean index e9ebdc2e143b1..a31d4f9f7196f 100644 --- a/Mathlib/RepresentationTheory/Action/Monoidal.lean +++ b/Mathlib/RepresentationTheory/Action/Monoidal.lean @@ -245,7 +245,7 @@ noncomputable def leftRegularTensorIso (G : Type u) [Group G] (X : Action (Type dsimp -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [leftRegular_ρ_apply] - erw [map_mul] + rw [map_mul] rfl } hom_inv_id := by apply Hom.ext diff --git a/Mathlib/RepresentationTheory/Character.lean b/Mathlib/RepresentationTheory/Character.lean index e40c61bfaf1ea..b68c19284a62c 100644 --- a/Mathlib/RepresentationTheory/Character.lean +++ b/Mathlib/RepresentationTheory/Character.lean @@ -32,7 +32,7 @@ noncomputable section universe u -open CategoryTheory LinearMap CategoryTheory.MonoidalCategory Representation FiniteDimensional +open CategoryTheory LinearMap CategoryTheory.MonoidalCategory Representation Module variable {k : Type u} [Field k] @@ -51,7 +51,7 @@ theorem char_mul_comm (V : FDRep k G) (g : G) (h : G) : V.character (h * g) = V.character (g * h) := by simp only [trace_mul_comm, character, map_mul] @[simp] -theorem char_one (V : FDRep k G) : V.character 1 = FiniteDimensional.finrank k V := by +theorem char_one (V : FDRep k G) : V.character 1 = Module.finrank k V := by simp only [character, map_one, trace_one] /-- The character is multiplicative under the tensor product. -/ @@ -89,7 +89,7 @@ variable [Fintype G] [Invertible (Fintype.card G : k)] theorem average_char_eq_finrank_invariants (V : FDRep k G) : ⅟ (Fintype.card G : k) • ∑ g : G, V.character g = finrank k (invariants V.ρ) := by - erw [← (isProj_averageMap V.ρ).trace] -- Porting note: Changed `rw` to `erw` + rw [← (isProj_averageMap V.ρ).trace] simp [character, GroupAlgebra.average, _root_.map_sum] end Group diff --git a/Mathlib/RepresentationTheory/FDRep.lean b/Mathlib/RepresentationTheory/FDRep.lean index b19b49f0e400b..1f3f8535f0114 100644 --- a/Mathlib/RepresentationTheory/FDRep.lean +++ b/Mathlib/RepresentationTheory/FDRep.lean @@ -114,7 +114,7 @@ example : MonoidalPreadditive (FDRep k G) := by infer_instance example : MonoidalLinear k (FDRep k G) := by infer_instance -open FiniteDimensional +open Module open scoped Classical diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean b/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean index d12b7df3e9055..3d60e4b43bfb4 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Basic.lean @@ -146,8 +146,7 @@ and the homogeneous `linearYonedaObjResolution`. -/ -- https://github.com/leanprover-community/mathlib4/issues/5164 change d n A f g = diagonalHomEquiv (n + 1) A ((resolution k G).d (n + 1) n ≫ (diagonalHomEquiv n A).symm f) g - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [diagonalHomEquiv_apply, Action.comp_hom, ModuleCat.comp_def, LinearMap.comp_apply, + rw [diagonalHomEquiv_apply, Action.comp_hom, ModuleCat.comp_def, LinearMap.comp_apply, resolution.d_eq] erw [resolution.d_of (Fin.partialProd g)] simp only [map_sum, ← Finsupp.smul_single_one _ ((-1 : k) ^ _)] diff --git a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean index fbe67ec9e3438..f8101f22d3a29 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/LowDegree.lean @@ -2,7 +2,6 @@ Copyright (c) 2023 Amelia Livingston. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Amelia Livingston, Joël Riou - -/ import Mathlib.Algebra.Homology.ShortComplex.ModuleCat import Mathlib.RepresentationTheory.GroupCohomology.Basic @@ -146,7 +145,7 @@ theorem dZero_comp_eq : dZero A ∘ₗ (zeroCochainsLequiv A) = oneCochainsLequiv A ∘ₗ (inhomogeneousCochains A).d 0 1 := by ext x y show A.ρ y (x default) - x default = _ + ({0} : Finset _).sum _ - simp_rw [Fin.coe_fin_one, zero_add, pow_one, neg_smul, one_smul, + simp_rw [Fin.val_eq_zero, zero_add, pow_one, neg_smul, one_smul, Finset.sum_singleton, sub_eq_add_neg] rcongr i <;> exact Fin.elim0 i @@ -202,9 +201,9 @@ theorem dOne_comp_dZero : dOne A ∘ₗ dZero A = 0 := by rfl theorem dTwo_comp_dOne : dTwo A ∘ₗ dOne A = 0 := by - show ModuleCat.ofHom (dOne A) ≫ ModuleCat.ofHom (dTwo A) = _ - have h1 : _ ≫ ModuleCat.ofHom (dOne A) = _ ≫ _ := congr_arg ModuleCat.ofHom (dOne_comp_eq A) - have h2 : _ ≫ ModuleCat.ofHom (dTwo A) = _ ≫ _ := congr_arg ModuleCat.ofHom (dTwo_comp_eq A) + show ModuleCat.asHom (dOne A) ≫ ModuleCat.asHom (dTwo A) = _ + have h1 : _ ≫ ModuleCat.asHom (dOne A) = _ ≫ _ := congr_arg ModuleCat.asHom (dOne_comp_eq A) + have h2 : _ ≫ ModuleCat.asHom (dTwo A) = _ ≫ _ := congr_arg ModuleCat.asHom (dTwo_comp_eq A) simp only [← LinearEquiv.toModuleIso_hom] at h1 h2 simp only [(Iso.eq_inv_comp _).2 h2, (Iso.eq_inv_comp _).2 h1, Category.assoc, Iso.hom_inv_id_assoc, HomologicalComplex.d_comp_d_assoc, zero_comp, comp_zero] @@ -716,7 +715,7 @@ lemma shortComplexH0_exact : (shortComplexH0 A).Exact := by `(inhomogeneousCochains A).d 0 1` of the complex of inhomogeneous cochains of `A`. -/ @[simps! hom_left hom_right inv_left inv_right] def dZeroArrowIso : Arrow.mk ((inhomogeneousCochains A).d 0 1) ≅ - Arrow.mk (ModuleCat.ofHom (dZero A)) := + Arrow.mk (ModuleCat.asHom (dZero A)) := Arrow.isoMk (zeroCochainsLequiv A).toModuleIso (oneCochainsLequiv A).toModuleIso (dZero_comp_eq A) @@ -764,7 +763,7 @@ def isoOneCocycles : cocycles A 1 ≅ ModuleCat.of k (oneCocycles A) := cyclesMapIso (shortComplexH1Iso A) ≪≫ (shortComplexH1 A).moduleCatCyclesIso lemma isoOneCocycles_hom_comp_subtype : - (isoOneCocycles A).hom ≫ ModuleCat.ofHom (oneCocycles A).subtype = + (isoOneCocycles A).hom ≫ ModuleCat.asHom (oneCocycles A).subtype = iCocycles A 1 ≫ (oneCochainsLequiv A).toModuleIso.hom := by dsimp [isoOneCocycles] rw [Category.assoc, Category.assoc] @@ -774,7 +773,7 @@ lemma isoOneCocycles_hom_comp_subtype : lemma toCocycles_comp_isoOneCocycles_hom : toCocycles A 0 1 ≫ (isoOneCocycles A).hom = (zeroCochainsLequiv A).toModuleIso.hom ≫ - ModuleCat.ofHom (shortComplexH1 A).moduleCatToCycles := by + ModuleCat.asHom (shortComplexH1 A).moduleCatToCycles := by simp [isoOneCocycles] rfl @@ -812,7 +811,7 @@ def isoTwoCocycles : cocycles A 2 ≅ ModuleCat.of k (twoCocycles A) := cyclesMapIso (shortComplexH2Iso A) ≪≫ (shortComplexH2 A).moduleCatCyclesIso lemma isoTwoCocycles_hom_comp_subtype : - (isoTwoCocycles A).hom ≫ ModuleCat.ofHom (twoCocycles A).subtype = + (isoTwoCocycles A).hom ≫ ModuleCat.asHom (twoCocycles A).subtype = iCocycles A 2 ≫ (twoCochainsLequiv A).toModuleIso.hom := by dsimp [isoTwoCocycles] rw [Category.assoc, Category.assoc] @@ -822,7 +821,7 @@ lemma isoTwoCocycles_hom_comp_subtype : lemma toCocycles_comp_isoTwoCocycles_hom : toCocycles A 1 2 ≫ (isoTwoCocycles A).hom = (oneCochainsLequiv A).toModuleIso.hom ≫ - ModuleCat.ofHom (shortComplexH2 A).moduleCatToCycles := by + ModuleCat.asHom (shortComplexH2 A).moduleCatToCycles := by simp [isoTwoCocycles] rfl diff --git a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean index b7e92987380e6..9d4c8627a8198 100644 --- a/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean +++ b/Mathlib/RepresentationTheory/GroupCohomology/Resolution.lean @@ -221,14 +221,11 @@ theorem diagonalSucc_inv_single_left (g : G) (f : Gⁿ →₀ k) (r : k) : diagonalSucc_inv_single_single, hx, Finsupp.sum_single_index, mul_comm b, zero_mul, single_zero] -/ · rw [TensorProduct.tmul_zero, map_zero] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [map_zero] + rw [map_zero] · intro _ _ _ _ _ hx - rw [TensorProduct.tmul_add, map_add]; erw [map_add, hx] + rw [TensorProduct.tmul_add, map_add, map_add, hx] simp_rw [lift_apply, smul_single, smul_eq_mul] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [diagonalSucc_inv_single_single] - rw [sum_single_index, mul_comm] + rw [diagonalSucc_inv_single_single, sum_single_index, mul_comm] rw [zero_mul, single_zero] theorem diagonalSucc_inv_single_right (g : G →₀ k) (f : Gⁿ) (r : k) : @@ -240,15 +237,11 @@ theorem diagonalSucc_inv_single_right (g : G →₀ k) (f : Gⁿ) (r : k) : · intro a b x ha hb hx simp only [lift_apply, smul_single', map_add, hx, diagonalSucc_inv_single_single, TensorProduct.add_tmul, Finsupp.sum_single_index, zero_mul, single_zero] -/ - · rw [TensorProduct.zero_tmul, map_zero] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [map_zero] + · rw [TensorProduct.zero_tmul, map_zero, map_zero] · intro _ _ _ _ _ hx - rw [TensorProduct.add_tmul, map_add]; erw [map_add, hx] + rw [TensorProduct.add_tmul, map_add, map_add, hx] simp_rw [lift_apply, smul_single'] - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [diagonalSucc_inv_single_single] - rw [sum_single_index] + rw [diagonalSucc_inv_single_single, sum_single_index] rw [zero_mul, single_zero] end Rep @@ -266,8 +259,7 @@ def ofMulActionBasisAux : (ofMulAction k G (Fin (n + 1) → G)).asModule := { (Rep.equivalenceModuleMonoidAlgebra.1.mapIso (diagonalSucc k G n).symm).toLinearEquiv with map_smul' := fun r x => by - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [RingHom.id_apply, LinearEquiv.toFun_eq_coe, ← LinearEquiv.map_smul] + rw [RingHom.id_apply, LinearEquiv.toFun_eq_coe, ← LinearEquiv.map_smul] congr 1 /- Porting note (#11039): broken proof was refine' x.induction_on _ (fun x y => _) fun y z hy hz => _ @@ -357,21 +349,23 @@ theorem diagonalHomEquiv_symm_apply (f : (Fin n → G) → A) (x : Fin (n + 1) Category.comp_id, Action.comp_hom, MonoidalClosed.linearHomEquivComm_symm_hom] -- Porting note: This is a sure sign that coercions for morphisms in `ModuleCat` -- are still not set up properly. - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [ModuleCat.coe_comp] + rw [ModuleCat.coe_comp] simp only [ModuleCat.coe_comp, Function.comp_apply] -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [diagonalSucc_hom_single] - erw [TensorProduct.uncurry_apply, Finsupp.lift_apply, Finsupp.sum_single_index] - · simp only [one_smul] - erw [Representation.linHom_apply] - simp only [LinearMap.comp_apply, MonoidHom.one_apply, LinearMap.one_apply] - erw [Finsupp.llift_apply] - rw [Finsupp.lift_apply] - erw [Finsupp.sum_single_index] - · rw [one_smul] + -- The prototype linter that checks if `erw` could be replaced with `rw` would time out + -- if it replaces the next `erw`s with `rw`s. So we focus down on the relevant part. + conv_lhs => + erw [TensorProduct.uncurry_apply, Finsupp.lift_apply, Finsupp.sum_single_index] + · simp only [one_smul] + erw [Representation.linHom_apply] + simp only [LinearMap.comp_apply, MonoidHom.one_apply, LinearMap.one_apply] + erw [Finsupp.llift_apply] + rw [Finsupp.lift_apply] + erw [Finsupp.sum_single_index] + · rw [one_smul] + · rw [zero_smul] · rw [zero_smul] - · rw [zero_smul] /-- Auxiliary lemma for defining group cohomology, used to show that the isomorphism `diagonalHomEquiv` commutes with the differentials in two complexes which compute diff --git a/Mathlib/RepresentationTheory/Rep.lean b/Mathlib/RepresentationTheory/Rep.lean index 223f8229607a1..0c233f3d57f27 100644 --- a/Mathlib/RepresentationTheory/Rep.lean +++ b/Mathlib/RepresentationTheory/Rep.lean @@ -332,7 +332,7 @@ variable [Group G] (A B C : Rep k G) protected def ihom (A : Rep k G) : Rep k G ⥤ Rep k G where obj B := Rep.of (Representation.linHom A.ρ B.ρ) map := fun {X} {Y} f => - { hom := ModuleCat.ofHom (LinearMap.llcomp k _ _ _ f.hom) + { hom := ModuleCat.asHom (LinearMap.llcomp k _ _ _ f.hom) comm := fun g => LinearMap.ext fun x => LinearMap.ext fun y => by show f.hom (X.ρ g _) = _ simp only [hom_comm_apply]; rfl } @@ -371,7 +371,7 @@ def homEquiv (A B C : Rep k G) : (A ⊗ B ⟶ C) ≃ (B ⟶ (Rep.ihom A).obj C) Rep.ihom_obj_ρ_apply, LinearMap.comp_apply, LinearMap.comp_apply] --, ρ_inv_self_apply (A := C)] dsimp - erw [ρ_inv_self_apply] + rw [ρ_inv_self_apply] rfl} left_inv f := Action.Hom.ext (TensorProduct.ext' fun _ _ => rfl) right_inv f := by ext; rfl @@ -569,7 +569,7 @@ theorem unit_iso_comm (V : Rep k G) (g : G) (x : V) : /- Porting note: rest of broken proof was simp only [AddEquiv.apply_eq_iff_eq, AddEquiv.apply_symm_apply, Representation.asModuleEquiv_symm_map_rho, Representation.ofModule_asModule_act] -/ - erw [Representation.asModuleEquiv_symm_map_rho] + rw [Representation.asModuleEquiv_symm_map_rho] rfl /-- Auxiliary definition for `equivalenceModuleMonoidAlgebra`. -/ diff --git a/Mathlib/RingTheory/AdicCompletion/Algebra.lean b/Mathlib/RingTheory/AdicCompletion/Algebra.lean index 4a2de3765231a..f9ab3648fed20 100644 --- a/Mathlib/RingTheory/AdicCompletion/Algebra.lean +++ b/Mathlib/RingTheory/AdicCompletion/Algebra.lean @@ -200,7 +200,7 @@ instance : SMul (R ⧸ (I • ⊤ : Ideal R)) (M ⧸ (I • ⊤ : Submodule R M) Quotient.liftOn r (· • x) fun b₁ b₂ (h : Setoid.Rel _ b₁ b₂) ↦ by refine Quotient.inductionOn' x (fun x ↦ ?_) have h : b₁ - b₂ ∈ (I : Submodule R R) := by - rwa [show I = I • ⊤ by simp, ← Submodule.quotientRel_r_def] + rwa [show I = I • ⊤ by simp, ← Submodule.quotientRel_def] rw [← sub_eq_zero, ← sub_smul, Submodule.Quotient.mk''_eq_mk, ← Submodule.Quotient.mk_smul, Submodule.Quotient.mk_eq_zero] exact Submodule.smul_mem_smul h mem_top diff --git a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean index afc24e101812b..1c4dfed5cf15a 100644 --- a/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean +++ b/Mathlib/RingTheory/AdicCompletion/AsTensorProduct.lean @@ -241,17 +241,17 @@ private instance : AddCommGroup (AdicCompletion I R ⊗[R] (LinearMap.ker f)) := private def firstRow : ComposableArrows (ModuleCat (AdicCompletion I R)) 4 := ComposableArrows.mk₄ - (ModuleCat.ofHom <| lTensorKerIncl I M f) - (ModuleCat.ofHom <| lTensorf I M f) - (ModuleCat.ofHom (0 : AdicCompletion I R ⊗[R] M →ₗ[AdicCompletion I R] PUnit)) - (ModuleCat.ofHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) + (ModuleCat.asHom <| lTensorKerIncl I M f) + (ModuleCat.asHom <| lTensorf I M f) + (ModuleCat.asHom (0 : AdicCompletion I R ⊗[R] M →ₗ[AdicCompletion I R] PUnit)) + (ModuleCat.asHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) private def secondRow : ComposableArrows (ModuleCat (AdicCompletion I R)) 4 := ComposableArrows.mk₄ - (ModuleCat.ofHom (map I <| (LinearMap.ker f).subtype)) - (ModuleCat.ofHom (map I f)) - (ModuleCat.ofHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) - (ModuleCat.ofHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) + (ModuleCat.asHom (map I <| (LinearMap.ker f).subtype)) + (ModuleCat.asHom (map I f)) + (ModuleCat.asHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) + (ModuleCat.asHom (0 : _ →ₗ[AdicCompletion I R] PUnit)) include hf @@ -282,25 +282,25 @@ private lemma secondRow_exact [Fintype ι] [IsNoetherianRing R] : (secondRow I M /- The compatible vertical maps between the first and the second row. -/ private def firstRowToSecondRow : firstRow I M f ⟶ secondRow I M f := ComposableArrows.homMk₄ - (ModuleCat.ofHom (ofTensorProduct I (LinearMap.ker f))) - (ModuleCat.ofHom (ofTensorProduct I (ι → R))) - (ModuleCat.ofHom (ofTensorProduct I M)) - (ModuleCat.ofHom 0) - (ModuleCat.ofHom 0) + (ModuleCat.asHom (ofTensorProduct I (LinearMap.ker f))) + (ModuleCat.asHom (ofTensorProduct I (ι → R))) + (ModuleCat.asHom (ofTensorProduct I M)) + (ModuleCat.asHom 0) + (ModuleCat.asHom 0) (ofTensorProduct_naturality I <| (LinearMap.ker f).subtype).symm (ofTensorProduct_naturality I f).symm rfl rfl private lemma ofTensorProduct_iso [Fintype ι] [IsNoetherianRing R] : - IsIso (ModuleCat.ofHom (ofTensorProduct I M)) := by + IsIso (ModuleCat.asHom (ofTensorProduct I M)) := by refine Abelian.isIso_of_epi_of_isIso_of_isIso_of_mono (firstRow_exact I M f hf) (secondRow_exact I M f hf) (firstRowToSecondRow I M f) ?_ ?_ ?_ ?_ · apply ConcreteCategory.epi_of_surjective exact ofTensorProduct_surjective_of_finite I (LinearMap.ker f) · apply (ConcreteCategory.isIso_iff_bijective _).mpr exact ofTensorProduct_bijective_of_pi_of_fintype I ι - · show IsIso (ModuleCat.ofHom 0) + · show IsIso (ModuleCat.asHom 0) apply Limits.isIso_of_isTerminal <;> exact Limits.IsZero.isTerminal (ModuleCat.isZero_of_subsingleton _) · apply ConcreteCategory.mono_of_injective @@ -310,9 +310,9 @@ private lemma ofTensorProduct_iso [Fintype ι] [IsNoetherianRing R] : private lemma ofTensorProduct_bijective_of_map_from_fin [Fintype ι] [IsNoetherianRing R] : Function.Bijective (ofTensorProduct I M) := by - have : IsIso (ModuleCat.ofHom (ofTensorProduct I M)) := + have : IsIso (ModuleCat.asHom (ofTensorProduct I M)) := ofTensorProduct_iso I M f hf - exact ConcreteCategory.bijective_of_isIso (ModuleCat.ofHom (ofTensorProduct I M)) + exact ConcreteCategory.bijective_of_isIso (ModuleCat.asHom (ofTensorProduct I M)) end diff --git a/Mathlib/RingTheory/AdicCompletion/Functoriality.lean b/Mathlib/RingTheory/AdicCompletion/Functoriality.lean index 671d719a25adf..03b236a454123 100644 --- a/Mathlib/RingTheory/AdicCompletion/Functoriality.lean +++ b/Mathlib/RingTheory/AdicCompletion/Functoriality.lean @@ -145,7 +145,7 @@ theorem map_ext {N} {f g : AdicCompletion I M → N} f (AdicCompletion.mk I M a) = g (AdicCompletion.mk I M a)) : f = g := by ext x - apply induction_on I M x (fun a ↦ h a) + apply induction_on I M x h /-- Equality of linear maps out of an adic completion can be checked on Cauchy sequences. -/ @[ext] @@ -154,7 +154,7 @@ theorem map_ext' {f g : AdicCompletion I M →ₗ[AdicCompletion I R] T} f (AdicCompletion.mk I M a) = g (AdicCompletion.mk I M a)) : f = g := by ext x - apply induction_on I M x (fun a ↦ h a) + apply induction_on I M x h /-- Equality of linear maps out of an adic completion can be checked on Cauchy sequences. -/ @[ext] diff --git a/Mathlib/RingTheory/AdjoinRoot.lean b/Mathlib/RingTheory/AdjoinRoot.lean index 7532a1f66cbdf..bba7f1e3e7457 100644 --- a/Mathlib/RingTheory/AdjoinRoot.lean +++ b/Mathlib/RingTheory/AdjoinRoot.lean @@ -353,11 +353,11 @@ noncomputable instance instField [Fact (Irreducible f)] : Field (AdjoinRoot f) w ratCast_def q := by rw [← map_natCast (of f), ← map_intCast (of f), ← map_div₀, ← Rat.cast_def]; rfl nnqsmul_def q x := - AdjoinRoot.induction_on (C := fun y ↦ q • y = (of f) q * y) x fun p ↦ by + AdjoinRoot.induction_on f (C := fun y ↦ q • y = (of f) q * y) x fun p ↦ by simp only [smul_mk, of, RingHom.comp_apply, ← (mk f).map_mul, Polynomial.nnqsmul_eq_C_mul] qsmul_def q x := -- Porting note: I gave the explicit motive and changed `rw` to `simp`. - AdjoinRoot.induction_on (C := fun y ↦ q • y = (of f) q * y) x fun p ↦ by + AdjoinRoot.induction_on f (C := fun y ↦ q • y = (of f) q * y) x fun p ↦ by simp only [smul_mk, of, RingHom.comp_apply, ← (mk f).map_mul, Polynomial.qsmul_eq_C_mul] theorem coe_injective (h : degree f ≠ 0) : Function.Injective ((↑) : K → AdjoinRoot f) := diff --git a/Mathlib/RingTheory/Algebraic.lean b/Mathlib/RingTheory/Algebraic.lean index 2f80a41c0e3cb..20fba6c16cb72 100644 --- a/Mathlib/RingTheory/Algebraic.lean +++ b/Mathlib/RingTheory/Algebraic.lean @@ -5,6 +5,7 @@ Authors: Johan Commelin -/ import Mathlib.RingTheory.IntegralClosure.IsIntegralClosure.Basic import Mathlib.RingTheory.Polynomial.IntegralNormalization +import Mathlib.RingTheory.LocalRing.Basic /-! # Algebraic elements and algebraic extensions @@ -47,11 +48,11 @@ def Subalgebra.IsAlgebraic (S : Subalgebra R A) : Prop := variable (R A) /-- An algebra is algebraic if all its elements are algebraic. -/ -protected class Algebra.IsAlgebraic : Prop := +protected class Algebra.IsAlgebraic : Prop where isAlgebraic : ∀ x : A, IsAlgebraic R x /-- An algebra is transcendental if some element is transcendental. -/ -protected class Algebra.Transcendental : Prop := +protected class Algebra.Transcendental : Prop where transcendental : ∃ x : A, Transcendental R x variable {R A} diff --git a/Mathlib/RingTheory/Artinian.lean b/Mathlib/RingTheory/Artinian.lean index 60965f6c689e4..9e43f7cbc62b9 100644 --- a/Mathlib/RingTheory/Artinian.lean +++ b/Mathlib/RingTheory/Artinian.lean @@ -91,22 +91,33 @@ theorem isArtinian_of_surjective (f : M →ₗ[R] P) (hf : Function.Surjective f show A.comap f < B.comap f from Submodule.comap_strictMono_of_surjective hf hAB) (InvImage.wf (Submodule.comap f) IsWellFounded.wf)⟩ +instance isArtinian_of_quotient_of_artinian + (N : Submodule R M) [IsArtinian R M] : IsArtinian R (M ⧸ N) := + isArtinian_of_surjective M (Submodule.mkQ N) (Submodule.Quotient.mk_surjective N) + variable {M} theorem isArtinian_of_linearEquiv (f : M ≃ₗ[R] P) [IsArtinian R M] : IsArtinian R P := isArtinian_of_surjective _ f.toLinearMap f.toEquiv.surjective theorem isArtinian_of_range_eq_ker [IsArtinian R M] [IsArtinian R P] (f : M →ₗ[R] N) (g : N →ₗ[R] P) - (hf : Function.Injective f) (hg : Function.Surjective g) (h : LinearMap.range f = LinearMap.ker g) : IsArtinian R N := - wellFounded_lt_exact_sequence (LinearMap.range f) (Submodule.map f) - (Submodule.comap f) (Submodule.comap g) (Submodule.map g) (Submodule.gciMapComap hf) - (Submodule.giMapComap hg) - (by simp [Submodule.map_comap_eq, inf_comm]) (by simp [Submodule.comap_map_eq, h]) + wellFounded_lt_exact_sequence (LinearMap.range f) (Submodule.map (f.ker.liftQ f le_rfl)) + (Submodule.comap (f.ker.liftQ f le_rfl)) + (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) + (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) + (Submodule.giMapComap g.surjective_rangeRestrict) + (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) + (by simp [Submodule.comap_map_eq, h]) + +theorem isArtinian_iff_submodule_quotient (S : Submodule R P) : + IsArtinian R P ↔ IsArtinian R S ∧ IsArtinian R (P ⧸ S) := by + refine ⟨fun h ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ + apply isArtinian_of_range_eq_ker S.subtype S.mkQ + rw [Submodule.ker_mkQ, Submodule.range_subtype] instance isArtinian_prod [IsArtinian R M] [IsArtinian R P] : IsArtinian R (M × P) := - isArtinian_of_range_eq_ker (LinearMap.inl R M P) (LinearMap.snd R M P) LinearMap.inl_injective - LinearMap.snd_surjective (LinearMap.range_inl R M P) + isArtinian_of_range_eq_ker (LinearMap.inl R M P) (LinearMap.snd R M P) (LinearMap.range_inl R M P) instance (priority := 100) isArtinian_of_finite [Finite M] : IsArtinian R M := ⟨Finite.wellFounded_of_trans_of_irrefl _⟩ @@ -115,17 +126,12 @@ instance (priority := 100) isArtinian_of_finite [Finite M] : IsArtinian R M := -- attribute [local elab_as_elim] Finite.induction_empty_option instance isArtinian_pi {R ι : Type*} [Finite ι] : - ∀ {M : ι → Type*} [Ring R] [∀ i, AddCommGroup (M i)], - ∀ [∀ i, Module R (M i)], ∀ [∀ i, IsArtinian R (M i)], IsArtinian R (∀ i, M i) := by + ∀ {M : ι → Type*} [Ring R] [∀ i, AddCommGroup (M i)] + [∀ i, Module R (M i)] [∀ i, IsArtinian R (M i)], IsArtinian R (∀ i, M i) := by apply Finite.induction_empty_option _ _ _ ι - · intro α β e hα M _ _ _ _ - have := @hα - exact isArtinian_of_linearEquiv (LinearEquiv.piCongrLeft R M e) - · intro M _ _ _ _ - infer_instance - · intro α _ ih M _ _ _ _ - have := @ih - exact isArtinian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm + · exact fun e h ↦ isArtinian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) + · infer_instance + · exact fun ih ↦ isArtinian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm /-- A version of `isArtinian_pi` for non-dependent functions. We need this instance because sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to @@ -336,10 +342,6 @@ theorem Ring.isArtinian_of_zero_eq_one {R} [Ring R] (h01 : (0 : R) = 1) : IsArti theorem isArtinian_of_submodule_of_artinian (R M) [Ring R] [AddCommGroup M] [Module R M] (N : Submodule R M) (_ : IsArtinian R M) : IsArtinian R N := inferInstance -instance isArtinian_of_quotient_of_artinian (R) [Ring R] (M) [AddCommGroup M] [Module R M] - (N : Submodule R M) [IsArtinian R M] : IsArtinian R (M ⧸ N) := - isArtinian_of_surjective M (Submodule.mkQ N) (Submodule.Quotient.mk_surjective N) - /-- If `M / S / R` is a scalar tower, and `M / R` is Artinian, then `M / S` is also Artinian. -/ theorem isArtinian_of_tower (R) {S M} [CommRing R] [Ring S] [AddCommGroup M] [Algebra R S] [Module S M] [Module R M] [IsScalarTower R S M] (h : IsArtinian R M) : IsArtinian S M := @@ -520,7 +522,7 @@ instance [IsReduced R] : DecompositionMonoid (Polynomial R) := theorem isSemisimpleRing_of_isReduced [IsReduced R] : IsSemisimpleRing R := (equivPi R).symm.isSemisimpleRing -proof_wanted IsSemisimpleRing.isArtinianRing (R : Type*) [CommRing R] [IsSemisimpleRing R] : +proof_wanted IsSemisimpleRing.isArtinianRing (R : Type*) [Ring R] [IsSemisimpleRing R] : IsArtinianRing R end IsArtinianRing diff --git a/Mathlib/RingTheory/Binomial.lean b/Mathlib/RingTheory/Binomial.lean index 45bbba6501dad..659a95f8fb226 100644 --- a/Mathlib/RingTheory/Binomial.lean +++ b/Mathlib/RingTheory/Binomial.lean @@ -175,7 +175,7 @@ theorem ascPochhammer_smeval_cast (R : Type*) [Semiring R] {S : Type*} [NonAssoc simp only [← C_eq_natCast, smeval_C_mul, hn, Nat.cast_smul_eq_nsmul R n] simp only [nsmul_eq_mul, Nat.cast_id] -variable {R S : Type*} +variable {R : Type*} theorem ascPochhammer_smeval_eq_eval [Semiring R] (r : R) (n : ℕ) : (ascPochhammer ℕ n).smeval r = (ascPochhammer R n).eval r := by diff --git a/Mathlib/RingTheory/ChainOfDivisors.lean b/Mathlib/RingTheory/ChainOfDivisors.lean index 8266ff382b37f..684edca6086c9 100644 --- a/Mathlib/RingTheory/ChainOfDivisors.lean +++ b/Mathlib/RingTheory/ChainOfDivisors.lean @@ -332,7 +332,7 @@ theorem multiplicity_prime_eq_multiplicity_image_by_factor_orderIso {m p : Assoc end -variable [Unique Mˣ] [Unique Nˣ] +variable [Subsingleton Mˣ] [Subsingleton Nˣ] /-- The order isomorphism between the factors of `mk m` and the factors of `mk n` induced by a bijection between the factors of `m` and the factors of `n` that preserves `∣`. -/ diff --git a/Mathlib/RingTheory/Coalgebra/TensorProduct.lean b/Mathlib/RingTheory/Coalgebra/TensorProduct.lean index dcd8d8d13df2e..5226e76ef5d0e 100644 --- a/Mathlib/RingTheory/Coalgebra/TensorProduct.lean +++ b/Mathlib/RingTheory/Coalgebra/TensorProduct.lean @@ -58,7 +58,7 @@ noncomputable instance TensorProduct.instCoalgebra : Coalgebra R (M ⊗[R] N) := rw [CoalgebraCat.ofComonObjCoalgebraStruct_comul] simp [-Mon_.monMonoidalStruct_tensorObj_X, ModuleCat.MonoidalCategory.instMonoidalCategoryStruct_tensorHom, - ModuleCat.comp_def, ModuleCat.of, ModuleCat.ofHom, + ModuleCat.comp_def, ModuleCat.of, ModuleCat.asHom, ModuleCat.MonoidalCategory.tensor_μ_eq_tensorTensorTensorComm] } end diff --git a/Mathlib/RingTheory/Congruence/Basic.lean b/Mathlib/RingTheory/Congruence/Basic.lean index 1a9c8ef824451..131575077c37b 100644 --- a/Mathlib/RingTheory/Congruence/Basic.lean +++ b/Mathlib/RingTheory/Congruence/Basic.lean @@ -67,16 +67,15 @@ section Basic 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 (R → Prop) := - { coe := fun c => c.r, - coe_injective' := fun x y h => by - rcases x with ⟨⟨x, _⟩, _⟩ - rcases y with ⟨⟨y, _⟩, _⟩ - congr! - rw [Setoid.ext_iff,(show x.Rel = y.Rel from h)] - simp} +instance : FunLike (RingCon R) R (R → Prop) where + coe c := c.r + coe_injective' x y h := by + rcases x with ⟨⟨x, _⟩, _⟩ + rcases y with ⟨⟨y, _⟩, _⟩ + congr! + rw [Setoid.ext_iff, (show x.Rel = y.Rel from h)] + simp theorem rel_eq_coe : c.r = c := rfl @@ -126,6 +125,16 @@ theorem ext' {c d : RingCon R} (H : ⇑c = ⇑d) : c = d := DFunLike.coe_injecti theorem ext {c d : RingCon R} (H : ∀ x y, c x y ↔ d x y) : c = d := ext' <| by ext; apply H +/-- +Pulling back a `RingCon` across a ring homomorphism. +-/ +def comap {R R' F : Type*} [Add R] [Add R'] + [FunLike F R R'] [AddHomClass F R R'] [Mul R] [Mul R'] [MulHomClass F R R'] + (J : RingCon R') (f : F) : + RingCon R where + __ := J.toCon.comap f (map_mul f) + __ := J.toAddCon.comap f (map_add f) + end Basic section Quotient @@ -409,7 +418,6 @@ end Quotient The API in this section is copied from `Mathlib/GroupTheory/Congruence.lean` -/ - section Lattice variable [Add R] [Mul R] diff --git a/Mathlib/RingTheory/DedekindDomain/Basic.lean b/Mathlib/RingTheory/DedekindDomain/Basic.lean index 29a6df2a644da..aae1db626fae1 100644 --- a/Mathlib/RingTheory/DedekindDomain/Basic.lean +++ b/Mathlib/RingTheory/DedekindDomain/Basic.lean @@ -49,7 +49,7 @@ variable (R A K : Type*) [CommRing R] [CommRing A] [Field K] open scoped nonZeroDivisors Polynomial /-- A ring `R` has Krull dimension at most one if all nonzero prime ideals are maximal. -/ -class Ring.DimensionLEOne : Prop := +class Ring.DimensionLEOne : Prop where (maximalOfPrime : ∀ {p : Ideal R}, p ≠ ⊥ → p.IsPrime → p.IsMaximal) open Ideal Ring @@ -122,7 +122,6 @@ use `isDedekindDomain_iff` to prove `IsDedekindDomain` for a given `fraction_map This is the default implementation, but there are equivalent definitions, `IsDedekindDomainDvr` and `IsDedekindDomainInv`. -TODO: Prove that these are actually equivalent definitions. -/ class IsDedekindDomain extends IsDomain A, IsDedekindRing A : Prop diff --git a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean index 395fe6de21fed..088395622dc68 100644 --- a/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean +++ b/Mathlib/RingTheory/DedekindDomain/FiniteAdeleRing.lean @@ -110,7 +110,7 @@ def Coe.addMonoidHom : AddMonoidHom (R_hat R K) (K_hat R K) where refine funext fun v => ?_ simp only [coe_apply, Pi.add_apply, Subring.coe_add] -- Porting note: added - erw [Pi.add_apply, Pi.add_apply, Subring.coe_add] + rw [Pi.add_apply, Pi.add_apply, Subring.coe_add] /-- The inclusion of `R_hat` in `K_hat` as a ring homomorphism. -/ @[simps] @@ -123,7 +123,7 @@ def Coe.ringHom : RingHom (R_hat R K) (K_hat R K) := refine funext fun p => ?_ simp only [Pi.mul_apply, Subring.coe_mul] -- Porting note: added - erw [Pi.mul_apply, Pi.mul_apply, Subring.coe_mul] } + rw [Pi.mul_apply, Pi.mul_apply, Subring.coe_mul] } end FiniteIntegralAdeles @@ -337,7 +337,7 @@ instance : IsScalarTower R K (FiniteAdeleRing R K) := IsScalarTower.of_algebraMap_eq' rfl instance : Coe (FiniteAdeleRing R K) (K_hat R K) where - coe := fun x ↦ x.1 + coe x := x.1 @[ext] lemma ext {a₁ a₂ : FiniteAdeleRing R K} (h : (a₁ : K_hat R K) = a₂) : a₁ = a₂ := diff --git a/Mathlib/RingTheory/DedekindDomain/Ideal.lean b/Mathlib/RingTheory/DedekindDomain/Ideal.lean index 788005c401860..426d939612987 100644 --- a/Mathlib/RingTheory/DedekindDomain/Ideal.lean +++ b/Mathlib/RingTheory/DedekindDomain/Ideal.lean @@ -892,7 +892,7 @@ theorem sup_eq_prod_inf_factors [DecidableEq (Ideal T)] (hI : I ≠ ⊥) (hJ : J · exact ne_bot_of_le_ne_bot hI le_sup_left · exact this -theorem irreducible_pow_sup [DecidableEq (Ideal T)](hI : I ≠ ⊥) (hJ : Irreducible J) (n : ℕ) : +theorem irreducible_pow_sup [DecidableEq (Ideal T)] (hI : I ≠ ⊥) (hJ : Irreducible J) (n : ℕ) : J ^ n ⊔ I = J ^ min ((normalizedFactors I).count J) n := by rw [sup_eq_prod_inf_factors (pow_ne_zero n hJ.ne_zero) hI, min_comm, normalizedFactors_of_irreducible_pow hJ, normalize_eq J, replicate_inter, prod_replicate] @@ -916,6 +916,17 @@ theorem irreducible_pow_sup_of_ge [DecidableRel fun (x : Ideal T) x_1 ↦ x ∣ multiplicity_eq_count_normalizedFactors hJ hI, normalize_eq J] · rwa [multiplicity_eq_count_normalizedFactors hJ hI, PartENat.coe_le_coe, normalize_eq J] at hn +theorem Ideal.eq_prime_pow_mul_coprime [DecidableEq (Ideal T)] {I : Ideal T} (hI : I ≠ ⊥) + (P : Ideal T) [hpm : P.IsMaximal] : + ∃ Q : Ideal T, P ⊔ Q = ⊤ ∧ I = P ^ (Multiset.count P (normalizedFactors I)) * Q := by + use (filter (¬ P = ·) (normalizedFactors I)).prod + constructor + · refine P.sup_multiset_prod_eq_top (fun p hpi ↦ ?_) + have hp : Prime p := prime_of_normalized_factor p (filter_subset _ (normalizedFactors I) hpi) + exact hpm.coprime_of_ne ((isPrime_of_prime hp).isMaximal hp.ne_zero) (of_mem_filter hpi) + · nth_rw 1 [← prod_normalizedFactors_eq_self hI, ← filter_add_not (P = ·) (normalizedFactors I)] + rw [prod_add, pow_count] + end IsDedekindDomain /-! @@ -1180,26 +1191,6 @@ theorem Ideal.le_mul_of_no_prime_factors {I J K : Ideal R} (UniqueFactorizationMonoid.dvd_of_dvd_mul_right_of_no_prime_factors (b := K) hJ0 ?_ hJ) exact fun hPJ hPK => mt Ideal.isPrime_of_prime (coprime _ hPJ hPK) -theorem Ideal.le_of_pow_le_prime {I P : Ideal R} [hP : P.IsPrime] {n : ℕ} (h : I ^ n ≤ P) : - I ≤ P := by - by_cases hP0 : P = ⊥ - · simp only [hP0, le_bot_iff] at h ⊢ - exact pow_eq_zero h - rw [← Ideal.dvd_iff_le] at h ⊢ - exact ((Ideal.prime_iff_isPrime hP0).mpr hP).dvd_of_dvd_pow h - -theorem Ideal.pow_le_prime_iff {I P : Ideal R} [_hP : P.IsPrime] {n : ℕ} (hn : n ≠ 0) : - I ^ n ≤ P ↔ I ≤ P := - ⟨Ideal.le_of_pow_le_prime, fun h => _root_.trans (Ideal.pow_le_self hn) h⟩ - -theorem Ideal.prod_le_prime {ι : Type*} {s : Finset ι} {f : ι → Ideal R} {P : Ideal R} - [hP : P.IsPrime] : ∏ i ∈ s, f i ≤ P ↔ ∃ i ∈ s, f i ≤ P := by - by_cases hP0 : P = ⊥ - · simp only [hP0, le_bot_iff] - rw [← Ideal.zero_eq_bot, Finset.prod_eq_zero_iff] - simp only [← Ideal.dvd_iff_le] - exact ((Ideal.prime_iff_isPrime hP0).mpr hP).dvd_finset_prod_iff _ - /-- The intersection of distinct prime powers in a Dedekind domain is the product of these prime powers. -/ theorem IsDedekindDomain.inf_prime_pow_eq_prod {ι : Type*} (s : Finset ι) (f : ι → Ideal R) @@ -1217,15 +1208,13 @@ theorem IsDedekindDomain.inf_prime_pow_eq_prod {ι : Type*} (s : Finset ι) (f : rw [Finset.inf_insert, Finset.prod_insert ha, ih] refine le_antisymm (Ideal.le_mul_of_no_prime_factors ?_ inf_le_left inf_le_right) Ideal.mul_le_inf intro P hPa hPs hPp - obtain ⟨b, hb, hPb⟩ := Ideal.prod_le_prime.mp hPs + obtain ⟨b, hb, hPb⟩ := hPp.prod_le.mp hPs haveI := Ideal.isPrime_of_prime (prime a (Finset.mem_insert_self a s)) haveI := Ideal.isPrime_of_prime (prime b (Finset.mem_insert_of_mem hb)) refine coprime a (Finset.mem_insert_self a s) b (Finset.mem_insert_of_mem hb) ?_ ?_ · exact (ne_of_mem_of_not_mem hb ha).symm - · refine ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp - (Ideal.le_of_pow_le_prime hPa)).trans - ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp - (Ideal.le_of_pow_le_prime hPb)).symm + · refine ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp (hPp.le_of_pow_le hPa)).trans + ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp (hPp.le_of_pow_le hPb)).symm · exact (prime a (Finset.mem_insert_self a s)).ne_zero · exact (prime b (Finset.mem_insert_of_mem hb)).ne_zero @@ -1240,17 +1229,13 @@ noncomputable def IsDedekindDomain.quotientEquivPiOfProdEq {ι : Type*} [Fintype simp only [← prod_eq, Finset.inf_eq_iInf, Finset.mem_univ, ciInf_pos, ← IsDedekindDomain.inf_prime_pow_eq_prod _ _ _ (fun i _ => prime i) (coprime.set_pairwise _)])).trans <| - Ideal.quotientInfRingEquivPiQuotient _ fun i j hij => Ideal.coprime_of_no_prime_ge (by + Ideal.quotientInfRingEquivPiQuotient _ fun i j hij => Ideal.coprime_of_no_prime_ge <| by intro P hPi hPj hPp haveI := Ideal.isPrime_of_prime (prime i) haveI := Ideal.isPrime_of_prime (prime j) - refine coprime hij ?_ - refine ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp - (Ideal.le_of_pow_le_prime hPi)).trans - ((Ring.DimensionLeOne.prime_le_prime_iff_eq ?_).mp - (Ideal.le_of_pow_le_prime hPj)).symm - · exact (prime i).ne_zero - · exact (prime j).ne_zero) + exact coprime hij <| ((Ring.DimensionLeOne.prime_le_prime_iff_eq (prime i).ne_zero).mp + (hPp.le_of_pow_le hPi)).trans <| Eq.symm <| + (Ring.DimensionLeOne.prime_le_prime_iff_eq (prime j).ne_zero).mp (hPp.le_of_pow_le hPj) open scoped Classical @@ -1267,7 +1252,7 @@ noncomputable def IsDedekindDomain.quotientEquivPiFactors {I : Ideal R} (hI : I (factors I).toFinset.prod_coe_sort fun P => P ^ (factors I).count P _ = ((factors I).map fun P => P).prod := (Finset.prod_multiset_map_count (factors I) id).symm _ = (factors I).prod := by rw [Multiset.map_id'] - _ = I := (@associated_iff_eq (Ideal R) _ Ideal.uniqueUnits _ _).mp (factors_prod hI) + _ = I := associated_iff_eq.mp (factors_prod hI) ) @[simp] diff --git a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean index f8aba734476d2..86796148fbcf3 100644 --- a/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean +++ b/Mathlib/RingTheory/DedekindDomain/IntegralClosure.lean @@ -198,13 +198,13 @@ theorem IsIntegralClosure.module_free [NoZeroSMulDivisors A L] [IsPrincipalIdeal and `L` has no zero smul divisors by `A`, the `A`-rank of the integral closure `C` of `A` in `L` is equal to the `K`-rank of `L`. -/ theorem IsIntegralClosure.rank [IsPrincipalIdealRing A] [NoZeroSMulDivisors A L] : - FiniteDimensional.finrank A C = FiniteDimensional.finrank K L := by + Module.finrank A C = Module.finrank K L := by haveI : Module.Free A C := IsIntegralClosure.module_free A K L C haveI : IsNoetherian A C := IsIntegralClosure.isNoetherian A K L C haveI : IsLocalization (Algebra.algebraMapSubmonoid C A⁰) L := IsIntegralClosure.isLocalization A K L C let b := Basis.localizationLocalization K A⁰ L (Module.Free.chooseBasis A C) - rw [FiniteDimensional.finrank_eq_card_chooseBasisIndex, FiniteDimensional.finrank_eq_card_basis b] + rw [Module.finrank_eq_card_chooseBasisIndex, Module.finrank_eq_card_basis b] variable {A K} diff --git a/Mathlib/RingTheory/Derivation/MapCoeffs.lean b/Mathlib/RingTheory/Derivation/MapCoeffs.lean index 01ab5a9134a4a..ec1b10e49cb27 100644 --- a/Mathlib/RingTheory/Derivation/MapCoeffs.lean +++ b/Mathlib/RingTheory/Derivation/MapCoeffs.lean @@ -22,7 +22,7 @@ open Polynomial Module namespace Derivation variable {R A M : Type*} [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] - [Module A M] [Module R M] (d : Derivation R A M) (a : A) + [Module A M] [Module R M] (d : Derivation R A M) /-- The `R`-derivation from `A[X]` to `M[X]` which applies the derivative to each diff --git a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean index b3171e5b848cd..5957f090f0b89 100644 --- a/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean +++ b/Mathlib/RingTheory/DiscreteValuationRing/TFAE.lean @@ -29,7 +29,7 @@ variable (R : Type*) [CommRing R] (K : Type*) [Field K] [Algebra R K] [IsFractio open scoped Multiplicative -open LocalRing FiniteDimensional +open LocalRing Module theorem exists_maximalIdeal_pow_eq_of_principal [IsNoetherianRing R] [LocalRing R] [IsDomain R] (h' : (maximalIdeal R).IsPrincipal) (I : Ideal R) (hI : I ≠ ⊥) : diff --git a/Mathlib/RingTheory/Discriminant.lean b/Mathlib/RingTheory/Discriminant.lean index f6285f4b7aa27..f3faffa03b668 100644 --- a/Mathlib/RingTheory/Discriminant.lean +++ b/Mathlib/RingTheory/Discriminant.lean @@ -50,7 +50,7 @@ universe u v w z open scoped Matrix -open Matrix FiniteDimensional Fintype Polynomial Finset IntermediateField +open Matrix Module Fintype Polynomial Finset IntermediateField namespace Algebra @@ -190,7 +190,7 @@ theorem discr_powerBasis_eq_prod'' [Algebra.IsSeparable K L] (e : Fin pb.dim ≃ have h₂ : 2 ∣ pb.dim * (pb.dim - 1) := pb.dim.even_mul_pred_self.two_dvd have hne : ((2 : ℕ) : ℚ) ≠ 0 := by simp have hle : 1 ≤ pb.dim := by - rw [← hn, Nat.one_le_iff_ne_zero, ← zero_lt_iff, FiniteDimensional.finrank_pos_iff] + rw [← hn, Nat.one_le_iff_ne_zero, ← zero_lt_iff, Module.finrank_pos_iff] infer_instance rw [hn, Nat.cast_div h₂ hne, Nat.cast_mul, Nat.cast_sub hle] field_simp diff --git a/Mathlib/RingTheory/DualNumber.lean b/Mathlib/RingTheory/DualNumber.lean new file mode 100644 index 0000000000000..cf0ac64836b99 --- /dev/null +++ b/Mathlib/RingTheory/DualNumber.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2024 Yakov Pechersky. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yakov Pechersky +-/ +import Mathlib.Algebra.DualNumber +import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic + +/-! +# Algebraic properties of dual numbers + +## Main results + +* `DualNumber.instLocalRing`: The dual numbers over a field `K` form a local ring. +* `DualNumber.instPrincipalIdealRing`: The dual numbers over a field `K` form a principal ideal + ring. + +-/ + +namespace TrivSqZeroExt + +variable {R M : Type*} + +section Semiring +variable [Semiring R] [AddCommMonoid M] [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] + +lemma isNilpotent_iff_isNilpotent_fst {x : TrivSqZeroExt R M} : + IsNilpotent x ↔ IsNilpotent x.fst := by + constructor <;> rintro ⟨n, hn⟩ + · refine ⟨n, ?_⟩ + rw [← fst_pow, hn, fst_zero] + · refine ⟨n * 2, ?_⟩ + rw [pow_mul] + ext + · rw [fst_pow, fst_pow, hn, zero_pow two_ne_zero, fst_zero] + · rw [pow_two, snd_mul, fst_pow, hn, MulOpposite.op_zero, zero_smul, zero_smul, zero_add, + snd_zero] + +@[simp] +lemma isNilpotent_inl_iff (r : R) : IsNilpotent (.inl r : TrivSqZeroExt R M) ↔ IsNilpotent r := by + rw [isNilpotent_iff_isNilpotent_fst, fst_inl] + +@[simp] +lemma isNilpotent_inr (x : M) : IsNilpotent (.inr x : TrivSqZeroExt R M) := by + refine ⟨2, by simp [pow_two]⟩ + +end Semiring + +lemma isUnit_or_isNilpotent_of_isMaximal_isNilpotent [CommSemiring R] [AddCommGroup M] + [Module R M] [Module Rᵐᵒᵖ M] [IsCentralScalar R M] + (h : ∀ I : Ideal R, I.IsMaximal → IsNilpotent I) + (a : TrivSqZeroExt R M) : + IsUnit a ∨ IsNilpotent a := by + rw [isUnit_iff_isUnit_fst, isNilpotent_iff_isNilpotent_fst] + refine (em _).imp_right fun ha ↦ ?_ + obtain ⟨I, hI, haI⟩ := exists_max_ideal_of_mem_nonunits (mem_nonunits_iff.mpr ha) + refine (h _ hI).imp fun n hn ↦ ?_ + exact hn.le (Ideal.pow_mem_pow haI _) + +lemma isUnit_or_isNilpotent [DivisionSemiring R] [AddCommGroup M] + [Module R M] [Module Rᵐᵒᵖ M] [SMulCommClass R Rᵐᵒᵖ M] + (a : TrivSqZeroExt R M) : + IsUnit a ∨ IsNilpotent a := by + simp [isUnit_iff_isUnit_fst, isNilpotent_iff_isNilpotent_fst, em'] + +end TrivSqZeroExt + +namespace DualNumber +variable {R : Type*} + +lemma fst_eq_zero_iff_eps_dvd [Semiring R] {x : R[ε]} : + x.fst = 0 ↔ ε ∣ x := by + simp_rw [dvd_def, TrivSqZeroExt.ext_iff, TrivSqZeroExt.fst_mul, TrivSqZeroExt.snd_mul, + fst_eps, snd_eps, zero_mul, zero_smul, zero_add, MulOpposite.smul_eq_mul_unop, + MulOpposite.unop_op, one_mul, exists_and_left, iff_self_and] + intro + exact ⟨.inl x.snd, rfl⟩ + +lemma isNilpotent_eps [Semiring R] : + IsNilpotent (ε : R[ε]) := + TrivSqZeroExt.isNilpotent_inr 1 + +open TrivSqZeroExt + +lemma isNilpotent_iff_eps_dvd [DivisionSemiring R] {x : R[ε]} : + IsNilpotent x ↔ ε ∣ x := by + simp only [isNilpotent_iff_isNilpotent_fst, isNilpotent_iff_eq_zero, fst_eq_zero_iff_eps_dvd] + +section Field + +variable {K : Type*} + +instance [DivisionRing K] : LocalRing K[ε] where + isUnit_or_isUnit_of_add_one {a b} h := by + rw [add_comm, ← eq_sub_iff_add_eq] at h + rcases eq_or_ne (fst a) 0 with ha|ha <;> + simp [isUnit_iff_isUnit_fst, h, ha] + +lemma ideal_trichotomy [DivisionRing K] (I : Ideal K[ε]) : + I = ⊥ ∨ I = .span {ε} ∨ I = ⊤ := by + refine (eq_or_ne I ⊥).imp_right fun hb ↦ ?_ + refine (eq_or_ne I ⊤).symm.imp_left fun ht ↦ ?_ + have hd : ∀ x ∈ I, ε ∣ x := by + intro x hxI + rcases isUnit_or_isNilpotent x with hx|hx + · exact absurd (Ideal.eq_top_of_isUnit_mem _ hxI hx) ht + · rwa [← isNilpotent_iff_eps_dvd] + have hd' : ∀ x ∈ I, x ≠ 0 → ∃ r, ε = r * x := by + intro x hxI hx0 + obtain ⟨r, rfl⟩ := hd _ hxI + have : ε * r = (fst r) • ε := by ext <;> simp + rw [this] at hxI hx0 ⊢ + have hr : fst r ≠ 0 := by + contrapose! hx0 + simp [hx0] + refine ⟨r⁻¹, ?_⟩ + simp [TrivSqZeroExt.ext_iff, inv_mul_cancel₀ hr] + refine le_antisymm ?_ ?_ <;> intro x <;> + simp_rw [Ideal.mem_span_singleton', (commute_eps_right _).eq, eq_comm, ← dvd_def] + · intro hx + simp_rw [hd _ hx] + · intro hx + obtain ⟨p, rfl⟩ := hx + obtain ⟨y, hyI, hy0⟩ := Submodule.exists_mem_ne_zero_of_ne_bot hb + obtain ⟨r, hr⟩ := hd' _ hyI hy0 + rw [(commute_eps_left _).eq, hr, ← mul_assoc] + exact Ideal.mul_mem_left _ _ hyI + +lemma isMaximal_span_singleton_eps [DivisionRing K] : + (Ideal.span {ε} : Ideal K[ε]).IsMaximal := by + refine ⟨?_, fun I hI ↦ ?_⟩ + · simp [ne_eq, Ideal.eq_top_iff_one, Ideal.mem_span_singleton', TrivSqZeroExt.ext_iff] + · rcases ideal_trichotomy I with rfl|rfl|rfl <;> + first | simp at hI | simp + +lemma maximalIdeal_eq_span_singleton_eps [Field K] : + LocalRing.maximalIdeal K[ε] = Ideal.span {ε} := + (LocalRing.eq_maximalIdeal isMaximal_span_singleton_eps).symm + +instance [DivisionRing K] : IsPrincipalIdealRing K[ε] where + principal I := by + rcases ideal_trichotomy I with rfl|rfl|rfl + · exact bot_isPrincipal + · exact ⟨_, rfl⟩ + · exact top_isPrincipal + +lemma exists_mul_left_or_mul_right [DivisionRing K] (a b : K[ε]) : + ∃ c, a * c = b ∨ b * c = a := by + rcases isUnit_or_isNilpotent a with ha|ha + · lift a to K[ε]ˣ using ha + exact ⟨a⁻¹ * b, by simp⟩ + rcases isUnit_or_isNilpotent b with hb|hb + · lift b to K[ε]ˣ using hb + exact ⟨b⁻¹ * a, by simp⟩ + rw [isNilpotent_iff_eps_dvd] at ha hb + obtain ⟨x, rfl⟩ := ha + obtain ⟨y, rfl⟩ := hb + suffices ∃ c, fst x * fst c = fst y ∨ fst y * fst c = fst x by + simpa [TrivSqZeroExt.ext_iff] using this + rcases eq_or_ne (fst x) 0 with hx|hx + · refine ⟨ε, Or.inr ?_⟩ + simp [hx] + refine ⟨inl ((fst x)⁻¹ * fst y), ?_⟩ + simp [← inl_mul, ← mul_assoc, mul_inv_cancel₀ hx] + +end Field + +end DualNumber diff --git a/Mathlib/RingTheory/EisensteinCriterion.lean b/Mathlib/RingTheory/EisensteinCriterion.lean index 1fcc31f3e3076..4db4a640eef89 100644 --- a/Mathlib/RingTheory/EisensteinCriterion.lean +++ b/Mathlib/RingTheory/EisensteinCriterion.lean @@ -34,8 +34,7 @@ theorem map_eq_C_mul_X_pow_of_forall_coeff_mem {f : R[X]} {P : Ideal R} by_cases hf0 : f = 0 · simp [hf0] rcases lt_trichotomy (n : WithBot ℕ) (degree f) with (h | h | h) - · erw [coeff_map, eq_zero_iff_mem.2 (hfP n h), coeff_C_mul, coeff_X_pow, if_neg, - mul_zero] + · rw [coeff_map, eq_zero_iff_mem.2 (hfP n h), coeff_C_mul, coeff_X_pow, if_neg, mul_zero] rintro rfl exact not_lt_of_ge degree_le_natDegree h · have : natDegree f = n := natDegree_eq_of_degree_eq_some h.symm diff --git a/Mathlib/RingTheory/Etale/Basic.lean b/Mathlib/RingTheory/Etale/Basic.lean index 171f57f41c31c..70ab05f56b544 100644 --- a/Mathlib/RingTheory/Etale/Basic.lean +++ b/Mathlib/RingTheory/Etale/Basic.lean @@ -56,7 +56,6 @@ section variable {R : Type u} [CommSemiring R] variable {A : Type u} [Semiring A] [Algebra R A] -variable {B : Type u} [CommRing B] [Algebra R B] (I : Ideal B) theorem iff_unramified_and_smooth : FormallyEtale R A ↔ FormallyUnramified R A ∧ FormallySmooth R A := by diff --git a/Mathlib/RingTheory/FiniteLength.lean b/Mathlib/RingTheory/FiniteLength.lean new file mode 100644 index 0000000000000..d0305806bd193 --- /dev/null +++ b/Mathlib/RingTheory/FiniteLength.lean @@ -0,0 +1,78 @@ +/- +Copyright (c) 2024 Junyan Xu. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Junyan Xu +-/ +import Mathlib.Order.Atoms.Finite +import Mathlib.RingTheory.Artinian + +/-! +# Modules of finite length + +We define modules of finite length (`IsFiniteLength`) to be finite iterated extensions of +simple modules, and show that a module is of finite length iff it is both Noetherian and Artinian, +iff it admits a composition series. +We do not make `IsFiniteLength` a class, instead we use `[IsNoetherian R M] [IsArtinian R M]`. + +## Tag + +Finite length, Composition series +-/ + +universe u + +variable (R : Type*) [Ring R] + +/-- A module of finite length is either trivial or a simple extension of a module known +to be of finite length. -/ +inductive IsFiniteLength : ∀ (M : Type u) [AddCommGroup M] [Module R M], Prop + | of_subsingleton {M} [AddCommGroup M] [Module R M] [Subsingleton M] : IsFiniteLength M + | of_simple_quotient {M} [AddCommGroup M] [Module R M] {N : Submodule R M} + [IsSimpleModule R (M ⧸ N)] : IsFiniteLength N → IsFiniteLength M + +variable {R} {M N : Type*} [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +theorem LinearEquiv.isFiniteLength (e : M ≃ₗ[R] N) + (h : IsFiniteLength R M) : IsFiniteLength R N := by + induction' h with M _ _ _ M _ _ S _ _ ih generalizing N + · have := e.symm.toEquiv.subsingleton; exact .of_subsingleton + · have : IsSimpleModule R (N ⧸ Submodule.map (e : M →ₗ[R] N) S) := + IsSimpleModule.congr (Submodule.Quotient.equiv S _ e rfl).symm + exact .of_simple_quotient (ih <| e.submoduleMap S) + +variable (R M) in +theorem exists_compositionSeries_of_isNoetherian_isArtinian [IsNoetherian R M] [IsArtinian R M] : + ∃ s : CompositionSeries (Submodule R M), s.head = ⊥ ∧ s.last = ⊤ := by + obtain ⟨f, f0, n, hn⟩ := exists_covBy_seq_of_wellFoundedLT_wellFoundedGT (Submodule R M) + exact ⟨⟨n, fun i ↦ f i, fun i ↦ hn.2 i i.2⟩, f0.eq_bot, hn.1.eq_top⟩ + +theorem isFiniteLength_of_exists_compositionSeries + (h : ∃ s : CompositionSeries (Submodule R M), s.head = ⊥ ∧ s.last = ⊤) : + IsFiniteLength R M := + Submodule.topEquiv.isFiniteLength <| by + obtain ⟨s, s_head, s_last⟩ := h + rw [← s_last] + suffices ∀ i, IsFiniteLength R (s i) from this (Fin.last _) + intro i + induction' i using Fin.induction with i ih + · change IsFiniteLength R s.head; rw [s_head]; exact .of_subsingleton + let cov := s.step i + have := (covBy_iff_quot_is_simple cov.le).mp cov + have := ((s i.castSucc).comap (s i.succ).subtype).equivMapOfInjective + _ (Submodule.injective_subtype _) + rw [Submodule.map_comap_subtype, inf_of_le_right cov.le] at this + exact .of_simple_quotient (this.symm.isFiniteLength ih) + +theorem isFiniteLength_iff_isNoetherian_isArtinian : + IsFiniteLength R M ↔ IsNoetherian R M ∧ IsArtinian R M := + ⟨fun h ↦ h.rec (fun {M} _ _ _ ↦ ⟨inferInstance, inferInstance⟩) fun M _ _ {N} _ _ ⟨_, _⟩ ↦ + ⟨(isNoetherian_iff_submodule_quotient N).mpr ⟨‹_›, isNoetherian_iff'.mpr inferInstance⟩, + (isArtinian_iff_submodule_quotient N).mpr ⟨‹_›, inferInstance⟩⟩, + fun ⟨_, _⟩ ↦ isFiniteLength_of_exists_compositionSeries + (exists_compositionSeries_of_isNoetherian_isArtinian R M)⟩ + +theorem isFiniteLength_iff_exists_compositionSeries : + IsFiniteLength R M ↔ ∃ s : CompositionSeries (Submodule R M), s.head = ⊥ ∧ s.last = ⊤ := + ⟨fun h ↦ have ⟨_, _⟩ := isFiniteLength_iff_isNoetherian_isArtinian.mp h + exists_compositionSeries_of_isNoetherian_isArtinian R M, + isFiniteLength_of_exists_compositionSeries⟩ diff --git a/Mathlib/RingTheory/FinitePresentation.lean b/Mathlib/RingTheory/FinitePresentation.lean index dbdefa4bd0fa8..b5f8a9e4728c8 100644 --- a/Mathlib/RingTheory/FinitePresentation.lean +++ b/Mathlib/RingTheory/FinitePresentation.lean @@ -394,6 +394,7 @@ variable {A B C : Type*} [CommRing A] [CommRing B] [CommRing C] /-- A ring morphism `A →+* B` is of `RingHom.FinitePresentation` if `B` is finitely presented as `A`-algebra. -/ +@[algebraize] def FinitePresentation (f : A →+* B) : Prop := @Algebra.FinitePresentation A B _ _ f.toAlgebra @@ -414,11 +415,9 @@ theorem id : FinitePresentation (RingHom.id A) := variable {A} theorem comp_surjective {f : A →+* B} {g : B →+* C} (hf : f.FinitePresentation) (hg : Surjective g) - (hker : g.ker.FG) : (g.comp f).FinitePresentation := - letI := f.toAlgebra - letI := (g.comp f).toAlgebra - letI : Algebra.FinitePresentation A B := hf - Algebra.FinitePresentation.of_surjective + (hker : g.ker.FG) : (g.comp f).FinitePresentation := by + algebraize [f, g.comp f] + exact Algebra.FinitePresentation.of_surjective (f := { g with toFun := g @@ -434,28 +433,16 @@ theorem of_finiteType [IsNoetherianRing A] {f : A →+* B} : f.FiniteType ↔ f. @Algebra.FinitePresentation.of_finiteType A B _ _ f.toAlgebra _ theorem comp {g : B →+* C} {f : A →+* B} (hg : g.FinitePresentation) (hf : f.FinitePresentation) : - (g.comp f).FinitePresentation := + (g.comp f).FinitePresentation := by -- Porting note: specify `Algebra` instances to get `SMul` - letI ins1 := RingHom.toAlgebra f - letI ins2 := RingHom.toAlgebra g - letI ins3 := RingHom.toAlgebra (g.comp f) - letI ins4 : IsScalarTower A B C := - { smul_assoc := fun a b c => by simp [Algebra.smul_def, mul_assoc]; rfl } - letI : Algebra.FinitePresentation A B := hf - letI : Algebra.FinitePresentation B C := hg - Algebra.FinitePresentation.trans A B C + algebraize [f, g, g.comp f] + exact Algebra.FinitePresentation.trans A B C theorem of_comp_finiteType (f : A →+* B) {g : B →+* C} (hg : (g.comp f).FinitePresentation) - (hf : f.FiniteType) : g.FinitePresentation := + (hf : f.FiniteType) : g.FinitePresentation := by -- Porting note: need to specify some instances - letI ins1 := RingHom.toAlgebra f - letI ins2 := RingHom.toAlgebra g - letI ins3 := RingHom.toAlgebra (g.comp f) - letI ins4 : IsScalarTower A B C := - { smul_assoc := fun a b c => by simp [Algebra.smul_def, mul_assoc]; rfl } - letI : Algebra.FinitePresentation A C := hg - letI : Algebra.FiniteType A B := hf - Algebra.FinitePresentation.of_restrict_scalars_finitePresentation A B C + algebraize [f, g, g.comp f] + exact Algebra.FinitePresentation.of_restrict_scalars_finitePresentation A B C end FinitePresentation diff --git a/Mathlib/RingTheory/FiniteType.lean b/Mathlib/RingTheory/FiniteType.lean index b0366a10493a5..ed78e1a416de7 100644 --- a/Mathlib/RingTheory/FiniteType.lean +++ b/Mathlib/RingTheory/FiniteType.lean @@ -45,7 +45,7 @@ section Algebra -- see Note [lower instance priority] instance (priority := 100) finiteType {R : Type*} (A : Type*) [CommSemiring R] [Semiring A] - [Algebra R A] [hRA : Finite R A] : Algebra.FiniteType R A := + [Algebra R A] [hRA : Module.Finite R A] : Algebra.FiniteType R A := ⟨Subalgebra.fg_of_submodule_fg hRA.1⟩ end Algebra @@ -207,6 +207,7 @@ namespace RingHom variable {A B C : Type*} [CommRing A] [CommRing B] [CommRing C] /-- A ring morphism `A →+* B` is of `FiniteType` if `B` is finitely generated as `A`-algebra. -/ +@[algebraize] def FiniteType (f : A →+* B) : Prop := @Algebra.FiniteType A B _ _ f.toAlgebra @@ -228,8 +229,7 @@ variable {A} theorem comp_surjective {f : A →+* B} {g : B →+* C} (hf : f.FiniteType) (hg : Surjective g) : (g.comp f).FiniteType := by - let _ : Algebra A B := f.toAlgebra - let _ : Algebra A C := (g.comp f).toAlgebra + algebraize_only [f, g.comp f] exact Algebra.FiniteType.of_surjective hf { g with toFun := g @@ -242,15 +242,8 @@ theorem of_surjective (f : A →+* B) (hf : Surjective f) : f.FiniteType := by theorem comp {g : B →+* C} {f : A →+* B} (hg : g.FiniteType) (hf : f.FiniteType) : (g.comp f).FiniteType := by - let _ : Algebra A B := f.toAlgebra - let _ : Algebra A C := (g.comp f).toAlgebra - let _ : Algebra B C := g.toAlgebra - exact @Algebra.FiniteType.trans A B C _ _ _ f.toAlgebra (g.comp f).toAlgebra g.toAlgebra - ⟨by - intro a b c - simp [Algebra.smul_def, RingHom.map_mul, mul_assoc] - rfl⟩ - hf hg + algebraize_only [f, g, g.comp f] + exact Algebra.FiniteType.trans hf hg theorem of_finite {f : A →+* B} (hf : f.Finite) : f.FiniteType := @Module.Finite.finiteType _ _ _ _ f.toAlgebra hf @@ -259,11 +252,7 @@ alias _root_.RingHom.Finite.to_finiteType := of_finite theorem of_comp_finiteType {f : A →+* B} {g : B →+* C} (h : (g.comp f).FiniteType) : g.FiniteType := by - let _ := f.toAlgebra - let _ := g.toAlgebra - let _ := (g.comp f).toAlgebra - let _ : IsScalarTower A B C := RestrictScalars.isScalarTower A B C - let _ : Algebra.FiniteType A C := h + algebraize [f, g, g.comp f] exact Algebra.FiniteType.of_restrictScalars_finiteType A B C end FiniteType @@ -746,7 +735,7 @@ This is similar to `IsNoetherian.injective_of_surjective_endomorphism` but only commutative case, but does not use a Noetherian hypothesis. -/ @[deprecated OrzechProperty.injective_of_surjective_endomorphism (since := "2024-05-30")] theorem Module.Finite.injective_of_surjective_endomorphism {R : Type*} [CommRing R] {M : Type*} - [AddCommGroup M] [Module R M] [Finite R M] (f : M →ₗ[R] M) + [AddCommGroup M] [Module R M] [Module.Finite R M] (f : M →ₗ[R] M) (f_surj : Function.Surjective f) : Function.Injective f := OrzechProperty.injective_of_surjective_endomorphism f f_surj diff --git a/Mathlib/RingTheory/Finiteness.lean b/Mathlib/RingTheory/Finiteness.lean index b9e7cb2a2c070..0039e1437e417 100644 --- a/Mathlib/RingTheory/Finiteness.lean +++ b/Mathlib/RingTheory/Finiteness.lean @@ -11,6 +11,7 @@ import Mathlib.GroupTheory.Finiteness import Mathlib.RingTheory.Ideal.Maps import Mathlib.RingTheory.Nilpotent.Defs import Mathlib.LinearAlgebra.Basis.Cardinality +import Mathlib.Tactic.Algebraize /-! # Finiteness conditions in commutative algebra @@ -380,9 +381,7 @@ theorem fg_iff_compact (s : Submodule R M) : s.FG ↔ CompleteLattice.IsCompactE suffices u.sup id ≤ s from le_antisymm husup this rw [sSup', Finset.sup_id_eq_sSup] exact sSup_le_sSup huspan - -- Porting note: had to split this out of the `obtain` - have := Finset.subset_image_iff.mp huspan - obtain ⟨t, ⟨-, rfl⟩⟩ := this + obtain ⟨t, -, rfl⟩ := Finset.subset_set_image_iff.mp huspan 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⟩ @@ -501,7 +500,7 @@ section ModuleAndAlgebra variable (R A B M N : Type*) /-- A module over a semiring is `Finite` if it is finitely generated as a module. -/ -class Module.Finite [Semiring R] [AddCommMonoid M] [Module R M] : Prop where +protected class Module.Finite [Semiring R] [AddCommMonoid M] [Module R M] : Prop where out : (⊤ : Submodule R M).FG attribute [inherit_doc Module.Finite] Module.Finite.out @@ -511,7 +510,7 @@ namespace Module variable [Semiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] theorem finite_def {R M} [Semiring R] [AddCommMonoid M] [Module R M] : - Finite R M ↔ (⊤ : Submodule R M).FG := + Module.Finite R M ↔ (⊤ : Submodule R M).FG := ⟨fun h => h.1, fun h => ⟨h⟩⟩ namespace Finite @@ -529,46 +528,47 @@ theorem iff_addGroup_fg {G : Type*} [AddCommGroup G] : Module.Finite ℤ G ↔ A variable {R M N} /-- See also `Module.Finite.exists_fin'`. -/ -theorem exists_fin [Finite R M] : ∃ (n : ℕ) (s : Fin n → M), Submodule.span R (range s) = ⊤ := +lemma exists_fin [Module.Finite R M] : ∃ (n : ℕ) (s : Fin n → M), Submodule.span R (range s) = ⊤ := Submodule.fg_iff_exists_fin_generating_family.mp out variable (R M) in -lemma exists_fin' [Finite R M] : ∃ (n : ℕ) (f : (Fin n → R) →ₗ[R] M), Surjective f := by +lemma exists_fin' [Module.Finite R M] : ∃ (n : ℕ) (f : (Fin n → R) →ₗ[R] M), Surjective f := by have ⟨n, s, hs⟩ := exists_fin (R := R) (M := M) refine ⟨n, Basis.constr (Pi.basisFun R _) ℕ s, ?_⟩ rw [← LinearMap.range_eq_top, Basis.constr_range, hs] -theorem of_surjective [hM : Finite R M] (f : M →ₗ[R] N) (hf : Surjective f) : Finite R N := +theorem of_surjective [hM : Module.Finite R M] (f : M →ₗ[R] N) (hf : Surjective f) : + Module.Finite R N := ⟨by rw [← LinearMap.range_eq_top.2 hf, ← Submodule.map_top] exact hM.1.map f⟩ instance quotient (R) {A M} [Semiring R] [AddCommGroup M] [Ring A] [Module A M] [Module R M] - [SMul R A] [IsScalarTower R A M] [Finite R M] - (N : Submodule A M) : Finite R (M ⧸ N) := + [SMul R A] [IsScalarTower R A M] [Module.Finite R M] + (N : Submodule A M) : Module.Finite R (M ⧸ N) := Module.Finite.of_surjective (N.mkQ.restrictScalars R) N.mkQ_surjective /-- The range of a linear map from a finite module is finite. -/ -instance range {F : Type*} [FunLike F M N] [SemilinearMapClass F (RingHom.id R) M N] [Finite R M] - (f : F) : Finite R (LinearMap.range f) := +instance range {F : Type*} [FunLike F M N] [SemilinearMapClass F (RingHom.id R) M N] + [Module.Finite R M] (f : F) : Module.Finite R (LinearMap.range f) := of_surjective (SemilinearMapClass.semilinearMap f).rangeRestrict fun ⟨_, y, hy⟩ => ⟨y, Subtype.ext hy⟩ /-- Pushforwards of finite submodules are finite. -/ -instance map (p : Submodule R M) [Finite R p] (f : M →ₗ[R] N) : Finite R (p.map f) := +instance map (p : Submodule R M) [Module.Finite R p] (f : M →ₗ[R] N) : Module.Finite R (p.map f) := of_surjective (f.restrict fun _ => Submodule.mem_map_of_mem) fun ⟨_, _, hy, hy'⟩ => ⟨⟨_, hy⟩, Subtype.ext hy'⟩ variable (R) -instance self : Finite R R := +instance self : Module.Finite R R := ⟨⟨{1}, by simpa only [Finset.coe_singleton] using Ideal.span_singleton_one⟩⟩ variable (M) theorem of_restrictScalars_finite (R A M : Type*) [CommSemiring R] [Semiring A] [AddCommMonoid M] - [Module R M] [Module A M] [Algebra R A] [IsScalarTower R A M] [hM : Finite R M] : - Finite A M := by + [Module R M] [Module A M] [Algebra R A] [IsScalarTower R A M] [hM : Module.Finite R M] : + Module.Finite A M := by rw [finite_def, Submodule.fg_def] at hM ⊢ obtain ⟨S, hSfin, hSgen⟩ := hM refine ⟨S, hSfin, eq_top_iff.2 ?_⟩ @@ -578,24 +578,24 @@ theorem of_restrictScalars_finite (R A M : Type*) [CommSemiring R] [Semiring A] variable {R M} -instance prod [hM : Finite R M] [hN : Finite R N] : Finite R (M × N) := +instance prod [hM : Module.Finite R M] [hN : Module.Finite R N] : Module.Finite R (M × N) := ⟨by rw [← Submodule.prod_top] exact hM.1.prod hN.1⟩ instance pi {ι : Type*} {M : ι → Type*} [_root_.Finite ι] [∀ i, AddCommMonoid (M i)] - [∀ i, Module R (M i)] [h : ∀ i, Finite R (M i)] : Finite R (∀ i, M i) := + [∀ i, Module R (M i)] [h : ∀ i, Module.Finite R (M i)] : Module.Finite R (∀ i, M i) := ⟨by rw [← Submodule.pi_top] exact Submodule.fg_pi fun i => (h i).1⟩ -theorem equiv [Finite R M] (e : M ≃ₗ[R] N) : Finite R N := +theorem equiv [Module.Finite R M] (e : M ≃ₗ[R] N) : Module.Finite R N := of_surjective (e : M →ₗ[R] N) e.surjective -theorem equiv_iff (e : M ≃ₗ[R] N) : Finite R M ↔ Finite R N := +theorem equiv_iff (e : M ≃ₗ[R] N) : Module.Finite R M ↔ Module.Finite R N := ⟨fun _ ↦ equiv e, fun _ ↦ equiv e.symm⟩ -instance ulift [Finite R M] : Finite R (ULift M) := equiv ULift.moduleEquiv.symm +instance ulift [Module.Finite R M] : Module.Finite R (ULift M) := equiv ULift.moduleEquiv.symm theorem iff_fg {N : Submodule R M} : Module.Finite R N ↔ N.FG := Module.finite_def.trans (fg_top _) @@ -603,7 +603,7 @@ variable (R M) instance bot : Module.Finite R (⊥ : Submodule R M) := iff_fg.mpr fg_bot -instance top [Finite R M] : Module.Finite R (⊤ : Submodule R M) := iff_fg.mpr out +instance top [Module.Finite R M] : Module.Finite R (⊤ : Submodule R M) := iff_fg.mpr out variable {M} @@ -642,7 +642,7 @@ section Algebra 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 + ∀ [Module.Finite R A] [Module.Finite A M], Module.Finite R M | ⟨⟨s, hs⟩⟩, ⟨⟨t, ht⟩⟩ => ⟨Submodule.fg_def.2 ⟨Set.image2 (· • ·) (↑s : Set A) (↑t : Set M), @@ -760,6 +760,7 @@ namespace RingHom variable {A B C : Type*} [CommRing A] [CommRing B] [CommRing C] /-- A ring morphism `A →+* B` is `Finite` if `B` is finitely generated as `A`-module. -/ +@[algebraize Module.Finite] def Finite (f : A →+* B) : Prop := letI : Algebra A B := f.toAlgebra Module.Finite A B @@ -778,20 +779,11 @@ theorem of_surjective (f : A →+* B) (hf : Surjective f) : f.Finite := Module.Finite.of_surjective (Algebra.linearMap A B) hf theorem comp {g : B →+* C} {f : A →+* B} (hg : g.Finite) (hf : f.Finite) : (g.comp f).Finite := by - letI := f.toAlgebra - letI := g.toAlgebra - letI := (g.comp f).toAlgebra - letI : IsScalarTower A B C := RestrictScalars.isScalarTower A B C - letI : Module.Finite A B := hf - letI : Module.Finite B C := hg + algebraize [f, g, g.comp f] exact Module.Finite.trans B C theorem of_comp_finite {f : A →+* B} {g : B →+* C} (h : (g.comp f).Finite) : g.Finite := by - letI := f.toAlgebra - letI := g.toAlgebra - letI := (g.comp f).toAlgebra - letI : IsScalarTower A B C := RestrictScalars.isScalarTower A B C - letI : Module.Finite A C := h + algebraize [f, g, g.comp f] exact Module.Finite.of_restrictScalars_finite A B C end Finite diff --git a/Mathlib/RingTheory/Flat/Algebra.lean b/Mathlib/RingTheory/Flat/Algebra.lean index 0aa4d1079abf0..53bc49e2510e5 100644 --- a/Mathlib/RingTheory/Flat/Algebra.lean +++ b/Mathlib/RingTheory/Flat/Algebra.lean @@ -60,6 +60,7 @@ theorem isBaseChange [Algebra R S] (R' : Type w) (S' : Type t) [CommRing R'] [Co end Algebra.Flat /-- A ring homomorphism `f : R →+* S` is flat if `S` is flat as an `R` algebra. -/ +@[algebraize RingHom.Flat.out] class RingHom.Flat {R : Type u} {S : Type v} [CommRing R] [CommRing S] (f : R →+* S) : Prop where out : f.toAlgebra.Flat := by infer_instance @@ -75,11 +76,8 @@ variable {R : Type u} {S : Type v} {T : Type w} [CommRing R] [CommRing S] [CommR /-- Composition of flat ring homomorphisms is flat. -/ instance comp [RingHom.Flat f] [RingHom.Flat g] : RingHom.Flat (g.comp f) where - out := - letI : Algebra R S := f.toAlgebra - letI : Algebra S T := g.toAlgebra - letI : Algebra R T := (g.comp f).toAlgebra - letI : IsScalarTower R S T := IsScalarTower.of_algebraMap_eq (congrFun rfl) - Algebra.Flat.comp R S T + out := by + algebraize_only [f, g, g.comp f] + exact Algebra.Flat.comp R S T end RingHom.Flat diff --git a/Mathlib/RingTheory/Flat/Basic.lean b/Mathlib/RingTheory/Flat/Basic.lean index 7592d42a7c793..813b32f84d0ac 100644 --- a/Mathlib/RingTheory/Flat/Basic.lean +++ b/Mathlib/RingTheory/Flat/Basic.lean @@ -172,7 +172,7 @@ instance directSum (ι : Type v) (M : ι → Type w) [(i : ι) → AddCommGroup apply TensorProduct.ext' intro a m simp only [ρ, ψ, φ, η, η₁, coe_comp, LinearEquiv.coe_coe, Function.comp_apply, - directSumRight_symm_lof_tmul, rTensor_tmul, Submodule.coeSubtype, lid_tmul, map_smul] + directSumRight_symm_lof_tmul, rTensor_tmul, Submodule.coe_subtype, lid_tmul, map_smul] rw [DirectSum.component.of, DirectSum.component.of] by_cases h₂ : j = i · subst j; simp diff --git a/Mathlib/RingTheory/Flat/CategoryTheory.lean b/Mathlib/RingTheory/Flat/CategoryTheory.lean index ea7bc816d2f57..ea6d1442dad38 100644 --- a/Mathlib/RingTheory/Flat/CategoryTheory.lean +++ b/Mathlib/RingTheory/Flat/CategoryTheory.lean @@ -52,7 +52,7 @@ lemma iff_lTensor_preserves_shortComplex_exact : ⟨fun _ _ ↦ lTensor_shortComplex_exact _ _, fun H ↦ iff_lTensor_exact.2 <| fun _ _ _ _ _ _ _ _ _ f g h ↦ moduleCat_exact_iff_function_exact _ |>.1 <| - H (.mk (ModuleCat.ofHom f) (ModuleCat.ofHom g) + H (.mk (ModuleCat.asHom f) (ModuleCat.asHom g) (DFunLike.ext _ _ h.apply_apply_eq_zero)) (moduleCat_exact_iff_function_exact _ |>.2 h)⟩ @@ -62,7 +62,7 @@ lemma iff_rTensor_preserves_shortComplex_exact : ⟨fun _ _ ↦ rTensor_shortComplex_exact _ _, fun H ↦ iff_rTensor_exact.2 <| fun _ _ _ _ _ _ _ _ _ f g h ↦ moduleCat_exact_iff_function_exact _ |>.1 <| - H (.mk (ModuleCat.ofHom f) (ModuleCat.ofHom g) + H (.mk (ModuleCat.asHom f) (ModuleCat.asHom g) (DFunLike.ext _ _ h.apply_apply_eq_zero)) (moduleCat_exact_iff_function_exact _ |>.2 h)⟩ diff --git a/Mathlib/RingTheory/Flat/EquationalCriterion.lean b/Mathlib/RingTheory/Flat/EquationalCriterion.lean index e90cd0987d45c..763d9dc2c83db 100644 --- a/Mathlib/RingTheory/Flat/EquationalCriterion.lean +++ b/Mathlib/RingTheory/Flat/EquationalCriterion.lean @@ -120,8 +120,8 @@ theorem tfae_equational_criterion : List.TFAE [ ∀ {ι : Type u} [Fintype ι] {f : ι →₀ R} {x : (ι →₀ R) →ₗ[R] M}, x f = 0 → ∃ (κ : Type u) (_ : Fintype κ) (a : (ι →₀ R) →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0, - ∀ {N : Type u} [AddCommGroup N] [Module R N] [Free R N] [Finite R N] {f : N} {x : N →ₗ[R] M}, - x f = 0 → + ∀ {N : Type u} [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] {f : N} + {x : N →ₗ[R] M}, x f = 0 → ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0] := by classical @@ -243,8 +243,8 @@ Let $M$ be a flat module over a commutative ring $R$. Let $N$ be a finite free m let $f \in N$, and let $x \colon N \to M$ be a homomorphism such that $x(f) = 0$. Then there exist a finite index type $\kappa$ and module homomorphisms $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a(f) = 0$. -/ -theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type u} - [AddCommGroup N] [Module R N] [Free R N] [Finite R N] {f : N} {x : N →ₗ[R] M} (h : x f = 0) : +theorem exists_factorization_of_apply_eq_zero_of_free [Flat R M] {N : Type u} [AddCommGroup N] + [Module R N] [Free R N] [Module.Finite R N] {f : N} {x : N →ₗ[R] M} (h : x f = 0) : ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a f = 0 := by exact ((tfae_equational_criterion R M).out 0 5 rfl rfl).mp ‹Flat R M› h @@ -254,8 +254,8 @@ free, and let $f \colon K \to N$ and $x \colon N \to M$ be homomorphisms such th $x \circ f = 0$. Then there exist a finite index type $\kappa$ and module homomorphisms $a \colon N \to R^{\kappa}$ and $y \colon R^{\kappa} \to M$ such that $x = y \circ a$ and $a \circ f = 0$. -/ -theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} - [AddCommGroup K] [Module R K] [Finite R K] [AddCommGroup N] [Module R N] [Free R N] [Finite R N] +theorem exists_factorization_of_comp_eq_zero_of_free [Flat R M] {K N : Type u} [AddCommGroup K] + [Module R K] [Module.Finite R K] [AddCommGroup N] [Module R N] [Free R N] [Module.Finite R N] {f : K →ₗ[R] N} {x : N →ₗ[R] M} (h : x ∘ₗ f = 0) : ∃ (κ : Type u) (_ : Fintype κ) (a : N →ₗ[R] (κ →₀ R)) (y : (κ →₀ R) →ₗ[R] M), x = y ∘ₗ a ∧ a ∘ₗ f = 0 := by @@ -283,7 +283,7 @@ theorem exists_factorization_of_isFinitelyPresented [Flat R M] {P : Type u} [Add ∃ (κ : Type u) (_ : Fintype κ) (h₂ : P →ₗ[R] (κ →₀ R)) (h₃ : (κ →₀ R) →ₗ[R] M), h₁ = h₃ ∘ₗ h₂ := by obtain ⟨L, _, _, K, ϕ, _, _, hK⟩ := FinitePresentation.equiv_quotient R P - haveI : Finite R ↥K := Module.Finite.iff_fg.mpr hK + haveI : Module.Finite R ↥K := Module.Finite.iff_fg.mpr hK have : (h₁ ∘ₗ ϕ.symm ∘ₗ K.mkQ) ∘ₗ K.subtype = 0 := by simp_rw [comp_assoc, (LinearMap.exact_subtype_mkQ K).linearMap_comp_eq_zero, comp_zero] obtain ⟨κ, hκ, a, y, hay, ha⟩ := exists_factorization_of_comp_eq_zero_of_free this diff --git a/Mathlib/RingTheory/FractionalIdeal/Operations.lean b/Mathlib/RingTheory/FractionalIdeal/Operations.lean index 50c15f91c6b62..d6ab280bcde60 100644 --- a/Mathlib/RingTheory/FractionalIdeal/Operations.lean +++ b/Mathlib/RingTheory/FractionalIdeal/Operations.lean @@ -5,6 +5,7 @@ Authors: Anne Baanen, Filippo A. E. Nuccio -/ import Mathlib.RingTheory.FractionalIdeal.Basic import Mathlib.RingTheory.IntegralClosure.IsIntegral.Basic +import Mathlib.RingTheory.LocalRing.Basic /-! # More operations on fractional ideals diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean index dc2ec96afc47a..f434e98f774a3 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousIdeal.lean @@ -146,7 +146,7 @@ theorem Ideal.mul_homogeneous_element_mem_of_mem {I : Ideal A} (r x : A) (hx₁ obtain ⟨i, hi⟩ := hx₁ have mem₁ : (DirectSum.decompose 𝒜 r k : A) * x ∈ 𝒜 (k + i) := GradedMul.mul_mem (SetLike.coe_mem _) hi - erw [GradedRing.proj_apply, DirectSum.decompose_of_mem 𝒜 mem₁, coe_of_apply] + rw [GradedRing.proj_apply, DirectSum.decompose_of_mem 𝒜 mem₁, coe_of_apply] split_ifs · exact I.mul_mem_left _ hx₂ · exact I.zero_mem diff --git a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean index c3721f85c4ec5..ace75dcb78fce 100644 --- a/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean +++ b/Mathlib/RingTheory/GradedAlgebra/HomogeneousLocalization.lean @@ -353,7 +353,7 @@ instance hasPow : Pow (HomogeneousLocalization 𝒜 x) ℕ where (Quotient.map' (· ^ n) fun c1 c2 (h : Localization.mk _ _ = Localization.mk _ _) => by change Localization.mk _ _ = Localization.mk _ _ simp only [num_pow, den_pow] - convert congr_arg (fun z : at x => z ^ n) h <;> erw [Localization.mk_pow] <;> rfl : + convert congr_arg (fun z : at x => z ^ n) h <;> rw [Localization.mk_pow] <;> rfl : HomogeneousLocalization 𝒜 x → HomogeneousLocalization 𝒜 x) z @@ -366,7 +366,7 @@ instance : Add (HomogeneousLocalization 𝒜 x) where (h' : Localization.mk _ _ = Localization.mk _ _) => by change Localization.mk _ _ = Localization.mk _ _ simp only [num_add, den_add, ← Localization.add_mk] - convert congr_arg₂ (· + ·) h h' <;> erw [Localization.add_mk] <;> rfl + convert congr_arg₂ (· + ·) h h' <;> rw [Localization.add_mk] <;> rfl @[simp] lemma mk_add (i j : NumDenSameDeg 𝒜 x) : mk (i + j) = mk i + mk j := rfl @@ -379,7 +379,7 @@ instance : Mul (HomogeneousLocalization 𝒜 x) where (h' : Localization.mk _ _ = Localization.mk _ _) => by change Localization.mk _ _ = Localization.mk _ _ simp only [num_mul, den_mul] - convert congr_arg₂ (· * ·) h h' <;> erw [Localization.mk_mul] <;> rfl + convert congr_arg₂ (· * ·) h h' <;> rw [Localization.mk_mul] <;> rfl @[simp] lemma mk_mul (i j : NumDenSameDeg 𝒜 x) : mk (i * j) = mk i * mk j := rfl diff --git a/Mathlib/RingTheory/HahnSeries/Multiplication.lean b/Mathlib/RingTheory/HahnSeries/Multiplication.lean index f3c1ef6a86bc5..153ac24993c5d 100644 --- a/Mathlib/RingTheory/HahnSeries/Multiplication.lean +++ b/Mathlib/RingTheory/HahnSeries/Multiplication.lean @@ -229,10 +229,10 @@ theorem add_smul [AddCommMonoid R] [SMulWithZero R V] {x y : HahnSeries Γ R} ext a have hwf := x.isPWO_support.union y.isPWO_support rw [smul_coeff_left hwf, HahnSeries.add_coeff', of_symm_add] - simp_all only [Pi.add_apply, HahnSeries.add_coeff'] - rw [smul_coeff_left hwf Set.subset_union_right, - smul_coeff_left hwf Set.subset_union_left] - · simp only [HahnSeries.add_coeff, h, sum_add_distrib] + · simp_all only [Pi.add_apply, HahnSeries.add_coeff'] + rw [smul_coeff_left hwf Set.subset_union_right, + smul_coeff_left hwf Set.subset_union_left] + simp only [HahnSeries.add_coeff, h, sum_add_distrib] · intro b simp_all only [Set.isPWO_union, HahnSeries.isPWO_support, and_self, HahnSeries.mem_support, HahnSeries.add_coeff, ne_eq, Set.mem_union, Set.mem_setOf_eq, mem_support] diff --git a/Mathlib/RingTheory/Henselian.lean b/Mathlib/RingTheory/Henselian.lean index c439259451ff0..b1762c379f824 100644 --- a/Mathlib/RingTheory/Henselian.lean +++ b/Mathlib/RingTheory/Henselian.lean @@ -194,7 +194,7 @@ instance (priority := 100) IsAdicComplete.henselianRing (R : Type*) [CommRing R] have hf'c : ∀ n, IsUnit (f'.eval (c n)) := by intro n haveI := isLocalRingHom_of_le_jacobson_bot I (IsAdicComplete.le_jacobson_bot I) - apply isUnit_of_map_unit (Ideal.Quotient.mk I) + apply IsUnit.of_map (Ideal.Quotient.mk I) convert h₂ using 1 exact SModEq.def.mp ((hc_mod n).eval _) have hfcI : ∀ n, f.eval (c n) ∈ I ^ (n + 1) := by @@ -229,13 +229,7 @@ instance (priority := 100) IsAdicComplete.henselianRing (R : Type*) [CommRing R] clear hmn induction' k with k ih · rw [add_zero] - rw [← add_assoc] - #adaptation_note /-- nightly-2024-03-11 - I'm not sure why the `erw` is now needed here. It looks like it should work. - It looks like a diamond between `instHAdd` on `Nat` and `AddSemigroup.toAdd` which is - used by `instHAdd` -/ - erw [hc] - rw [← add_zero (c m), sub_eq_add_neg] + rw [← add_assoc, hc, ← add_zero (c m), sub_eq_add_neg] refine ih.add ?_ symm rw [SModEq.zero, Ideal.neg_mem_iff] diff --git a/Mathlib/RingTheory/Ideal/Basic.lean b/Mathlib/RingTheory/Ideal/Basic.lean index 3b495e29ee8df..69a42212b475e 100644 --- a/Mathlib/RingTheory/Ideal/Basic.lean +++ b/Mathlib/RingTheory/Ideal/Basic.lean @@ -28,7 +28,7 @@ Support right ideals, and two-sided ideals over non-commutative rings. universe u v w -variable {α : Type u} {β : Type v} +variable {α : Type u} {β : Type v} {F : Type w} open Set Function @@ -149,6 +149,9 @@ theorem mem_span_insert {s : Set α} {x y} : theorem mem_span_singleton' {x y : α} : x ∈ span ({y} : Set α) ↔ ∃ a, a * y = x := Submodule.mem_span_singleton +theorem mem_span_singleton_self (x : α) : x ∈ span ({x} : Set α) := + Submodule.mem_span_singleton_self x + theorem span_singleton_le_iff_mem {x : α} : span {x} ≤ I ↔ x ∈ I := Submodule.span_singleton_le_iff_mem _ _ @@ -184,8 +187,8 @@ theorem span_eq_top_iff_finite (s : Set α) : simp_rw [eq_top_iff_one] exact ⟨Submodule.mem_span_finite_of_mem_span, fun ⟨s', h₁, h₂⟩ => span_mono h₁ h₂⟩ -theorem mem_span_singleton_sup {S : Type*} [CommSemiring S] {x y : S} {I : Ideal S} : - x ∈ Ideal.span {y} ⊔ I ↔ ∃ a : S, ∃ b ∈ I, a * y + b = x := by +theorem mem_span_singleton_sup {x y : α} {I : Ideal α} : + x ∈ Ideal.span {y} ⊔ I ↔ ∃ a : α, ∃ b ∈ I, a * y + b = x := by rw [Submodule.mem_sup] constructor · rintro ⟨ya, hya, b, hb, rfl⟩ @@ -431,9 +434,6 @@ theorem mul_unit_mem_iff_mem {x y : α} (hy : IsUnit y) : x * y ∈ I ↔ x ∈ theorem mem_span_singleton {x y : α} : x ∈ span ({y} : Set α) ↔ y ∣ x := mem_span_singleton'.trans <| exists_congr fun _ => by rw [eq_comm, mul_comm] -theorem mem_span_singleton_self (x : α) : x ∈ span ({x} : Set α) := - mem_span_singleton.mpr dvd_rfl - theorem span_singleton_le_span_singleton {x y : α} : span ({x} : Set α) ≤ span ({y} : Set α) ↔ y ∣ x := span_le.trans <| singleton_subset_iff.trans mem_span_singleton @@ -805,6 +805,12 @@ theorem zero_mem_nonunits [Semiring α] : 0 ∈ nonunits α ↔ (0 : α) ≠ 1 : theorem one_not_mem_nonunits [Monoid α] : (1 : α) ∉ nonunits α := not_not_intro isUnit_one +-- Porting note : as this can be proved by other `simp` lemmas, this is marked as high priority. +@[simp (high)] +theorem map_mem_nonunits_iff [Monoid α] [Monoid β] [FunLike F α β] [MonoidHomClass F α β] (f : F) + [IsLocalRingHom f] (a) : f a ∈ nonunits β ↔ a ∈ nonunits α := + ⟨fun h ha => h <| ha.map f, fun h ha => h <| ha.of_map⟩ + theorem coe_subset_nonunits [Semiring α] {I : Ideal α} (h : I ≠ ⊤) : (I : Set α) ⊆ nonunits α := fun _x hx hu => h <| I.eq_top_of_isUnit_mem hx hu diff --git a/Mathlib/RingTheory/Ideal/Cotangent.lean b/Mathlib/RingTheory/Ideal/Cotangent.lean index 948ea0ff4843f..9ce01fea0e26b 100644 --- a/Mathlib/RingTheory/Ideal/Cotangent.lean +++ b/Mathlib/RingTheory/Ideal/Cotangent.lean @@ -251,7 +251,7 @@ lemma CotangentSpace.span_image_eq_top_iff [IsNoetherianRing R] {s : Set (maxima · simp only [Ideal.toCotangent_apply, Submodule.restrictScalars_top, Submodule.map_span] · exact Ideal.Quotient.mk_surjective -open FiniteDimensional +open Module lemma finrank_cotangentSpace_eq_zero_iff [IsNoetherianRing R] : finrank (ResidueField R) (CotangentSpace R) = 0 ↔ IsField R := by diff --git a/Mathlib/RingTheory/Ideal/Maps.lean b/Mathlib/RingTheory/Ideal/Maps.lean index 1f4675bf75936..5a46dd702e132 100644 --- a/Mathlib/RingTheory/Ideal/Maps.lean +++ b/Mathlib/RingTheory/Ideal/Maps.lean @@ -173,6 +173,9 @@ theorem comap_eq_top_iff {I : Ideal S} : I.comap f = ⊤ ↔ I = ⊤ := theorem map_bot : (⊥ : Ideal R).map f = ⊥ := (gc_map_comap f).l_bot +theorem ne_bot_of_map_ne_bot (hI : map f I ≠ ⊥) : I ≠ ⊥ := + fun h => hI (Eq.mpr (congrArg (fun I ↦ map f I = ⊥) h) map_bot) + variable (f I J K L) @[simp] diff --git a/Mathlib/RingTheory/Ideal/Operations.lean b/Mathlib/RingTheory/Ideal/Operations.lean index e24dba67ac093..50211d46f660e 100644 --- a/Mathlib/RingTheory/Ideal/Operations.lean +++ b/Mathlib/RingTheory/Ideal/Operations.lean @@ -608,6 +608,11 @@ theorem sup_prod_eq_top {s : Finset ι} {J : ι → Ideal R} (h : ∀ i, i ∈ s (fun J K hJ hK => (sup_mul_eq_of_coprime_left hJ).trans hK) (by simp_rw [one_eq_top, sup_top_eq]) h +theorem sup_multiset_prod_eq_top {s : Multiset (Ideal R)} (h : ∀ p ∈ s, I ⊔ p = ⊤) : + I ⊔ Multiset.prod s = ⊤ := + Multiset.prod_induction (I ⊔ · = ⊤) s (fun _ _ hp hq ↦ (sup_mul_eq_of_coprime_left hp).trans hq) + (by simp only [one_eq_top, ge_iff_le, top_le_iff, le_top, sup_of_le_right]) h + theorem sup_iInf_eq_top {s : Finset ι} {J : ι → Ideal R} (h : ∀ i, i ∈ s → I ⊔ J i = ⊤) : (I ⊔ ⨅ i ∈ s, J i) = ⊤ := eq_top_iff.mpr <| @@ -975,10 +980,37 @@ theorem IsPrime.multiset_prod_mem_iff_exists_mem {I : Ideal R} (hI : I.IsPrime) s.prod ∈ I ↔ ∃ p ∈ s, p ∈ I := by simpa [span_singleton_le_iff_mem] using (hI.multiset_prod_map_le (span {·})) +theorem IsPrime.pow_le_iff {I P : Ideal R} [hP : P.IsPrime] {n : ℕ} (hn : n ≠ 0) : + I ^ n ≤ P ↔ I ≤ P := by + have h : (Multiset.replicate n I).prod ≤ P ↔ _ := hP.multiset_prod_le + simp_rw [Multiset.prod_replicate, Multiset.mem_replicate, ne_eq, hn, not_false_eq_true, + true_and, exists_eq_left] at h + exact h + +@[deprecated (since := "2024-10-06")] alias pow_le_prime_iff := IsPrime.pow_le_iff + +theorem IsPrime.le_of_pow_le {I P : Ideal R} [hP : P.IsPrime] {n : ℕ} (h : I ^ n ≤ P) : + I ≤ P := by + by_cases hn : n = 0 + · rw [hn, pow_zero, one_eq_top] at h + exact fun ⦃_⦄ _ ↦ h Submodule.mem_top + · exact (pow_le_iff hn).mp h + +@[deprecated (since := "2024-10-06")] alias le_of_pow_le_prime := IsPrime.le_of_pow_le + theorem IsPrime.prod_le {s : Finset ι} {f : ι → Ideal R} {P : Ideal R} (hp : IsPrime P) : s.prod f ≤ P ↔ ∃ i ∈ s, f i ≤ P := hp.multiset_prod_map_le f +@[deprecated (since := "2024-10-06")] alias prod_le_prime := IsPrime.prod_le + +/-- The product of a finite number of elements in the commutative semiring `R` lies in the + prime ideal `p` if and only if at least one of those elements is in `p`. -/ +theorem IsPrime.prod_mem_iff {s : Finset ι} {x : ι → R} {p : Ideal R} [hp : p.IsPrime] : + ∏ i in s, x i ∈ p ↔ ∃ i ∈ s, x i ∈ p := by + simp_rw [← span_singleton_le_iff_mem, ← prod_span_singleton] + exact hp.prod_le + theorem IsPrime.prod_mem_iff_exists_mem {I : Ideal R} (hI : I.IsPrime) (s : Finset R) : s.prod (fun x ↦ x) ∈ I ↔ ∃ p ∈ s, p ∈ I := by rw [Finset.prod_eq_multiset_prod, Multiset.map_id'] @@ -1038,8 +1070,8 @@ theorem subset_union_prime' {R : Type u} [CommRing R] {s : Finset ι} {f : ι rw [Finset.coe_insert] at h ⊢ rw [Finset.coe_insert] at h simp only [Set.biUnion_insert] at h ⊢ - rw [← Set.union_assoc (f i : Set R)] at h - erw [Set.union_eq_self_of_subset_right hfji] at h + rw [← Set.union_assoc (f i : Set R), + Set.union_eq_self_of_subset_right hfji] at h exact h specialize ih hp' hn' h' refine ih.imp id (Or.imp id (Exists.imp fun k => ?_)) @@ -1047,8 +1079,8 @@ theorem subset_union_prime' {R : Type u} [CommRing R] {s : Finset ι} {f : ι by_cases Ha : f a ≤ f i · have h' : (I : Set R) ⊆ f i ∪ f b ∪ ⋃ j ∈ (↑t : Set ι), f j := by rw [Finset.coe_insert, Set.biUnion_insert, ← Set.union_assoc, - Set.union_right_comm (f a : Set R)] at h - erw [Set.union_eq_self_of_subset_left Ha] at h + Set.union_right_comm (f a : Set R), + Set.union_eq_self_of_subset_left Ha] at h exact h specialize ih hp.2 hn h' right @@ -1059,8 +1091,8 @@ theorem subset_union_prime' {R : Type u} [CommRing R] {s : Finset ι} {f : ι by_cases Hb : f b ≤ f i · have h' : (I : Set R) ⊆ f a ∪ f i ∪ ⋃ j ∈ (↑t : Set ι), f j := by rw [Finset.coe_insert, Set.biUnion_insert, ← Set.union_assoc, - Set.union_assoc (f a : Set R)] at h - erw [Set.union_eq_self_of_subset_left Hb] at h + Set.union_assoc (f a : Set R), + Set.union_eq_self_of_subset_left Hb] at h exact h specialize ih hp.2 hn h' rcases ih with (ih | ih | ⟨k, hkt, ih⟩) diff --git a/Mathlib/RingTheory/Ideal/Quotient.lean b/Mathlib/RingTheory/Ideal/Quotient.lean index a8a6b587bf0f9..5a9cc0195360c 100644 --- a/Mathlib/RingTheory/Ideal/Quotient.lean +++ b/Mathlib/RingTheory/Ideal/Quotient.lean @@ -55,7 +55,7 @@ instance one (I : Ideal R) : One (R ⧸ I) := protected def ringCon (I : Ideal R) : RingCon R := { QuotientAddGroup.con I.toAddSubgroup with mul' := fun {a₁ b₁ a₂ b₂} h₁ h₂ => by - rw [Submodule.quotientRel_r_def] at h₁ h₂ ⊢ + rw [Submodule.quotientRel_def] at h₁ h₂ ⊢ have F := I.add_mem (I.mul_mem_left a₂ h₁) (I.mul_mem_right b₁ h₂) have : a₁ * a₂ - b₁ * b₂ = a₂ * (a₁ - b₁) + (a₂ - b₂) * b₁ := by rw [mul_sub, sub_mul, sub_add_sub_cancel, mul_comm, mul_comm b₁] @@ -177,7 +177,7 @@ theorem exists_inv {I : Ideal R} [hI : I.IsMaximal] : rcases hI.exists_inv (mt eq_zero_iff_mem.2 h) with ⟨b, c, hc, abc⟩ rw [mul_comm] at abc refine ⟨mk _ b, Quot.sound ?_⟩ - simp only [Submodule.quotientRel_r_def] + simp only [Submodule.quotientRel_def] rw [← eq_sub_iff_add_eq'] at abc rwa [abc, ← neg_mem_iff (G := R) (H := I), neg_sub] at hc @@ -291,7 +291,7 @@ instance modulePi : Module (R ⧸ I) ((ι → R) ⧸ I.pi ι) where 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 + rw [Submodule.quotientRel_def] at hc hm intro i exact I.mul_sub_mul_mem hc (hm i) one_smul := by diff --git a/Mathlib/RingTheory/Idempotents.lean b/Mathlib/RingTheory/Idempotents.lean index 2e8db654b863c..c2dd1724dad6f 100644 --- a/Mathlib/RingTheory/Idempotents.lean +++ b/Mathlib/RingTheory/Idempotents.lean @@ -214,8 +214,6 @@ A family `{ eᵢ }` of idempotent elements is complete orthogonal if structure CompleteOrthogonalIdempotents (e : I → R) extends OrthogonalIdempotents e : Prop where complete : ∑ i, e i = 1 -variable (he : CompleteOrthogonalIdempotents e) - lemma CompleteOrthogonalIdempotents.unique_iff [Unique I] : CompleteOrthogonalIdempotents e ↔ e default = 1 := by rw [completeOrthogonalIdempotents_iff, OrthogonalIdempotents.unique, Fintype.sum_unique, diff --git a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean index ac6ad06cc3419..37343ddf2c611 100644 --- a/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/Algebra/Basic.lean @@ -148,9 +148,23 @@ variable (f : R →+* S) theorem RingHom.IsIntegralElem.neg {x : S} (hx : f.IsIntegralElem x) : f.IsIntegralElem (-x) := hx.of_mem_closure f hx (Subring.neg_mem _ (Subring.subset_closure (Or.inl rfl))) +theorem RingHom.IsIntegralElem.of_neg {x : S} (h : f.IsIntegralElem (-x)) : f.IsIntegralElem x := + neg_neg x ▸ h.neg + +@[simp] +theorem RingHom.IsIntegralElem.neg_iff {x : S} : f.IsIntegralElem (-x) ↔ f.IsIntegralElem x := + ⟨fun h => h.of_neg, fun h => h.neg⟩ + theorem IsIntegral.neg {x : B} (hx : IsIntegral R x) : IsIntegral R (-x) := .of_mem_of_fg _ hx.fg_adjoin_singleton _ (Subalgebra.neg_mem _ <| Algebra.subset_adjoin rfl) +theorem IsIntegral.of_neg {x : B} (hx : IsIntegral R (-x)) : IsIntegral R x := + neg_neg x ▸ hx.neg + +@[simp] +theorem IsIntegral.neg_iff {x : B} : IsIntegral R (-x) ↔ IsIntegral R x := + ⟨IsIntegral.of_neg, IsIntegral.neg⟩ + theorem RingHom.IsIntegralElem.sub {x y : S} (hx : f.IsIntegralElem x) (hy : f.IsIntegralElem y) : f.IsIntegralElem (x - y) := by simpa only [sub_eq_add_neg] using hx.add f (hy.neg f) diff --git a/Mathlib/RingTheory/IntegralClosure/Algebra/Defs.lean b/Mathlib/RingTheory/IntegralClosure/Algebra/Defs.lean index 8e9ef7deed80b..58e184777c8f9 100644 --- a/Mathlib/RingTheory/IntegralClosure/Algebra/Defs.lean +++ b/Mathlib/RingTheory/IntegralClosure/Algebra/Defs.lean @@ -29,7 +29,7 @@ variable [Algebra R A] (R) variable (A) /-- An algebra is integral if every element of the extension is integral over the base ring. -/ -protected class Algebra.IsIntegral : Prop := +protected class Algebra.IsIntegral : Prop where isIntegral : ∀ x : A, IsIntegral R x variable {R A} diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Defs.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Defs.lean index 891b51eb8aa16..a145ced7ef9ab 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegral/Defs.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegral/Defs.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kenny Lau -/ import Mathlib.Algebra.Polynomial.Eval +import Mathlib.Tactic.Algebraize /-! # Integral closure of a subring. @@ -35,6 +36,7 @@ def RingHom.IsIntegralElem (f : R →+* A) (x : A) := /-- A ring homomorphism `f : R →+* A` is said to be integral if every element `A` is integral with respect to the map `f` -/ +@[algebraize Algebra.IsIntegral.mk] def RingHom.IsIntegral (f : R →+* A) := ∀ x : A, f.IsIntegralElem x diff --git a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean index 0a9301168ce1c..146fc3d8f12a9 100644 --- a/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean +++ b/Mathlib/RingTheory/IntegralClosure/IsIntegralClosure/Basic.lean @@ -395,14 +395,14 @@ variable [Algebra R A] [Algebra R A'] [IsScalarTower R A B] [IsScalarTower R A' /-- Integral closures are all isomorphic to each other. -/ noncomputable def equiv : A ≃ₐ[R] A' := AlgEquiv.ofAlgHom - (lift _ B (isIntegral := isIntegral_algebra R B)) - (lift _ B (isIntegral := isIntegral_algebra R B)) + (lift R A' B (isIntegral := isIntegral_algebra R B)) + (lift R A B (isIntegral := isIntegral_algebra R B)) (by ext x; apply algebraMap_injective A' R B; simp) (by ext x; apply algebraMap_injective A R B; simp) @[simp] theorem algebraMap_equiv (x : A) : algebraMap A' B (equiv R A B A' x) = algebraMap A B x := - algebraMap_lift A' B (isIntegral := isIntegral_algebra R B) x + algebraMap_lift R A' B (isIntegral := isIntegral_algebra R B) x end Equiv diff --git a/Mathlib/RingTheory/IntegralDomain.lean b/Mathlib/RingTheory/IntegralDomain.lean index 544f816a2f202..2d5e9ee2a2c51 100644 --- a/Mathlib/RingTheory/IntegralDomain.lean +++ b/Mathlib/RingTheory/IntegralDomain.lean @@ -54,7 +54,7 @@ def Fintype.groupWithZeroOfCancel (M : Type*) [CancelMonoidWithZero M] [Decidabl inv_zero := by simp [Inv.inv, dif_pos rfl] } theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsDomain R] - [GCDMonoid R] [Unique Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) : + [GCDMonoid R] [Subsingleton Rˣ] {a b c : R} {n : ℕ} (cp : IsCoprime a b) (h : a * b = c ^ n) : ∃ d : R, a = d ^ n := by refine exists_eq_pow_of_mul_eq_pow (isUnit_of_dvd_one ?_) h obtain ⟨x, y, hxy⟩ := cp @@ -65,7 +65,7 @@ theorem exists_eq_pow_of_mul_eq_pow_of_coprime {R : Type*} [CommSemiring R] [IsD nonrec theorem Finset.exists_eq_pow_of_mul_eq_pow_of_coprime {ι R : Type*} [CommSemiring R] [IsDomain R] - [GCDMonoid R] [Unique Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R} + [GCDMonoid R] [Subsingleton Rˣ] {n : ℕ} {c : R} {s : Finset ι} {f : ι → R} (h : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → IsCoprime (f i) (f j)) (hprod : ∏ i ∈ s, f i = c ^ n) : ∀ i ∈ s, ∃ d : R, f i = d ^ n := by classical diff --git a/Mathlib/RingTheory/IsTensorProduct.lean b/Mathlib/RingTheory/IsTensorProduct.lean index 942b0ab45ddf4..b02662937d43f 100644 --- a/Mathlib/RingTheory/IsTensorProduct.lean +++ b/Mathlib/RingTheory/IsTensorProduct.lean @@ -318,11 +318,40 @@ theorem IsBaseChange.comp {f : M →ₗ[R] N} (hf : IsBaseChange S f) {g : N → ext rfl +/-- If `N` is the base change of `M` to `S` and `O` the base change of `M` to `T`, then +`O` is the base change of `N` to `T`. -/ +lemma IsBaseChange.of_comp {f : M →ₗ[R] N} (hf : IsBaseChange S f) {h : N →ₗ[S] O} + (hc : IsBaseChange T ((h : N →ₗ[R] O) ∘ₗ f)) : + IsBaseChange T h := by + apply IsBaseChange.of_lift_unique + intro Q _ _ _ _ r + letI : Module R Q := inferInstanceAs (Module R (RestrictScalars R S Q)) + haveI : IsScalarTower R S Q := IsScalarTower.of_algebraMap_smul fun r ↦ congrFun rfl + haveI : IsScalarTower R T Q := IsScalarTower.of_algebraMap_smul fun r x ↦ by + simp [IsScalarTower.algebraMap_apply R S T] + let r' : M →ₗ[R] Q := r ∘ₗ f + let q : O →ₗ[T] Q := hc.lift r' + refine ⟨q, ?_, ?_⟩ + · apply hf.algHom_ext' + simp [LinearMap.comp_assoc, hc.lift_comp] + · intro q' hq' + apply hc.algHom_ext' + apply_fun LinearMap.restrictScalars R at hq' + rw [← LinearMap.comp_assoc] + rw [show q'.restrictScalars R ∘ₗ h.restrictScalars R = _ from hq', hc.lift_comp] + +/-- If `N` is the base change `M` to `S`, then `O` is the base change of `M` to `T` if and +only if `O` is the base change of `N` to `T`. -/ +lemma IsBaseChange.comp_iff {f : M →ₗ[R] N} (hf : IsBaseChange S f) {h : N →ₗ[S] O} : + IsBaseChange T ((h : N →ₗ[R] O) ∘ₗ f) ↔ IsBaseChange T h := + ⟨fun hc ↦ IsBaseChange.of_comp hf hc, fun hh ↦ IsBaseChange.comp hf hh⟩ + variable {R' S' : Type*} [CommSemiring R'] [CommSemiring S'] variable [Algebra R R'] [Algebra S S'] [Algebra R' S'] [Algebra R S'] variable [IsScalarTower R R' S'] [IsScalarTower R S S'] open IsScalarTower (toAlgHom) +open IsScalarTower (algebraMap_apply) variable (R S R' S') @@ -424,7 +453,7 @@ noncomputable def Algebra.pushoutDesc [H : Algebra.IsPushout R S R' S'] {A : Typ rw [mul_add, map_add, map_add, mul_add, e₁, e₂] @[simp] -theorem Algebra.pushoutDesc_left [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] +theorem Algebra.pushoutDesc_left [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) (x : S) : Algebra.pushoutDesc S' f g H (algebraMap S S' x) = f x := by letI := Module.compHom A f.toRingHom @@ -442,7 +471,7 @@ theorem Algebra.lift_algHom_comp_left [Algebra.IsPushout R S R' S'] {A : Type*} AlgHom.ext fun x => (Algebra.pushoutDesc_left S' f g H x : _) @[simp] -theorem Algebra.pushoutDesc_right [H : Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] +theorem Algebra.pushoutDesc_right [Algebra.IsPushout R S R' S'] {A : Type*} [Semiring A] [Algebra R A] (f : S →ₐ[R] A) (g : R' →ₐ[R] A) (H) (x : R') : Algebra.pushoutDesc S' f g H (algebraMap R' S' x) = g x := letI := Module.compHom A f.toRingHom @@ -471,4 +500,33 @@ theorem Algebra.IsPushout.algHom_ext [H : Algebra.IsPushout R S R' S'] {A : Type · intro s₁ s₂ e₁ e₂ rw [map_add, map_add, e₁, e₂] +/-- +Let the following be a commutative diagram of rings +``` + R → S → T + ↓ ↓ ↓ + R' → S' → T' +``` +where the left-hand square is a pushout. Then the following are equivalent: +- the big rectangle is a pushout. +- the right-hand square is a pushout. + +Note that this is essentially the isomorphism `T ⊗[S] (S ⊗[R] R') ≃ₐ[T] T ⊗[R] R'`. +-/ +lemma Algebra.IsPushout.comp_iff {T' : Type*} [CommRing T'] [Algebra R T'] + [Algebra S' T'] [Algebra S T'] [Algebra T T'] [Algebra R' T'] + [IsScalarTower R T T'] [IsScalarTower S T T'] [IsScalarTower S S' T'] + [IsScalarTower R R' T'] [IsScalarTower R S' T'] [IsScalarTower R' S' T'] + [Algebra.IsPushout R S R' S'] : + Algebra.IsPushout R T R' T' ↔ Algebra.IsPushout S T S' T' := by + let f : R' →ₗ[R] S' := (IsScalarTower.toAlgHom R R' S').toLinearMap + haveI : IsScalarTower R S T' := IsScalarTower.of_algebraMap_eq <| fun x ↦ by + rw [algebraMap_apply R S' T', algebraMap_apply R S S', ← algebraMap_apply S S' T'] + have heq : (toAlgHom S S' T').toLinearMap.restrictScalars R ∘ₗ f = + (toAlgHom R R' T').toLinearMap := by + ext x + simp [f, ← IsScalarTower.algebraMap_apply] + rw [isPushout_iff, isPushout_iff, ← heq, IsBaseChange.comp_iff] + exact Algebra.IsPushout.out + end IsBaseChange diff --git a/Mathlib/RingTheory/Jacobson.lean b/Mathlib/RingTheory/Jacobson.lean index 29cd5339dde32..93ed9e32a751f 100644 --- a/Mathlib/RingTheory/Jacobson.lean +++ b/Mathlib/RingTheory/Jacobson.lean @@ -144,7 +144,7 @@ section Localization open IsLocalization Submonoid -variable {R S : Type*} [CommRing R] [CommRing S] {I : Ideal R} +variable {R S : Type*} [CommRing R] [CommRing S] variable (y : R) [Algebra R S] [IsLocalization.Away y S] variable (S) diff --git a/Mathlib/RingTheory/JacobsonIdeal.lean b/Mathlib/RingTheory/JacobsonIdeal.lean index c51eef801b35e..5f513287fa395 100644 --- a/Mathlib/RingTheory/JacobsonIdeal.lean +++ b/Mathlib/RingTheory/JacobsonIdeal.lean @@ -1,11 +1,12 @@ /- Copyright (c) 2020 Devon Tuma. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Kenny Lau, Devon Tuma +Authors: Kenny Lau, Devon Tuma, Wojciech Nawrocki -/ import Mathlib.RingTheory.Ideal.IsPrimary import Mathlib.RingTheory.Ideal.Quotient import Mathlib.RingTheory.Polynomial.Quotient +import Mathlib.RingTheory.TwoSidedIdeal.Operations /-! # Jacobson radical @@ -13,20 +14,24 @@ import Mathlib.RingTheory.Polynomial.Quotient The Jacobson radical of a ring `R` is defined to be the intersection of all maximal ideals of `R`. This is similar to how the nilradical is equal to the intersection of all prime ideals of `R`. -We can extend the idea of the nilradical to ideals of `R`, -by letting the radical of an ideal `I` be the intersection of prime ideals containing `I`. +We can extend the idea of the nilradical of `R` to ideals of `R`, +by letting the nilradical of an ideal `I` be the intersection of prime ideals containing `I`. Under this extension, the original nilradical is the radical of the zero ideal `⊥`. Here we define the Jacobson radical of an ideal `I` in a similar way, as the intersection of maximal ideals containing `I`. ## Main definitions -Let `R` be a commutative ring, and `I` be an ideal of `R` +Let `R` be a ring, and `I` be a left ideal of `R` -* `Ideal.jacobson I` is the jacobson radical, i.e. the infimum of all maximal ideals containing I. +* `Ideal.jacobson I` is the Jacobson radical, i.e. the infimum of all maximal ideals containing `I`. * `Ideal.IsLocal I` is the proposition that the jacobson radical of `I` is itself a maximal ideal +Furthermore when `I` is a two-sided ideal of `R` + +* `TwoSidedIdeal.jacobson I` is the Jacobson radical as a two-sided ideal + ## Main statements * `mem_jacobson_iff` gives a characterization of members of the jacobson of I @@ -111,11 +116,17 @@ theorem mem_jacobson_iff {x : R} : x ∈ jacobson I ↔ ∀ y, ∃ z, z * y * x sub_add_cancel] exact M.mul_mem_left _ hi) <| him hz⟩ -theorem exists_mul_sub_mem_of_sub_one_mem_jacobson {I : Ideal R} (r : R) (h : r - 1 ∈ jacobson I) : - ∃ s, s * r - 1 ∈ I := by +theorem exists_mul_add_sub_mem_of_mem_jacobson {I : Ideal R} (r : R) (h : r ∈ jacobson I) : + ∃ s, s * (r + 1) - 1 ∈ I := by cases' mem_jacobson_iff.1 h 1 with s hs use s - simpa [mul_sub] using hs + rw [mul_add, mul_one] + simpa using hs + +theorem exists_mul_sub_mem_of_sub_one_mem_jacobson {I : Ideal R} (r : R) (h : r - 1 ∈ jacobson I) : + ∃ s, s * r - 1 ∈ I := by + convert exists_mul_add_sub_mem_of_mem_jacobson _ h + simp /-- An ideal equals its Jacobson radical iff it is the intersection of a set of maximal ideals. Allowing the set to include ⊤ is equivalent, and is included only to simplify some proofs. -/ @@ -214,6 +225,44 @@ theorem jacobson_mono {I J : Ideal R} : I ≤ J → I.jacobson ≤ J.jacobson := erw [mem_sInf] at hx ⊢ exact fun K ⟨hK, hK_max⟩ => hx ⟨Trans.trans h hK, hK_max⟩ +/-- The Jacobson radical of a two-sided ideal is two-sided. + +It is preferable to use `TwoSidedIdeal.jacobson` instead of this lemma. -/ +theorem jacobson_mul_mem_right {I : Ideal R} + (mul_mem_right : ∀ {x y}, x ∈ I → x * y ∈ I) : + ∀ {x y}, x ∈ I.jacobson → x * y ∈ I.jacobson := by + -- Proof generalized from + -- https://ysharifi.wordpress.com/2022/08/16/the-jacobson-radical-definition-and-basic-results/ + intro x r xJ + apply mem_sInf.mpr + intro 𝔪 𝔪_mem + by_cases r𝔪 : r ∈ 𝔪 + · apply 𝔪.smul_mem _ r𝔪 + -- 𝔪₀ := { a : R | a*r ∈ 𝔪 } + let 𝔪₀ : Ideal R := Submodule.comap (DistribMulAction.toLinearMap R (S := Rᵐᵒᵖ) R (.op r)) 𝔪 + suffices x ∈ 𝔪₀ by simpa [𝔪₀] using this + have I𝔪₀ : I ≤ 𝔪₀ := fun i iI => + 𝔪_mem.left (mul_mem_right iI) + have 𝔪₀_maximal : IsMaximal 𝔪₀ := by + refine isMaximal_iff.mpr ⟨ + fun h => r𝔪 (by simpa [𝔪₀] using h), + fun J b 𝔪₀J b𝔪₀ bJ => ?_⟩ + let K : Ideal R := Ideal.span {b*r} ⊔ 𝔪 + have ⟨s, y, y𝔪, sbyr⟩ := + mem_span_singleton_sup.mp <| + mul_mem_left _ r <| + (isMaximal_iff.mp 𝔪_mem.right).right K (b*r) + le_sup_right b𝔪₀ + (mem_sup_left <| mem_span_singleton_self _) + have : 1 - s*b ∈ 𝔪₀ := by + rw [mul_one, add_comm, ← eq_sub_iff_add_eq] at sbyr + rw [sbyr, ← mul_assoc] at y𝔪 + simp [𝔪₀, sub_mul, y𝔪] + have : 1 - s*b + s*b ∈ J := by + apply add_mem (𝔪₀J this) (J.mul_mem_left _ bJ) + simpa using this + exact mem_sInf.mp xJ ⟨I𝔪₀, 𝔪₀_maximal⟩ + end Ring section CommRing @@ -375,3 +424,16 @@ theorem isPrimary_of_isMaximal_radical [CommRing R] {I : Ideal R} (hi : IsMaxima (this ▸ id)⟩ end Ideal + +namespace TwoSidedIdeal + +variable {R : Type u} [Ring R] + +/-- The Jacobson radical of `I` is the infimum of all maximal (left) ideals containing `I`. -/ +def jacobson (I : TwoSidedIdeal R) : TwoSidedIdeal R := + (asIdeal I).jacobson.toTwoSided (Ideal.jacobson_mul_mem_right <| I.mul_mem_right _ _) + +lemma asIdeal_jacobson (I : TwoSidedIdeal R) : asIdeal I.jacobson = (asIdeal I).jacobson := by + ext; simp [jacobson] + +end TwoSidedIdeal diff --git a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean index bcdc42a93b266..75e250102f8fe 100644 --- a/Mathlib/RingTheory/Kaehler/CotangentComplex.lean +++ b/Mathlib/RingTheory/Kaehler/CotangentComplex.lean @@ -157,10 +157,6 @@ lemma map_comp_cotangentComplex (f : Hom P P') : end CotangentSpace -universe uT - -variable {T : Type uT} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] - lemma Hom.sub_aux (f g : Hom P P') (x y) : letI := ((algebraMap S S').comp (algebraMap P.Ring S)).toAlgebra f.toAlgHom (x * y) - g.toAlgHom (x * y) - diff --git a/Mathlib/RingTheory/Kaehler/Polynomial.lean b/Mathlib/RingTheory/Kaehler/Polynomial.lean index c5e94eaca9de6..688733e7fd0c5 100644 --- a/Mathlib/RingTheory/Kaehler/Polynomial.lean +++ b/Mathlib/RingTheory/Kaehler/Polynomial.lean @@ -16,7 +16,7 @@ open Algebra universe u v -variable (R : Type u) (S : Type v) [CommRing R] [CommRing S] [Algebra R S] +variable (R : Type u) [CommRing R] suppress_compilation diff --git a/Mathlib/RingTheory/KrullDimension/Basic.lean b/Mathlib/RingTheory/KrullDimension/Basic.lean new file mode 100644 index 0000000000000..cca9f211a88e5 --- /dev/null +++ b/Mathlib/RingTheory/KrullDimension/Basic.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Fangming Li, Jujian Zhang +-/ +import Mathlib.Algebra.MvPolynomial.CommRing +import Mathlib.Algebra.Polynomial.Basic +import Mathlib.RingTheory.PrimeSpectrum +import Mathlib.Order.KrullDimension + +/-! +# Krull dimensions of (commutative) rings + +Given a commutative ring, its ring theoretic Krull dimension is the order theoretic Krull dimension +of its prime spectrum. Unfolding this definition, it is the length of the longest sequence(s) of +prime ideals ordered by strict inclusion. +-/ + +open Order + +/-- +The ring theoretic Krull dimension is the Krull dimension of its spectrum ordered by inclusion. +-/ +noncomputable def ringKrullDim (R : Type*) [CommRing R] : WithBot (WithTop ℕ) := + krullDim (PrimeSpectrum R) + +variable {R S : Type*} [CommRing R] [CommRing S] + +@[nontriviality] +lemma ringKrullDim_eq_bot_of_subsingleton [Subsingleton R] : + ringKrullDim R = ⊥ := + krullDim_eq_bot_of_isEmpty + +lemma ringKrullDim_nonneg_of_nontrivial [Nontrivial R] : + 0 ≤ ringKrullDim R := + krullDim_nonneg_of_nonempty + +/-- If `f : R →+* S` is surjective, then `ringKrullDim S ≤ ringKrullDim R`. -/ +theorem ringKrullDim_le_of_surjective (f : R →+* S) (hf : Function.Surjective f) : + ringKrullDim S ≤ ringKrullDim R := + krullDim_le_of_strictMono (fun I ↦ ⟨Ideal.comap f I.asIdeal, inferInstance⟩) + (Monotone.strictMono_of_injective (fun _ _ hab ↦ Ideal.comap_mono hab) + (fun _ _ h => PrimeSpectrum.ext_iff.mpr <| Ideal.comap_injective_of_surjective f hf <| by + simpa using h)) + +/-- If `I` is an ideal of `R`, then `ringKrullDim (R ⧸ I) ≤ ringKrullDim R`. -/ +theorem ringKrullDim_quotient_le (I : Ideal R) : + ringKrullDim (R ⧸ I) ≤ ringKrullDim R := + ringKrullDim_le_of_surjective _ Ideal.Quotient.mk_surjective + +/-- If `R` and `S` are isomorphic, then `ringKrullDim R = ringKrullDim S`. -/ +theorem ringKrullDim_eq_of_ringEquiv (e : R ≃+* S) : + ringKrullDim R = ringKrullDim S := + le_antisymm (ringKrullDim_le_of_surjective e.symm e.symm.surjective) + (ringKrullDim_le_of_surjective e e.surjective) + +alias RingEquiv.ringKrullDim := ringKrullDim_eq_of_ringEquiv + +proof_wanted Polynomial.ringKrullDim_le : + ringKrullDim (Polynomial R) ≤ 2 * (ringKrullDim R) + 1 + +proof_wanted MvPolynomial.fin_ringKrullDim_eq_add_of_isNoetherianRing + [IsNoetherianRing R] (n : ℕ) : + ringKrullDim (MvPolynomial (Fin n) R) = ringKrullDim R + n diff --git a/Mathlib/RingTheory/KrullDimension/Field.lean b/Mathlib/RingTheory/KrullDimension/Field.lean new file mode 100644 index 0000000000000..bc8ebdf09a387 --- /dev/null +++ b/Mathlib/RingTheory/KrullDimension/Field.lean @@ -0,0 +1,22 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Fangming Li, Jujian Zhang +-/ +import Mathlib.RingTheory.KrullDimension.Basic + +/-! +# The Krull dimension of a field + +This file proves that the Krull dimension of a field is zero. +-/ + +open Order + +@[simp] +theorem ringKrullDim_eq_zero_of_field (F : Type*) [Field F] : ringKrullDim F = 0 := + krullDim_eq_zero_of_unique + +theorem ringKrullDim_eq_zero_of_isField {F : Type*} [CommRing F] (hF : IsField F) : + ringKrullDim F = 0 := + @krullDim_eq_zero_of_unique _ _ <| @PrimeSpectrum.instUnique _ hF.toField diff --git a/Mathlib/RingTheory/LaurentSeries.lean b/Mathlib/RingTheory/LaurentSeries.lean index e2ae574e5cae7..e9cc56ec5ec51 100644 --- a/Mathlib/RingTheory/LaurentSeries.lean +++ b/Mathlib/RingTheory/LaurentSeries.lean @@ -11,46 +11,62 @@ import Mathlib.RingTheory.HahnSeries.Summable import Mathlib.RingTheory.PowerSeries.Inverse import Mathlib.FieldTheory.RatFunc.AsPolynomial import Mathlib.RingTheory.Localization.FractionRing +import Mathlib.Topology.UniformSpace.Cauchy /-! # Laurent Series +In this file we define `LaurentSeries R`, the formal Laurent series over `R` here an *arbitrary* +type with a zero. It is denoted `R⸨X⸩`. + ## Main Definitions + * Defines `LaurentSeries` as an abbreviation for `HahnSeries ℤ`. * Defines `hasseDeriv` of a Laurent series with coefficients in a module over a ring. -* Provides a coercion `PowerSeries R` into `LaurentSeries R` given by - `HahnSeries.ofPowerSeries`. +* Provides a coercion `from power series `R⟦X⟧` into `R⸨X⸩` given by `HahnSeries.ofPowerSeries`. * Defines `LaurentSeries.powerSeriesPart` * Defines the localization map `LaurentSeries.of_powerSeries_localization` which evaluates to `HahnSeries.ofPowerSeries`. * Embedding of rational functions into Laurent series, provided as a coercion, utilizing the underlying `RatFunc.coeAlgHom`. * Study of the `X`-Adic valuation on the ring of Laurent series over a field +* In `LaurentSeries.uniformContinuous_coeff` we show that sending a Laurent series to its `d`th +coefficient is uniformly continuous, ensuring that it sends a Cauchy filter `ℱ` in `K⸨X⸩` +to a Cauchy filter in `K`: since this latter is given the discrete topology, this provides an +element `LaurentSeries.Cauchy.coeff ℱ d` in `K` that serves as `d`th coefficient of the Laurent +series to which the filter `ℱ` converges. ## Main Results + * Basic properties of Hasse derivatives ### About the `X`-Adic valuation: * The (integral) valuation of a power series is the order of the first non-zero coefficient, see -`intValuation_le_iff_coeff_lt_eq_zero`. +`LaurentSeries.intValuation_le_iff_coeff_lt_eq_zero`. * The valuation of a Laurent series is the order of the first non-zero coefficient, see -`valuation_le_iff_coeff_lt_eq_zero`. +`LaurentSeries.valuation_le_iff_coeff_lt_eq_zero`. * Every Laurent series of valuation less than `(1 : ℤₘ₀)` comes from a power series, see -`val_le_one_iff_eq_coe`. +`LaurentSeries.val_le_one_iff_eq_coe`. +* The uniform space of `LaurentSeries` over a field is complete, formalized in the instance +`instLaurentSeriesComplete`. ## Implementation details + * Since `LaurentSeries` is just an abbreviation of `HahnSeries ℤ _`, the definition of the coefficients is given in terms of `HahnSeries.coeff` and this forces sometimes to go back-and-forth -from `X : LaurentSeries _` to `single 1 1 : HahnSeries ℤ _`. +from `X : _⸨X⸩` to `single 1 1 : HahnSeries ℤ _`. -/ universe u -open scoped Classical +open scoped Classical PowerSeries open HahnSeries Polynomial noncomputable section -/-- A `LaurentSeries` is implemented as a `HahnSeries` with value group `ℤ`. -/ +/-- `LaurentSeries R` is the type of formal Laurent series with coefficients in `R`, denoted `R⸨X⸩`. + + It is implemented as a `HahnSeries` with value group `ℤ`. +-/ abbrev LaurentSeries (R : Type u) [Zero R] := HahnSeries ℤ R @@ -58,12 +74,21 @@ variable {R : Type*} namespace LaurentSeries +section + +/-- +`R⸨X⸩` is notation for `LaurentSeries R`, +-/ +scoped notation:9000 R "⸨X⸩" => LaurentSeries R + +end + section HasseDeriv /-- The Hasse derivative of Laurent series, as a linear map. -/ @[simps] def hasseDeriv (R : Type*) {V : Type*} [AddCommGroup V] [Semiring R] [Module R V] (k : ℕ) : - LaurentSeries V →ₗ[R] LaurentSeries V where + V⸨X⸩ →ₗ[R] V⸨X⸩ where toFun f := HahnSeries.ofSuppBddBelow (fun (n : ℤ) => (Ring.choose (n + k) k) • f.coeff (n + k)) (forallLTEqZero_supp_BddBelow _ (f.order - k : ℤ) (fun _ h_lt ↦ by rw [coeff_eq_zero_of_lt_order <| lt_sub_iff_add_lt.mp h_lt, smul_zero])) @@ -76,7 +101,7 @@ def hasseDeriv (R : Type*) {V : Type*} [AddCommGroup V] [Semiring R] [Module R V variable [Semiring R] {V : Type*} [AddCommGroup V] [Module R V] -theorem hasseDeriv_coeff (k : ℕ) (f : LaurentSeries V) (n : ℤ) : +theorem hasseDeriv_coeff (k : ℕ) (f : V⸨X⸩) (n : ℤ) : (hasseDeriv R k f).coeff n = Ring.choose (n + k) k • f.coeff (n + k) := rfl @@ -86,37 +111,37 @@ section Semiring variable [Semiring R] -instance : Coe (PowerSeries R) (LaurentSeries R) := +instance : Coe R⟦X⟧ R⸨X⸩ := ⟨HahnSeries.ofPowerSeries ℤ R⟩ /- Porting note: now a syntactic tautology and not needed elsewhere -theorem coe_powerSeries (x : PowerSeries R) : - (x : LaurentSeries R) = HahnSeries.ofPowerSeries ℤ R x := +theorem coe_powerSeries (x : R⟦X⟧) : + (x : R⸨X⸩) = HahnSeries.ofPowerSeries ℤ R x := rfl -/ @[simp] -theorem coeff_coe_powerSeries (x : PowerSeries R) (n : ℕ) : - HahnSeries.coeff (x : LaurentSeries R) n = PowerSeries.coeff R n x := by +theorem coeff_coe_powerSeries (x : R⟦X⟧) (n : ℕ) : + HahnSeries.coeff (x : R⸨X⸩) n = PowerSeries.coeff R n x := by rw [ofPowerSeries_apply_coeff] /-- This is a power series that can be multiplied by an integer power of `X` to give our Laurent series. If the Laurent series is nonzero, `powerSeriesPart` has a nonzero constant term. -/ -def powerSeriesPart (x : LaurentSeries R) : PowerSeries R := +def powerSeriesPart (x : R⸨X⸩) : R⟦X⟧ := PowerSeries.mk fun n => x.coeff (x.order + n) @[simp] -theorem powerSeriesPart_coeff (x : LaurentSeries R) (n : ℕ) : +theorem powerSeriesPart_coeff (x : R⸨X⸩) (n : ℕ) : PowerSeries.coeff R n x.powerSeriesPart = x.coeff (x.order + n) := PowerSeries.coeff_mk _ _ @[simp] -theorem powerSeriesPart_zero : powerSeriesPart (0 : LaurentSeries R) = 0 := by +theorem powerSeriesPart_zero : powerSeriesPart (0 : R⸨X⸩) = 0 := by ext simp [(PowerSeries.coeff _ _).map_zero] -- Note: this doesn't get picked up any more @[simp] -theorem powerSeriesPart_eq_zero (x : LaurentSeries R) : x.powerSeriesPart = 0 ↔ x = 0 := by +theorem powerSeriesPart_eq_zero (x : R⸨X⸩) : x.powerSeriesPart = 0 ↔ x = 0 := by constructor · contrapose! simp only [ne_eq] @@ -128,8 +153,8 @@ theorem powerSeriesPart_eq_zero (x : LaurentSeries R) : x.powerSeriesPart = 0 simp @[simp] -theorem single_order_mul_powerSeriesPart (x : LaurentSeries R) : - (single x.order 1 : LaurentSeries R) * x.powerSeriesPart = x := by +theorem single_order_mul_powerSeriesPart (x : R⸨X⸩) : + (single x.order 1 : R⸨X⸩) * x.powerSeriesPart = x := by ext n rw [← sub_add_cancel n x.order, single_mul_coeff_add, sub_add_cancel, one_mul] by_cases h : x.order ≤ n @@ -145,25 +170,24 @@ theorem single_order_mul_powerSeriesPart (x : LaurentSeries R) : rw [← sub_nonneg, ← hm] simp only [Nat.cast_nonneg] -theorem ofPowerSeries_powerSeriesPart (x : LaurentSeries R) : +theorem ofPowerSeries_powerSeriesPart (x : R⸨X⸩) : ofPowerSeries ℤ R x.powerSeriesPart = single (-x.order) 1 * x := by refine Eq.trans ?_ (congr rfl x.single_order_mul_powerSeriesPart) rw [← mul_assoc, single_mul_single, neg_add_cancel, mul_one, ← C_apply, C_one, one_mul] end Semiring -instance [CommSemiring R] : Algebra (PowerSeries R) (LaurentSeries R) := - (HahnSeries.ofPowerSeries ℤ R).toAlgebra +instance [CommSemiring R] : Algebra R⟦X⟧ R⸨X⸩ := (HahnSeries.ofPowerSeries ℤ R).toAlgebra @[simp] theorem coe_algebraMap [CommSemiring R] : - ⇑(algebraMap (PowerSeries R) (LaurentSeries R)) = HahnSeries.ofPowerSeries ℤ R := + ⇑(algebraMap R⟦X⟧ R⸨X⸩) = HahnSeries.ofPowerSeries ℤ R := rfl /-- The localization map from power series to Laurent series. -/ @[simps (config := { rhsMd := .all, simpRhs := true })] instance of_powerSeries_localization [CommRing R] : - IsLocalization (Submonoid.powers (PowerSeries.X : PowerSeries R)) (LaurentSeries R) where + IsLocalization (Submonoid.powers (PowerSeries.X : R⟦X⟧)) R⸨X⸩ where map_units' := by rintro ⟨_, n, rfl⟩ refine ⟨⟨single (n : ℤ) 1, single (-n : ℤ) 1, ?_, ?_⟩, ?_⟩ @@ -187,8 +211,8 @@ instance of_powerSeries_localization [CommRing R] : rintro rfl exact ⟨1, rfl⟩ -instance {K : Type*} [Field K] : IsFractionRing (PowerSeries K) (LaurentSeries K) := - IsLocalization.of_le (Submonoid.powers (PowerSeries.X : PowerSeries K)) _ +instance {K : Type*} [Field K] : IsFractionRing K⟦X⟧ K⸨X⸩ := + IsLocalization.of_le (Submonoid.powers (PowerSeries.X : K⟦X⟧)) _ (powers_le_nonZeroDivisors_of_noZeroDivisors PowerSeries.X_ne_zero) fun _ hf => isUnit_of_mem_nonZeroDivisors <| map_mem_nonZeroDivisors _ HahnSeries.ofPowerSeries_injective hf @@ -198,34 +222,34 @@ namespace PowerSeries open LaurentSeries -variable {R' : Type*} [Semiring R] [Ring R'] (f g : PowerSeries R) (f' g' : PowerSeries R') +variable {R' : Type*} [Semiring R] [Ring R'] (f g : R⟦X⟧) (f' g' : R'⟦X⟧) @[norm_cast] -- Porting note (#10618): simp can prove this -theorem coe_zero : ((0 : PowerSeries R) : LaurentSeries R) = 0 := +theorem coe_zero : ((0 : R⟦X⟧) : R⸨X⸩) = 0 := (ofPowerSeries ℤ R).map_zero @[norm_cast] -- Porting note (#10618): simp can prove this -theorem coe_one : ((1 : PowerSeries R) : LaurentSeries R) = 1 := +theorem coe_one : ((1 : R⟦X⟧) : R⸨X⸩) = 1 := (ofPowerSeries ℤ R).map_one @[norm_cast] -- Porting note (#10618): simp can prove this -theorem coe_add : ((f + g : PowerSeries R) : LaurentSeries R) = f + g := +theorem coe_add : ((f + g : R⟦X⟧) : R⸨X⸩) = f + g := (ofPowerSeries ℤ R).map_add _ _ @[norm_cast] -theorem coe_sub : ((f' - g' : PowerSeries R') : LaurentSeries R') = f' - g' := +theorem coe_sub : ((f' - g' : R'⟦X⟧) : R'⸨X⸩) = f' - g' := (ofPowerSeries ℤ R').map_sub _ _ @[norm_cast] -theorem coe_neg : ((-f' : PowerSeries R') : LaurentSeries R') = -f' := +theorem coe_neg : ((-f' : R'⟦X⟧) : R'⸨X⸩) = -f' := (ofPowerSeries ℤ R').map_neg _ @[norm_cast] -- Porting note (#10618): simp can prove this -theorem coe_mul : ((f * g : PowerSeries R) : LaurentSeries R) = f * g := +theorem coe_mul : ((f * g : R⟦X⟧) : R⸨X⸩) = f * g := (ofPowerSeries ℤ R).map_mul _ _ theorem coeff_coe (i : ℤ) : - ((f : PowerSeries R) : LaurentSeries R).coeff i = + ((f : R⟦X⟧) : R⸨X⸩).coeff i = if i < 0 then 0 else PowerSeries.coeff R i.natAbs f := by cases i · rw [Int.ofNat_eq_coe, coeff_coe_powerSeries, if_neg (Int.natCast_nonneg _).not_lt, @@ -237,57 +261,59 @@ theorem coeff_coe (i : ℤ) : -- Porting note (#10618): simp can prove this -- Porting note: removed norm_cast attribute -theorem coe_C (r : R) : ((C R r : PowerSeries R) : LaurentSeries R) = HahnSeries.C r := +theorem coe_C (r : R) : ((C R r : R⟦X⟧) : R⸨X⸩) = HahnSeries.C r := ofPowerSeries_C _ -- @[simp] -- Porting note (#10618): simp can prove this -theorem coe_X : ((X : PowerSeries R) : LaurentSeries R) = single 1 1 := +theorem coe_X : ((X : R⟦X⟧) : R⸨X⸩) = single 1 1 := ofPowerSeries_X @[simp, norm_cast] -theorem coe_smul {S : Type*} [Semiring S] [Module R S] (r : R) (x : PowerSeries S) : - ((r • x : PowerSeries S) : LaurentSeries S) = r • (ofPowerSeries ℤ S x) := by +theorem coe_smul {S : Type*} [Semiring S] [Module R S] (r : R) (x : S⟦X⟧) : + ((r • x : S⟦X⟧) : S⸨X⸩) = r • (ofPowerSeries ℤ S x) := by ext simp [coeff_coe, coeff_smul, smul_ite] -- Porting note: RingHom.map_bit0 and RingHom.map_bit1 no longer exist @[norm_cast] -theorem coe_pow (n : ℕ) : ((f ^ n : PowerSeries R) : LaurentSeries R) = (ofPowerSeries ℤ R f) ^ n := +theorem coe_pow (n : ℕ) : ((f ^ n : R⟦X⟧) : R⸨X⸩) = (ofPowerSeries ℤ R f) ^ n := (ofPowerSeries ℤ R).map_pow _ _ end PowerSeries namespace RatFunc +open scoped LaurentSeries + variable {F : Type u} [Field F] (p q : F[X]) (f g : RatFunc F) -/-- The coercion `RatFunc F → LaurentSeries F` as bundled alg hom. -/ -def coeAlgHom (F : Type u) [Field F] : RatFunc F →ₐ[F[X]] LaurentSeries F := +/-- The coercion `RatFunc F → F⸨X⸩` as bundled alg hom. -/ +def coeAlgHom (F : Type u) [Field F] : RatFunc F →ₐ[F[X]] F⸨X⸩ := liftAlgHom (Algebra.ofId _ _) <| nonZeroDivisors_le_comap_nonZeroDivisors_of_injective _ <| Polynomial.algebraMap_hahnSeries_injective _ -/-- The coercion `RatFunc F → LaurentSeries F` as a function. +/-- The coercion `RatFunc F → F⸨X⸩` as a function. This is the implementation of `coeToLaurentSeries`. -/ @[coe] -def coeToLaurentSeries_fun {F : Type u} [Field F] : RatFunc F → LaurentSeries F := +def coeToLaurentSeries_fun {F : Type u} [Field F] : RatFunc F → F⸨X⸩ := coeAlgHom F -instance coeToLaurentSeries : Coe (RatFunc F) (LaurentSeries F) := +instance coeToLaurentSeries : Coe (RatFunc F) F⸨X⸩ := ⟨coeToLaurentSeries_fun⟩ -theorem coe_def : (f : LaurentSeries F) = coeAlgHom F f := +theorem coe_def : (f : F⸨X⸩) = coeAlgHom F f := rfl attribute [-instance] RatFunc.instCoePolynomial in -- avoids a diamond, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/compiling.20behaviour.20within.20one.20file -theorem coe_num_denom : (f : LaurentSeries F) = f.num / f.denom := +theorem coe_num_denom : (f : F⸨X⸩) = f.num / f.denom := liftAlgHom_apply _ _ f -theorem coe_injective : Function.Injective ((↑) : RatFunc F → LaurentSeries F) := +theorem coe_injective : Function.Injective ((↑) : RatFunc F → F⸨X⸩) := liftAlgHom_injective _ (Polynomial.algebraMap_hahnSeries_injective _) -- Porting note: removed the `norm_cast` tag: @@ -297,47 +323,46 @@ theorem coe_apply : coeAlgHom F f = f := rfl -- avoids a diamond, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/compiling.20behaviour.20within.20one.20file -theorem coe_coe (P : Polynomial F) : ((P : PowerSeries F) : LaurentSeries F) = (P : RatFunc F) := by +theorem coe_coe (P : Polynomial F) : ((P : F⟦X⟧) : F⸨X⸩) = (P : RatFunc F) := by simp only [coePolynomial, coe_def, AlgHom.commutes, algebraMap_hahnSeries_apply] @[simp, norm_cast] -theorem coe_zero : ((0 : RatFunc F) : LaurentSeries F) = 0 := +theorem coe_zero : ((0 : RatFunc F) : F⸨X⸩) = 0 := map_zero (coeAlgHom F) -theorem coe_ne_zero {f : Polynomial F} (hf : f ≠ 0) : (↑f : PowerSeries F) ≠ 0 := by +theorem coe_ne_zero {f : Polynomial F} (hf : f ≠ 0) : (↑f : F⟦X⟧) ≠ 0 := by simp only [ne_eq, Polynomial.coe_eq_zero_iff, hf, not_false_eq_true] @[simp, norm_cast] -theorem coe_one : ((1 : RatFunc F) : LaurentSeries F) = 1 := +theorem coe_one : ((1 : RatFunc F) : F⸨X⸩) = 1 := map_one (coeAlgHom F) @[simp, norm_cast] -theorem coe_add : ((f + g : RatFunc F) : LaurentSeries F) = f + g := +theorem coe_add : ((f + g : RatFunc F) : F⸨X⸩) = f + g := map_add (coeAlgHom F) _ _ @[simp, norm_cast] -theorem coe_sub : ((f - g : RatFunc F) : LaurentSeries F) = f - g := +theorem coe_sub : ((f - g : RatFunc F) : F⸨X⸩) = f - g := map_sub (coeAlgHom F) _ _ @[simp, norm_cast] -theorem coe_neg : ((-f : RatFunc F) : LaurentSeries F) = -f := +theorem coe_neg : ((-f : RatFunc F) : F⸨X⸩) = -f := map_neg (coeAlgHom F) _ @[simp, norm_cast] -theorem coe_mul : ((f * g : RatFunc F) : LaurentSeries F) = f * g := +theorem coe_mul : ((f * g : RatFunc F) : F⸨X⸩) = f * g := map_mul (coeAlgHom F) _ _ @[simp, norm_cast] -theorem coe_pow (n : ℕ) : ((f ^ n : RatFunc F) : LaurentSeries F) = (f : LaurentSeries F) ^ n := +theorem coe_pow (n : ℕ) : ((f ^ n : RatFunc F) : F⸨X⸩) = (f : F⸨X⸩) ^ n := map_pow (coeAlgHom F) _ _ @[simp, norm_cast] -theorem coe_div : - ((f / g : RatFunc F) : LaurentSeries F) = (f : LaurentSeries F) / (g : LaurentSeries F) := +theorem coe_div : ((f / g : RatFunc F) : F⸨X⸩) = (f : F⸨X⸩) / (g : F⸨X⸩) := map_div₀ (coeAlgHom F) _ _ @[simp, norm_cast] -theorem coe_C (r : F) : ((RatFunc.C r : RatFunc F) : LaurentSeries F) = HahnSeries.C r := by +theorem coe_C (r : F) : ((RatFunc.C r : RatFunc F) : F⸨X⸩) = HahnSeries.C r := by rw [coe_num_denom, num_C, denom_C, Polynomial.coe_C, -- Porting note: removed `coe_C` Polynomial.coe_one, PowerSeries.coe_one, div_one] @@ -345,13 +370,13 @@ theorem coe_C (r : F) : ((RatFunc.C r : RatFunc F) : LaurentSeries F) = HahnSeri -- TODO: generalize over other modules @[simp, norm_cast] -theorem coe_smul (r : F) : ((r • f : RatFunc F) : LaurentSeries F) = r • (f : LaurentSeries F) := by +theorem coe_smul (r : F) : ((r • f : RatFunc F) : F⸨X⸩) = r • (f : F⸨X⸩) := by rw [RatFunc.smul_eq_C_mul, ← C_mul_eq_smul, coe_mul, coe_C] -- Porting note: removed `norm_cast` because "badly shaped lemma, rhs can't start with coe" -- even though `single 1 1` is a bundled function application, not a "real" coercion @[simp] -theorem coe_X : ((X : RatFunc F) : LaurentSeries F) = single 1 1 := by +theorem coe_X : ((X : RatFunc F) : F⸨X⸩) = single 1 1 := by rw [coe_num_denom, num_X, denom_X, Polynomial.coe_X, -- Porting note: removed `coe_C` Polynomial.coe_one, PowerSeries.coe_one, div_one] @@ -377,18 +402,18 @@ theorem single_zpow (n : ℤ) : single_inv (n_neg + 1 : ℤ) one_ne_zero, zpow_neg, ← Nat.cast_one, ← Int.ofNat_add, Nat.cast_one, inv_inj, zpow_natCast, single_one_eq_pow, inv_one] -instance : Algebra (RatFunc F) (LaurentSeries F) := +instance : Algebra (RatFunc F) F⸨X⸩ := RingHom.toAlgebra (coeAlgHom F).toRingHom theorem algebraMap_apply_div : - algebraMap (RatFunc F) (LaurentSeries F) (algebraMap _ _ p / algebraMap _ _ q) = - algebraMap F[X] (LaurentSeries F) p / algebraMap _ _ q := by + algebraMap (RatFunc F) F⸨X⸩ (algebraMap _ _ p / algebraMap _ _ q) = + algebraMap F[X] F⸨X⸩ p / algebraMap _ _ q := by -- Porting note: had to supply implicit arguments to `convert` convert coe_div (algebraMap F[X] (RatFunc F) p) (algebraMap F[X] (RatFunc F) q) <;> rw [← mk_one, coe_def, coeAlgHom, mk_eq_div, liftAlgHom_apply_div, map_one, div_one, Algebra.ofId_apply] -instance : IsScalarTower F[X] (RatFunc F) (LaurentSeries F) := +instance : IsScalarTower F[X] (RatFunc F) F⸨X⸩ := ⟨fun x y z => by ext simp⟩ @@ -401,8 +426,7 @@ open scoped Multiplicative variable (K : Type*) [Field K] namespace PowerSeries -/-- The prime ideal `(X)` of `PowerSeries K`, when `K` is a field, as a term of the -`HeightOneSpectrum`. -/ +/-- The prime ideal `(X)` of `K⟦X⟧`, when `K` is a field, as a term of the `HeightOneSpectrum`. -/ def idealX : IsDedekindDomain.HeightOneSpectrum K⟦X⟧ where asIdeal := Ideal.span {X} isPrime := PowerSeries.span_X_isPrime @@ -448,13 +472,14 @@ end PowerSeries namespace RatFunc open IsDedekindDomain.HeightOneSpectrum PowerSeries +open scoped LaurentSeries theorem valuation_eq_LaurentSeries_valuation (P : RatFunc K) : - (Polynomial.idealX K).valuation P = (PowerSeries.idealX K).valuation (P : LaurentSeries K) := by + (Polynomial.idealX K).valuation P = (PowerSeries.idealX K).valuation (P : K⸨X⸩) := by refine RatFunc.induction_on' P ?_ intro f g h rw [Polynomial.valuation_of_mk K f h, RatFunc.mk_eq_mk' f h, Eq.comm] - convert @valuation_of_mk' (PowerSeries K) _ _ (LaurentSeries K) _ _ _ (PowerSeries.idealX K) f + convert @valuation_of_mk' K⟦X⟧ _ _ K⸨X⸩ _ _ _ (PowerSeries.idealX K) f ⟨g, mem_nonZeroDivisors_iff_ne_zero.2 <| coe_ne_zero h⟩ · simp only [IsFractionRing.mk'_eq_div, coe_div, LaurentSeries.coe_algebraMap, coe_coe] rfl @@ -464,20 +489,21 @@ end RatFunc namespace LaurentSeries + open IsDedekindDomain.HeightOneSpectrum PowerSeries RatFunc -instance : Valued (LaurentSeries K) ℤₘ₀ := Valued.mk' (PowerSeries.idealX K).valuation +instance : Valued K⸨X⸩ ℤₘ₀ := Valued.mk' (PowerSeries.idealX K).valuation theorem valuation_X_pow (s : ℕ) : - Valued.v (((X : K⟦X⟧) : LaurentSeries K) ^ s) = Multiplicative.ofAdd (-(s : ℤ)) := by + Valued.v (((X : K⟦X⟧) : K⸨X⸩) ^ s) = Multiplicative.ofAdd (-(s : ℤ)) := by erw [map_pow, ← one_mul (s : ℤ), ← neg_mul (1 : ℤ) s, Int.ofAdd_mul, WithZero.coe_zpow, ofAdd_neg, WithZero.coe_inv, zpow_natCast, valuation_of_algebraMap, intValuation_toFun, intValuation_X, ofAdd_neg, WithZero.coe_inv, inv_pow] theorem valuation_single_zpow (s : ℤ) : - Valued.v (HahnSeries.single s (1 : K) : LaurentSeries K) = + Valued.v (HahnSeries.single s (1 : K) : K⸨X⸩) = Multiplicative.ofAdd (-(s : ℤ)) := by - have : Valued.v (1 : LaurentSeries K) = (1 : ℤₘ₀) := Valued.v.map_one + have : Valued.v (1 : K⸨X⸩) = (1 : ℤₘ₀) := Valued.v.map_one rw [← single_zero_one, ← add_neg_cancel s, ← mul_one 1, ← single_mul_single, map_mul, mul_eq_one_iff_eq_inv₀] at this · rw [this] @@ -490,18 +516,18 @@ theorem valuation_single_zpow (s : ℤ) : /- The coefficients of a power series vanish in degree strictly less than its valuation. -/ theorem coeff_zero_of_lt_intValuation {n d : ℕ} {f : K⟦X⟧} - (H : Valued.v (f : LaurentSeries K) ≤ Multiplicative.ofAdd (-d : ℤ)) : + (H : Valued.v (f : K⸨X⸩) ≤ Multiplicative.ofAdd (-d : ℤ)) : n < d → coeff K n f = 0 := by intro hnd apply (PowerSeries.X_pow_dvd_iff).mp _ n hnd erw [← span_singleton_dvd_span_singleton_iff_dvd, ← Ideal.span_singleton_pow, ← (intValuation_le_pow_iff_dvd (PowerSeries.idealX K) f d), ← intValuation_apply, - ← valuation_of_algebraMap (R := K⟦X⟧) (K := (LaurentSeries K))] + ← valuation_of_algebraMap (R := K⟦X⟧) (K := K⸨X⸩)] exact H /- The valuation of a power series is the order of the first non-zero coefficient. -/ theorem intValuation_le_iff_coeff_lt_eq_zero {d : ℕ} (f : K⟦X⟧) : - Valued.v (f : LaurentSeries K) ≤ Multiplicative.ofAdd (-d : ℤ) ↔ + Valued.v (f : K⸨X⸩) ≤ Multiplicative.ofAdd (-d : ℤ) ↔ ∀ n : ℕ, n < d → coeff K n f = 0 := by have : PowerSeries.X ^ d ∣ f ↔ ∀ n : ℕ, n < d → (PowerSeries.coeff K n) f = 0 := ⟨PowerSeries.X_pow_dvd_iff.mp, PowerSeries.X_pow_dvd_iff.mpr⟩ @@ -510,7 +536,7 @@ theorem intValuation_le_iff_coeff_lt_eq_zero {d : ℕ} (f : K⟦X⟧) : apply intValuation_le_pow_iff_dvd /- The coefficients of a Laurent series vanish in degree strictly less than its valuation. -/ -theorem coeff_zero_of_lt_valuation {n D : ℤ} {f : LaurentSeries K} +theorem coeff_zero_of_lt_valuation {n D : ℤ} {f : K⸨X⸩} (H : Valued.v f ≤ Multiplicative.ofAdd (-D)) : n < D → f.coeff n = 0 := by intro hnd by_cases h_n_ord : n < f.order @@ -538,7 +564,7 @@ theorem coeff_zero_of_lt_valuation {n D : ℤ} {f : LaurentSeries K} mul_le_mul_left (by simp only [ne_eq, WithZero.coe_ne_zero, not_false_iff, zero_lt_iff])] /- The valuation of a Laurent series is the order of the first non-zero coefficient. -/ -theorem valuation_le_iff_coeff_lt_eq_zero {D : ℤ} {f : LaurentSeries K} : +theorem valuation_le_iff_coeff_lt_eq_zero {D : ℤ} {f : K⸨X⸩} : Valued.v f ≤ ↑(Multiplicative.ofAdd (-D : ℤ)) ↔ ∀ n : ℤ, n < D → f.coeff n = 0 := by refine ⟨fun hnD n hn => coeff_zero_of_lt_valuation K hnD hn, fun h_val_f => ?_⟩ let F := powerSeriesPart f @@ -580,18 +606,18 @@ theorem valuation_le_iff_coeff_lt_eq_zero {D : ℤ} {f : LaurentSeries K} : /- Two Laurent series whose difference has small valuation have the same coefficients for small enough indices. -/ -theorem eq_coeff_of_valuation_sub_lt {d n : ℤ} {f g : LaurentSeries K} +theorem eq_coeff_of_valuation_sub_lt {d n : ℤ} {f g : K⸨X⸩} (H : Valued.v (g - f) ≤ ↑(Multiplicative.ofAdd (-d))) : n < d → g.coeff n = f.coeff n := by by_cases triv : g = f · exact fun _ => by rw [triv] · intro hn apply eq_of_sub_eq_zero - erw [← HahnSeries.sub_coeff] + rw [← HahnSeries.sub_coeff] apply coeff_zero_of_lt_valuation K H hn /- Every Laurent series of valuation less than `(1 : ℤₘ₀)` comes from a power series. -/ -theorem val_le_one_iff_eq_coe (f : LaurentSeries K) : Valued.v f ≤ (1 : ℤₘ₀) ↔ - ∃ F : PowerSeries K, F = f := by +theorem val_le_one_iff_eq_coe (f : K⸨X⸩) : Valued.v f ≤ (1 : ℤₘ₀) ↔ + ∃ F : K⟦X⟧, F = f := by rw [← WithZero.coe_one, ← ofAdd_zero, ← neg_zero, valuation_le_iff_coeff_lt_eq_zero] refine ⟨fun h => ⟨PowerSeries.mk fun n => f.coeff n, ?_⟩, ?_⟩ on_goal 1 => ext (_ | n) @@ -609,3 +635,169 @@ theorem val_le_one_iff_eq_coe (f : LaurentSeries K) : Valued.v f ≤ (1 : ℤₘ end LaurentSeries end AdicValuation +namespace LaurentSeries +section Complete + +open Filter + +open scoped Multiplicative + +variable {K : Type*} [Field K] + +/- Sending a Laurent series to its `d`-th coefficient is uniformly continuous (independently of the + uniformity with which `K` is endowed). -/ +theorem uniformContinuous_coeff {uK : UniformSpace K} (d : ℤ) : + UniformContinuous fun f : K⸨X⸩ ↦ f.coeff d := by + refine uniformContinuous_iff_eventually.mpr fun S hS ↦ eventually_iff_exists_mem.mpr ?_ + let γ : ℤₘ₀ˣ := Units.mk0 (↑(Multiplicative.ofAdd (-(d + 1)))) WithZero.coe_ne_zero + use {P | Valued.v (P.snd - P.fst) < ↑γ} + refine ⟨(Valued.hasBasis_uniformity K⸨X⸩ ℤₘ₀).mem_of_mem (by tauto), fun P hP ↦ ?_⟩ + rw [eq_coeff_of_valuation_sub_lt K (le_of_lt hP) (lt_add_one _)] + exact mem_uniformity_of_eq hS rfl + +/-- Since extracting coefficients is uniformly continuous, every Cauchy filter in +`K⸨X⸩` gives rise to a Cauchy filter in `K` for every `d : ℤ`, and such Cauchy filter +in `K` converges to a principal filter -/ +def Cauchy.coeff {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : ℤ → K := + let _ : UniformSpace K := ⊥ + fun d ↦ UniformSpace.DiscreteUnif.cauchyConst rfl <| hℱ.map (uniformContinuous_coeff d) + +theorem Cauchy.coeff_tendsto {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) (D : ℤ) : + Tendsto (fun f : K⸨X⸩ ↦ f.coeff D) ℱ (𝓟 {coeff hℱ D}) := + let _ : UniformSpace K := ⊥ + le_of_eq <| UniformSpace.DiscreteUnif.eq_const_of_cauchy (by rfl) + (hℱ.map (uniformContinuous_coeff D)) ▸ (principal_singleton _).symm + +/- For every Cauchy filter of Laurent series, there is a `N` such that the `n`-th coefficient +vanishes for all `n ≤ N` and almost all series in the filter. This is an auxiliary lemma used +to construct the limit of the Cauchy filter as a Laurent series, ensuring that the support of the +limit is `PWO`. +The result is true also for more general Hahn Series indexed over a partially ordered group `Γ` +beyond the special case `Γ = ℤ`, that corresponds to Laurent Series: nevertheless the proof below +does not generalise, as it relies on the study of the `X`-adic valuation attached to the height-one +prime `X`, and this is peculiar to the one-variable setting. In the future we should prove this +result in full generality and deduce the case `Γ = ℤ` from that one.-/ +lemma Cauchy.exists_lb_eventual_support {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : + ∃ N, ∀ᶠ f : K⸨X⸩ in ℱ, ∀ n < N, f.coeff n = (0 : K) := by + let entourage : Set (K⸨X⸩ × K⸨X⸩) := + {P : K⸨X⸩ × K⸨X⸩ | + Valued.v (P.snd - P.fst) < ((Multiplicative.ofAdd 0 : Multiplicative ℤ) : ℤₘ₀)} + let ζ := Units.mk0 (G₀ := ℤₘ₀) _ (WithZero.coe_ne_zero (a := (Multiplicative.ofAdd 0))) + obtain ⟨S, ⟨hS, ⟨T, ⟨hT, H⟩⟩⟩⟩ := mem_prod_iff.mp <| Filter.le_def.mp hℱ.2 entourage + <| (Valued.hasBasis_uniformity K⸨X⸩ ℤₘ₀).mem_of_mem (i := ζ) (by tauto) + obtain ⟨f, hf⟩ := forall_mem_nonempty_iff_neBot.mpr hℱ.1 (S ∩ T) (inter_mem_iff.mpr ⟨hS, hT⟩) + obtain ⟨N, hN⟩ : ∃ N : ℤ, ∀ g : K⸨X⸩, + Valued.v (g - f) ≤ ↑(Multiplicative.ofAdd (0 : ℤ)) → ∀ n < N, g.coeff n = 0 := by + by_cases hf : f = 0 + · refine ⟨0, fun x hg ↦ ?_⟩ + rw [hf, sub_zero] at hg + exact (valuation_le_iff_coeff_lt_eq_zero K).mp hg + · refine ⟨min (f.2.isWF.min (HahnSeries.support_nonempty_iff.mpr hf)) 0 - 1, fun _ hg n hn ↦ ?_⟩ + rw [eq_coeff_of_valuation_sub_lt K hg (d := 0)] + · exact Function.nmem_support.mp fun h ↦ + f.2.isWF.not_lt_min (HahnSeries.support_nonempty_iff.mpr hf) h + <| lt_trans hn <| Int.sub_one_lt_iff.mpr <| min_le_left _ _ + exact lt_of_lt_of_le hn <| le_of_lt (Int.sub_one_lt_of_le <| min_le_right _ _) + use N + apply mem_of_superset (inter_mem hS hT) + intro g hg + have h_prod : (f, g) ∈ entourage := Set.prod_mono (Set.inter_subset_left (t := T)) + (Set.inter_subset_right (s := S)) |>.trans H <| Set.mem_prod.mpr ⟨hf, hg⟩ + exact hN g (le_of_lt h_prod) + +/- The support of `Cauchy.coeff` has a lower bound. -/ +theorem Cauchy.exists_lb_support {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : + ∃ N, ∀ n, n < N → coeff hℱ n = 0 := by + let _ : UniformSpace K := ⊥ + obtain ⟨N, hN⟩ := exists_lb_eventual_support hℱ + refine ⟨N, fun n hn ↦ Ultrafilter.eq_of_le_pure (hℱ.map (uniformContinuous_coeff n)).1 + ((principal_singleton _).symm ▸ coeff_tendsto _ _) ?_⟩ + simp only [pure_zero, nonpos_iff] + apply Filter.mem_of_superset hN (fun _ ha ↦ ha _ hn) + +/- The support of `Cauchy.coeff` is bounded below -/ +theorem Cauchy.coeff_support_bddBelow {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : + BddBelow (coeff hℱ).support := by + refine ⟨(exists_lb_support hℱ).choose, fun d hd ↦ ?_⟩ + by_contra hNd + exact hd ((exists_lb_support hℱ).choose_spec d (not_le.mp hNd)) + +/-- To any Cauchy filter ℱ of `K⸨X⸩`, we can attach a laurent series that is the limit +of the filter. Its `d`-th coefficient is defined as the limit of `Cauchy.coeff hℱ d`, which is +again Cauchy but valued in the discrete space `K`. That sufficiently negative coefficients vanish +follows from `Cauchy.coeff_support_bddBelow` -/ +def Cauchy.limit {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : K⸨X⸩ := + HahnSeries.mk (coeff hℱ) <| Set.IsWF.isPWO (coeff_support_bddBelow _).wellFoundedOn_lt + +/- The following lemma shows that for every `d` smaller than the minimum between the integers +produced in `Cauchy.exists_lb_eventual_support` and `Cauchy.exists_lb_support`, for almost all +series in `ℱ` the `d`th coefficient coincides with the `d`th coefficient of `Cauchy.coeff hℱ`. -/ +theorem Cauchy.exists_lb_coeff_ne {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) : + ∃ N, ∀ᶠ f : K⸨X⸩ in ℱ, ∀ d < N, coeff hℱ d = f.coeff d := by + obtain ⟨⟨N₁, hN₁⟩, ⟨N₂, hN₂⟩⟩ := exists_lb_eventual_support hℱ, exists_lb_support hℱ + refine ⟨min N₁ N₂, ℱ.3 hN₁ fun _ hf d hd ↦ ?_⟩ + rw [hf d (lt_of_lt_of_le hd (min_le_left _ _)), hN₂ d (lt_of_lt_of_le hd (min_le_right _ _))] + +/- Given a Cauchy filter `ℱ` in the Laurent Series and a bound `D`, for almost all series in the +filter the coefficients below `D` coincide with `Caucy.coeff hℱ`-/ +theorem Cauchy.coeff_eventually_equal {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) {D : ℤ} : + ∀ᶠ f : K⸨X⸩ in ℱ, ∀ d, d < D → coeff hℱ d = f.coeff d := by + -- `φ` sends `d` to the set of Laurent Series having `d`th coefficient equal to `ℱ.coeff`. + let φ : ℤ → Set K⸨X⸩ := fun d ↦ {f | coeff hℱ d = f.coeff d} + have intersec₁ : + (⋂ n ∈ Set.Iio D, φ n) ⊆ {x : K⸨X⸩ | ∀ d : ℤ, d < D → coeff hℱ d = x.coeff d} := by + intro _ hf + simpa only [Set.mem_iInter] using hf + -- The goal is now to show that the intersection of all `φ d` (for `d < D`) is in `ℱ`. + let ℓ := (exists_lb_coeff_ne hℱ).choose + let N := max ℓ D + have intersec₂ : ⋂ n ∈ Set.Iio D, φ n ⊇ (⋂ n ∈ Set.Iio ℓ, φ n) ∩ (⋂ n ∈ Set.Icc ℓ N, φ n) := by + simp only [Set.mem_Iio, Set.mem_Icc, Set.subset_iInter_iff] + intro i hi x hx + simp only [Set.mem_inter_iff, Set.mem_iInter, and_imp] at hx + by_cases H : i < ℓ + exacts [hx.1 _ H, hx.2 _ (le_of_not_lt H) <| le_of_lt <| lt_max_of_lt_right hi] + suffices (⋂ n ∈ Set.Iio ℓ, φ n) ∩ (⋂ n ∈ Set.Icc ℓ N, φ n) ∈ ℱ by + exact ℱ.sets_of_superset this <| intersec₂.trans intersec₁ + /- To show that the intersection we have in sight is in `ℱ`, we use that it contains a double + intersection (an infinite and a finite one): by general properties of filters, we are reduced + to show that both terms are in `ℱ`, which is easy in light of their definition. -/ + · simp only [Set.mem_Iio, Set.mem_Ico, inter_mem_iff] + constructor + · have := (exists_lb_coeff_ne hℱ).choose_spec + rw [Filter.eventually_iff] at this + convert this + ext + simp only [Set.mem_iInter, Set.mem_setOf_eq]; rfl + · rw [biInter_mem (Set.finite_Icc ℓ N)] + intro _ _ + apply coeff_tendsto hℱ + simp only [principal_singleton, mem_pure]; rfl + + +open scoped Topology + +/- The main result showing that the Cauchy filter tends to the `Cauchy.limit`-/ +theorem Cauchy.eventually_mem_nhds {ℱ : Filter K⸨X⸩} (hℱ : Cauchy ℱ) + {U : Set K⸨X⸩} (hU : U ∈ 𝓝 (Cauchy.limit hℱ)) : ∀ᶠ f in ℱ, f ∈ U := by + obtain ⟨γ, hU₁⟩ := Valued.mem_nhds.mp hU + suffices ∀ᶠ f in ℱ, f ∈ {y : K⸨X⸩ | Valued.v (y - limit hℱ) < ↑γ} by + apply this.mono fun _ hf ↦ hU₁ hf + set D := -(Multiplicative.toAdd (WithZero.unzero γ.ne_zero) - 1) with hD₀ + have hD : ((Multiplicative.ofAdd (-D) : Multiplicative ℤ) : ℤₘ₀) < γ := by + rw [← WithZero.coe_unzero γ.ne_zero, WithZero.coe_lt_coe, hD₀, neg_neg, ofAdd_sub, + ofAdd_toAdd, div_lt_comm, div_self', ← ofAdd_zero, Multiplicative.ofAdd_lt] + exact zero_lt_one + apply coeff_eventually_equal (D := D) hℱ |>.mono + intro _ hf + apply lt_of_le_of_lt (valuation_le_iff_coeff_lt_eq_zero K |>.mpr _) hD + intro n hn + rw [HahnSeries.sub_coeff, sub_eq_zero, hf n hn |>.symm]; rfl + +/- Laurent Series with coefficients in a field are complete w.r.t. the `X`-adic valuation -/ +instance instLaurentSeriesComplete : CompleteSpace K⸨X⸩ := + ⟨fun hℱ ↦ ⟨Cauchy.limit hℱ, fun _ hS ↦ Cauchy.eventually_mem_nhds hℱ hS⟩⟩ + +end Complete + +end LaurentSeries diff --git a/Mathlib/RingTheory/LittleWedderburn.lean b/Mathlib/RingTheory/LittleWedderburn.lean index 24f9b1cce5f40..42f44f6d9f529 100644 --- a/Mathlib/RingTheory/LittleWedderburn.lean +++ b/Mathlib/RingTheory/LittleWedderburn.lean @@ -48,7 +48,7 @@ private def InductionHyp : Prop := namespace InductionHyp -open FiniteDimensional Polynomial +open Module Polynomial variable {D} diff --git a/Mathlib/RingTheory/LocalProperties/Basic.lean b/Mathlib/RingTheory/LocalProperties/Basic.lean index 0141196dfed77..a3ece3c9a9726 100644 --- a/Mathlib/RingTheory/LocalProperties/Basic.lean +++ b/Mathlib/RingTheory/LocalProperties/Basic.lean @@ -240,8 +240,8 @@ theorem RingHom.PropertyIsLocal.ofLocalizationSpan (hP : RingHom.PropertyIsLocal rintro ⟨_, r, hr, rfl⟩ rw [← IsLocalization.map_comp (M := Submonoid.powers r) (S := Localization.Away r) (T := Submonoid.powers (f r))] - apply hP.StableUnderCompositionWithLocalizationAway.right _ r - exact hs' ⟨r, hr⟩ + · apply hP.StableUnderCompositionWithLocalizationAway.right _ r + exact hs' ⟨r, hr⟩ lemma RingHom.OfLocalizationSpanTarget.ofIsLocalization (hP : RingHom.OfLocalizationSpanTarget P) (hP' : RingHom.RespectsIso P) diff --git a/Mathlib/RingTheory/LocalRing/Module.lean b/Mathlib/RingTheory/LocalRing/Module.lean index 06103c98b607e..332bccee7c8f5 100644 --- a/Mathlib/RingTheory/LocalRing/Module.lean +++ b/Mathlib/RingTheory/LocalRing/Module.lean @@ -171,26 +171,28 @@ theorem free_of_maximalIdeal_rTensor_injective [Module.FinitePresentation R M] refine ⟨?_, this⟩ rw [← LinearMap.ker_eq_bot (M := k ⊗[R] (I →₀ R)) (f := i.baseChange k), ← Submodule.finrank_eq_zero (R := k) (M := k ⊗[R] (I →₀ R)), - ← Nat.add_right_inj (n := FiniteDimensional.finrank k (LinearMap.range <| i.baseChange k)), + ← Nat.add_right_inj (n := Module.finrank k (LinearMap.range <| i.baseChange k)), LinearMap.finrank_range_add_finrank_ker (V := k ⊗[R] (I →₀ R)), LinearMap.range_eq_top.mpr this, finrank_top] - simp only [FiniteDimensional.finrank_tensorProduct, FiniteDimensional.finrank_self, - FiniteDimensional.finrank_finsupp_self, one_mul, add_zero] - rw [FiniteDimensional.finrank_eq_card_chooseBasisIndex] + simp only [Module.finrank_tensorProduct, Module.finrank_self, + Module.finrank_finsupp_self, one_mul, add_zero] + rw [Module.finrank_eq_card_chooseBasisIndex] -- On the other hand, `m ⊗ M → M` injective => `Tor₁(k, M) = 0` => `k ⊗ ker(i) → kᴵ` injective. - have := @lTensor_injective_of_exact_of_exact_of_rTensor_injective - (N₁ := LinearMap.ker i) (N₂ := I →₀ R) (N₃ := M) - (f₁ := (𝔪).subtype) (f₂ := Submodule.mkQ 𝔪) inferInstance inferInstance inferInstance - inferInstance inferInstance inferInstance intro x - apply @this (LinearMap.ker i).subtype i (LinearMap.exact_subtype_mkQ 𝔪) - (Submodule.mkQ_surjective _) (LinearMap.exact_subtype_ker_map i) hi H - (Module.Flat.lTensor_preserves_injective_linearMap _ Subtype.val_injective) - apply hi'.injective - rw [LinearMap.baseChange_eq_ltensor] - erw [← LinearMap.comp_apply (i.lTensor k), ← LinearMap.lTensor_comp] - rw [(LinearMap.exact_subtype_ker_map i).linearMap_comp_eq_zero] - simp only [LinearMap.lTensor_zero, LinearMap.zero_apply, map_zero] + refine lTensor_injective_of_exact_of_exact_of_rTensor_injective + (N₁ := LinearMap.ker i) (N₂ := I →₀ R) (N₃ := M) + (f₁ := (𝔪).subtype) (f₂ := Submodule.mkQ 𝔪) + (g₁ := (LinearMap.ker i).subtype) (g₂ := i) (LinearMap.exact_subtype_mkQ 𝔪) + (Submodule.mkQ_surjective _) (LinearMap.exact_subtype_ker_map i) hi H ?_ ?_ + · apply Module.Flat.lTensor_preserves_injective_linearMap + (N := LinearMap.ker i) (N' := I →₀ R) + (L := (LinearMap.ker i).subtype) + exact Subtype.val_injective + · apply hi'.injective + rw [LinearMap.baseChange_eq_ltensor] + erw [← LinearMap.comp_apply (i.lTensor k), ← LinearMap.lTensor_comp] + rw [(LinearMap.exact_subtype_ker_map i).linearMap_comp_eq_zero] + simp only [LinearMap.lTensor_zero, LinearMap.zero_apply, map_zero] -- TODO: Generalise this to finite free modules. theorem free_of_flat_of_localRing [Module.FinitePresentation R P] [Module.Flat R P] : diff --git a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean index 7dd4c8dade367..4b44e62f3ee66 100644 --- a/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean +++ b/Mathlib/RingTheory/LocalRing/RingHom/Basic.lean @@ -3,7 +3,7 @@ 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 -/ -import Mathlib.RingTheory.LocalRing.RingHom.Defs +import Mathlib.Algebra.Group.Units.Hom import Mathlib.RingTheory.LocalRing.MaximalIdeal.Defs import Mathlib.RingTheory.Ideal.Maps import Mathlib.Logic.Equiv.TransferInstance @@ -24,34 +24,14 @@ variable [Semiring R] [Semiring S] [Semiring T] instance isLocalRingHom_id (R : Type*) [Semiring R] : IsLocalRingHom (RingHom.id R) where map_nonunit _ := id -@[simp] -theorem isUnit_map_iff (f : R →+* S) [IsLocalRingHom f] (a) : IsUnit (f a) ↔ IsUnit a := - ⟨IsLocalRingHom.map_nonunit a, f.isUnit_map⟩ - --- Porting note: as this can be proved by other `simp` lemmas, this is marked as high priority. -@[simp (high)] -theorem map_mem_nonunits_iff (f : R →+* S) [IsLocalRingHom f] (a) : - f a ∈ nonunits S ↔ a ∈ nonunits R := - ⟨fun h ha => h <| (isUnit_map_iff f a).mpr ha, fun h ha => h <| (isUnit_map_iff f a).mp ha⟩ - -instance isLocalRingHom_comp (g : S →+* T) (f : R →+* S) [IsLocalRingHom g] [IsLocalRingHom f] : - IsLocalRingHom (g.comp f) where - map_nonunit a := IsLocalRingHom.map_nonunit a ∘ IsLocalRingHom.map_nonunit (f a) - -instance isLocalRingHom_equiv (f : R ≃+* S) : IsLocalRingHom (f : R →+* S) where - map_nonunit a ha := by - convert RingHom.isUnit_map (f.symm : S →+* R) ha - exact (RingEquiv.symm_apply_apply f a).symm - -@[simp] -theorem isUnit_of_map_unit (f : R →+* S) [IsLocalRingHom f] (a) (h : IsUnit (f a)) : IsUnit a := - IsLocalRingHom.map_nonunit a h - -theorem of_irreducible_map (f : R →+* S) [h : IsLocalRingHom f] {x} (hfx : Irreducible (f x)) : - Irreducible x := - ⟨fun h => hfx.not_unit <| IsUnit.map f h, fun p q hx => - let ⟨H⟩ := h - Or.imp (H p) (H q) <| hfx.isUnit_or_isUnit <| f.map_mul p q ▸ congr_arg f hx⟩ +-- see note [lower instance priority] +instance (priority := 100) isLocalRingHom_toRingHom {F : Type*} [FunLike F R S] + [RingHomClass F R S] (f : F) [IsLocalRingHom f] : IsLocalRingHom (f : R →+* S) := + ⟨IsLocalRingHom.map_nonunit (f := f)⟩ + +instance RingHom.isLocalRingHom_comp (g : S →+* T) (f : R →+* S) [IsLocalRingHom g] + [IsLocalRingHom f] : IsLocalRingHom (g.comp f) where + map_nonunit a := IsLocalRingHom.map_nonunit a ∘ IsLocalRingHom.map_nonunit (f := g) (f a) theorem isLocalRingHom_of_comp (f : R →+* S) (g : S →+* T) [IsLocalRingHom (g.comp f)] : IsLocalRingHom f := diff --git a/Mathlib/RingTheory/LocalRing/RingHom/Defs.lean b/Mathlib/RingTheory/LocalRing/RingHom/Defs.lean deleted file mode 100644 index 5949c6dcab0ff..0000000000000 --- a/Mathlib/RingTheory/LocalRing/RingHom/Defs.lean +++ /dev/null @@ -1,28 +0,0 @@ -/- -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 --/ -import Mathlib.Algebra.Group.Units -import Mathlib.Algebra.Ring.Hom.Defs - -/-! - -# Local rings homomorphisms - -We Define local ring homomorhpisms. - -## Main definitions - -* `IsLocalRingHom`: A predicate on semiring homomorphisms, requiring that it maps nonunits - to nonunits. For local rings, this means that the image of the unique maximal ideal is again - contained in the unique maximal ideal. - --/ - -/-- A local ring homomorphism is a homomorphism `f` between local rings such that `a` in the domain - is a unit if `f a` is a unit for any `a`. See `LocalRing.local_hom_TFAE` for other equivalent - definitions. -/ -class IsLocalRingHom {R S : Type*} [Semiring R] [Semiring S] (f : R →+* S) : Prop where - /-- A local ring homomorphism `f : R ⟶ S` will send nonunits of `R` to nonunits of `S`. -/ - map_nonunit : ∀ a, IsUnit (f a) → IsUnit a diff --git a/Mathlib/RingTheory/Localization/AtPrime.lean b/Mathlib/RingTheory/Localization/AtPrime.lean index a52c0df699d51..5b122fb2d696c 100644 --- a/Mathlib/RingTheory/Localization/AtPrime.lean +++ b/Mathlib/RingTheory/Localization/AtPrime.lean @@ -5,7 +5,7 @@ Authors: Kenny Lau, Mario Carneiro, Johan Commelin, Amelia Livingston, Anne Baan -/ import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic -import Mathlib.RingTheory.LocalRing.RingHom.Defs +import Mathlib.Algebra.Group.Units.Hom /-! # Localizations of commutative rings at the complement of a prime ideal diff --git a/Mathlib/RingTheory/Localization/Away/Basic.lean b/Mathlib/RingTheory/Localization/Away/Basic.lean index c41d650a75ef4..13a452b4b4e86 100644 --- a/Mathlib/RingTheory/Localization/Away/Basic.lean +++ b/Mathlib/RingTheory/Localization/Away/Basic.lean @@ -38,7 +38,8 @@ section Away variable (x : R) /-- Given `x : R`, the typeclass `IsLocalization.Away x S` states that `S` is -isomorphic to the localization of `R` at the submonoid generated by `x`. -/ +isomorphic to the localization of `R` at the submonoid generated by `x`. +See `IsLocalization.Away.mk` for a specialized constructor. -/ abbrev Away (S : Type*) [CommSemiring S] [Algebra R S] := IsLocalization (Submonoid.powers x) S @@ -68,6 +69,58 @@ lemma sec_spec (s : S) : s * (algebraMap R S) (x ^ (IsLocalization.Away.sec x s) congr exact (IsLocalization.sec (Submonoid.powers x) s).2.property.choose_spec +lemma algebraMap_pow_isUnit (n : ℕ) : IsUnit (algebraMap R S x ^ n) := + IsUnit.pow _ <| IsLocalization.map_units _ (⟨x, 1, by simp⟩ : Submonoid.powers x) + +lemma algebraMap_isUnit : IsUnit (algebraMap R S x) := + IsLocalization.map_units _ (⟨x, 1, by simp⟩ : Submonoid.powers x) + +lemma surj (z : S) : ∃ (n : ℕ) (a : R), z * algebraMap R S x ^ n = algebraMap R S a := by + obtain ⟨⟨a, ⟨-, n, rfl⟩⟩, h⟩ := IsLocalization.surj (Submonoid.powers x) z + use n, a + simpa using h + +lemma exists_of_eq {a b : R} (h : algebraMap R S a = algebraMap R S b) : + ∃ (n : ℕ), x ^ n * a = x ^ n * b := by + obtain ⟨⟨-, n, rfl⟩, hx⟩ := IsLocalization.exists_of_eq (M := Submonoid.powers x) h + use n + +/-- Specialized constructor for `IsLocalization.Away`. -/ +lemma mk (r : R) (map_unit : IsUnit (algebraMap R S r)) + (surj : ∀ s, ∃ (n : ℕ) (a : R), s * algebraMap R S r ^ n = algebraMap R S a) + (exists_of_eq : ∀ a b, algebraMap R S a = algebraMap R S b → ∃ (n : ℕ), r ^ n * a = r ^ n * b) : + IsLocalization.Away r S where + map_units' := by + rintro ⟨-, n, rfl⟩ + simp only [map_pow] + exact IsUnit.pow _ map_unit + surj' z := by + obtain ⟨n, a, hn⟩ := surj z + use ⟨a, ⟨r ^ n, n, rfl⟩⟩ + simpa using hn + exists_of_eq {x y} h := by + obtain ⟨n, hn⟩ := exists_of_eq x y h + use ⟨r ^ n, n, rfl⟩ + +lemma of_associated {r r' : R} (h : Associated r r') [IsLocalization.Away r S] : + IsLocalization.Away r' S := by + obtain ⟨u, rfl⟩ := h + refine mk _ ?_ (fun s ↦ ?_) (fun a b hab ↦ ?_) + · simp [algebraMap_isUnit r, IsUnit.map _ u.isUnit] + · obtain ⟨n, a, hn⟩ := surj r s + use n, a * u ^ n + simp [mul_pow, ← mul_assoc, hn] + · obtain ⟨n, hn⟩ := exists_of_eq r hab + use n + rw [mul_pow, mul_comm (r ^ n), mul_assoc, mul_assoc, hn] + +/-- If `r` and `r'` are associated elements of `R`, an `R`-algebra `S` +is the localization of `R` away from `r` if and only of it is the localization of `R` away from +`r'`. -/ +lemma iff_of_associated {r r' : R} (h : Associated r r') : + IsLocalization.Away r S ↔ IsLocalization.Away r' S := + ⟨fun _ ↦ IsLocalization.Away.of_associated h, fun _ ↦ IsLocalization.Away.of_associated h.symm⟩ + variable {g : R →+* P} /-- Given `x : R`, a localization map `F : R →+* S` away from `x`, and a map of `CommSemiring`s @@ -146,6 +199,53 @@ lemma mapₐ_surjective_of_surjective {f : A →ₐ[R] B} (a : A) [Away a Aₚ] end Algebra +/-- Localizing the localization of `R` at `x` at the image of `y` is the same as localizing +`R` at `y * x`. See `IsLocalization.Away.mul'` for the `x * y` version. -/ +lemma mul (T : Type*) [CommSemiring T] [Algebra S T] + [Algebra R T] [IsScalarTower R S T] (x y : R) + [IsLocalization.Away x S] [IsLocalization.Away (algebraMap R S y) T] : + IsLocalization.Away (y * x) T := by + refine mk _ ?_ (fun z ↦ ?_) (fun a b h ↦ ?_) + · simp only [map_mul, IsUnit.mul_iff, IsScalarTower.algebraMap_apply R S T] + exact ⟨algebraMap_isUnit _, IsUnit.map _ (algebraMap_isUnit x)⟩ + · obtain ⟨m, p, hpq⟩ := surj (algebraMap R S y) z + obtain ⟨n, a, hab⟩ := surj x p + use m + n, a * x ^ m * y ^ n + simp only [mul_pow, pow_add, map_pow, map_mul, ← mul_assoc, hpq, + IsScalarTower.algebraMap_apply R S T, ← hab] + ring + · repeat rw [IsScalarTower.algebraMap_apply R S T] at h + obtain ⟨n, hn⟩ := exists_of_eq (algebraMap R S y) h + simp only [← map_pow, ← map_mul, ← map_mul] at hn + obtain ⟨m, hm⟩ := exists_of_eq x hn + use n + m + convert_to y ^ m * x ^ n * (x ^ m * (y ^ n * a)) = y ^ m * x ^ n * (x ^ m * (y ^ n * b)) + · ring + · ring + · rw [hm] + +/-- Localizing the localization of `R` at `x` at the image of `y` is the same as localizing +`R` at `x * y`. See `IsLocalization.Away.mul` for the `y * x` version. -/ +lemma mul' (T : Type*) [CommSemiring T] [Algebra S T] [Algebra R T] [IsScalarTower R S T] (x y : R) + [IsLocalization.Away x S] [IsLocalization.Away (algebraMap R S y) T] : + IsLocalization.Away (x * y) T := + mul_comm x y ▸ mul S T x y + +/-- If `S₁` is the localization of `R` away from `f` and `S₂` is the localization away from `g`, +then any localization `T` of `S₂` away from `f` is also a localization of `S₁` away from `g`. -/ +lemma commutes {R : Type*} [CommSemiring R] (S₁ S₂ T : Type*) [CommSemiring S₁] + [CommSemiring S₂] [CommSemiring T] [Algebra R S₁] [Algebra R S₂] [Algebra R T] [Algebra S₁ T] + [Algebra S₂ T] [IsScalarTower R S₁ T] [IsScalarTower R S₂ T] (x y : R) + [IsLocalization.Away x S₁] [IsLocalization.Away y S₂] + [IsLocalization.Away (algebraMap R S₂ x) T] : + IsLocalization.Away (algebraMap R S₁ y) T := by + haveI : IsLocalization (Algebra.algebraMapSubmonoid S₂ (Submonoid.powers x)) T := by + simp only [Algebra.algebraMapSubmonoid, Submonoid.map_powers] + infer_instance + convert IsLocalization.commutes S₁ S₂ T (Submonoid.powers x) (Submonoid.powers y) + ext x + simp [Algebra.algebraMapSubmonoid] + end Away end Away @@ -175,7 +275,7 @@ theorem away_of_isUnit_of_bijective {R : Type*} (S : Type*) [CommRing R] [CommRi obtain ⟨z', rfl⟩ := H.2 z exact ⟨⟨z', 1⟩, by simp⟩ exists_of_eq := fun {x y} => by - erw [H.1.eq_iff] + rw [H.1.eq_iff] rintro rfl exact ⟨1, rfl⟩ } diff --git a/Mathlib/RingTheory/Localization/Away/Lemmas.lean b/Mathlib/RingTheory/Localization/Away/Lemmas.lean new file mode 100644 index 0000000000000..640763c874cbe --- /dev/null +++ b/Mathlib/RingTheory/Localization/Away/Lemmas.lean @@ -0,0 +1,66 @@ +/- +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.RingTheory.Localization.Away.Basic +import Mathlib.RingTheory.Localization.Submodule + +/-! +# More lemmas on localization away + +This file contains lemmas on localization away from an element requiring more imports. + +-/ + +variable {R : Type*} [CommRing R] + +namespace IsLocalization + +namespace Away + +/-- Given a set `s` in a ring `R` and for every `t : s` a set `p t` of fractions in +a localization of `R` at `t`, this is the function sending a pair `(t, y)`, with +`t : s` and `y : t a`, to `t` multiplied with a numerator of `y`. The range +of this function spans the unit ideal, if `s` and every `p t` do. -/ +noncomputable def mulNumerator (s : Set R) + {Rₜ : s → Type*} [∀ t, CommRing (Rₜ t)] [∀ t, Algebra R (Rₜ t)] + [∀ t, IsLocalization.Away t.val (Rₜ t)] + (p : (t : s) → Set (Rₜ t)) (x : (t : s) × p t) : R := + x.1 * (IsLocalization.Away.sec x.1.1 x.2.1).1 + +lemma span_range_mulNumerator_eq_top {s : Set R} + (hsone : Ideal.span s = ⊤) {Rₜ : s → Type*} [∀ t, CommRing (Rₜ t)] [∀ t, Algebra R (Rₜ t)] + [∀ t, IsLocalization.Away t.val (Rₜ t)] + {p : (t : s) → Set (Rₜ t)} (htone : ∀ (r : s), Ideal.span (p r) = ⊤) : + Ideal.span (Set.range (IsLocalization.Away.mulNumerator s p)) = ⊤ := by + rw [← Ideal.radical_eq_top, eq_top_iff, ← hsone, Ideal.span_le] + intro a ha + haveI : IsLocalization (Submonoid.powers a) (Rₜ ⟨a, ha⟩) := + inferInstanceAs <| IsLocalization.Away (⟨a, ha⟩ : s).val (Rₜ ⟨a, ha⟩) + have h₁ : Ideal.span (p ⟨a, ha⟩) ≤ Ideal.span + (algebraMap R (Rₜ ⟨a, ha⟩) '' Set.range (IsLocalization.Away.mulNumerator s p)) := by + rw [Ideal.span_le] + intro x hx + rw [SetLike.mem_coe, IsLocalization.mem_span_map (Submonoid.powers a)] + refine ⟨a * (IsLocalization.Away.sec a x).1, Ideal.subset_span ⟨⟨⟨a, ha⟩, ⟨x, hx⟩⟩, rfl⟩, ?_⟩ + use ⟨a ^ ((IsLocalization.Away.sec a x).2 + 1), _, rfl⟩ + rw [IsLocalization.eq_mk'_iff_mul_eq, map_pow, map_mul, ← map_pow, pow_add, map_mul, + ← mul_assoc, IsLocalization.Away.sec_spec a x, mul_comm, pow_one] + have h₂ : IsLocalization.mk' (Rₜ ⟨a, ha⟩) 1 (1 : Submonoid.powers a) ∈ Ideal.span + (algebraMap R (Rₜ ⟨a, ha⟩) '' + (Set.range <| IsLocalization.Away.mulNumerator s p)) := by + rw [IsLocalization.mk'_one] + apply h₁ + simp [htone] + rw [IsLocalization.mem_span_map (Submonoid.powers a)] at h₂ + obtain ⟨y, hy, ⟨-, m, rfl⟩, hyz⟩ := h₂ + rw [IsLocalization.eq] at hyz + obtain ⟨⟨-, n, rfl⟩, hc⟩ := hyz + simp only [← mul_assoc, OneMemClass.coe_one, one_mul, mul_one] at hc + use n + m + simpa [pow_add, hc] using Ideal.mul_mem_left _ _ hy + +end Away + +end IsLocalization diff --git a/Mathlib/RingTheory/Localization/Basic.lean b/Mathlib/RingTheory/Localization/Basic.lean index b6a8a172936cf..71f588f147216 100644 --- a/Mathlib/RingTheory/Localization/Basic.lean +++ b/Mathlib/RingTheory/Localization/Basic.lean @@ -828,6 +828,48 @@ theorem map_nonZeroDivisors_le [IsLocalization M S] : (nonZeroDivisors R).map (algebraMap R S) ≤ nonZeroDivisors S := Submonoid.map_le_iff_le_comap.mpr (nonZeroDivisors_le_comap M S) +/-- If `S₁` is the localization of `R` at `M₁` and `S₂` is the localization of +`R` at `M₂`, then every localization `T` of `S₂` at `M₁` is also a localization of +`S₁` at `M₂`, in other words `M₁⁻¹M₂⁻¹R` can be identified with `M₂⁻¹M₁⁻¹R`. -/ +lemma commutes (S₁ S₂ T : Type*) [CommSemiring S₁] + [CommSemiring S₂] [CommSemiring T] [Algebra R S₁] [Algebra R S₂] [Algebra R T] [Algebra S₁ T] + [Algebra S₂ T] [IsScalarTower R S₁ T] [IsScalarTower R S₂ T] (M₁ M₂ : Submonoid R) + [IsLocalization M₁ S₁] [IsLocalization M₂ S₂] + [IsLocalization (Algebra.algebraMapSubmonoid S₂ M₁) T] : + IsLocalization (Algebra.algebraMapSubmonoid S₁ M₂) T where + map_units' := by + rintro ⟨m, ⟨a, ha, rfl⟩⟩ + rw [← IsScalarTower.algebraMap_apply, IsScalarTower.algebraMap_apply R S₂ T] + exact IsUnit.map _ (IsLocalization.map_units' ⟨a, ha⟩) + surj' a := by + obtain ⟨⟨y, -, m, hm, rfl⟩, hy⟩ := surj (M := Algebra.algebraMapSubmonoid S₂ M₁) a + rw [← IsScalarTower.algebraMap_apply, IsScalarTower.algebraMap_apply R S₁ T] at hy + obtain ⟨⟨z, n, hn⟩, hz⟩ := IsLocalization.surj (M := M₂) y + have hunit : IsUnit (algebraMap R S₁ m) := map_units' ⟨m, hm⟩ + use ⟨algebraMap R S₁ z * hunit.unit⁻¹, ⟨algebraMap R S₁ n, n, hn, rfl⟩⟩ + rw [map_mul, ← IsScalarTower.algebraMap_apply, IsScalarTower.algebraMap_apply R S₂ T] + conv_rhs => rw [← IsScalarTower.algebraMap_apply] + rw [IsScalarTower.algebraMap_apply R S₂ T, ← hz, map_mul, ← hy] + convert_to _ = a * (algebraMap S₂ T) ((algebraMap R S₂) n) * + (algebraMap S₁ T) (((algebraMap R S₁) m) * hunit.unit⁻¹.val) + · rw [map_mul] + ring + simp + exists_of_eq {x y} hxy := by + obtain ⟨r, s, d, hr, hs⟩ := IsLocalization.surj₂ M₁ S₁ x y + apply_fun (· * algebraMap S₁ T (algebraMap R S₁ d)) at hxy + simp_rw [← map_mul, hr, hs, ← IsScalarTower.algebraMap_apply, + IsScalarTower.algebraMap_apply R S₂ T] at hxy + obtain ⟨⟨-, c, hmc, rfl⟩, hc⟩ := exists_of_eq (M := Algebra.algebraMapSubmonoid S₂ M₁) hxy + simp_rw [← map_mul] at hc + obtain ⟨a, ha⟩ := IsLocalization.exists_of_eq (M := M₂) hc + use ⟨algebraMap R S₁ a, a, a.property, rfl⟩ + apply (map_units S₁ d).mul_right_cancel + rw [mul_assoc, hr, mul_assoc, hs] + apply (map_units S₁ ⟨c, hmc⟩).mul_right_cancel + rw [← map_mul, ← map_mul, mul_assoc, mul_comm _ c, ha, map_mul, map_mul] + ring + end IsLocalization namespace Localization @@ -1059,7 +1101,7 @@ theorem IsField.localization_map_bijective {R Rₘ : Type*} [CommRing R] [CommRi refine ⟨IsLocalization.injective _ hM, fun x => ?_⟩ obtain ⟨r, ⟨m, hm⟩, rfl⟩ := mk'_surjective M x obtain ⟨n, hn⟩ := hR.mul_inv_cancel (nonZeroDivisors.ne_zero <| hM hm) - exact ⟨r * n, by erw [eq_mk'_iff_mul_eq, ← map_mul, mul_assoc, _root_.mul_comm n, hn, mul_one]⟩ + exact ⟨r * n, by rw [eq_mk'_iff_mul_eq, ← map_mul, mul_assoc, _root_.mul_comm n, hn, mul_one]⟩ /-- If `R` is a field, then localizing at a submonoid not containing `0` adds no new elements. -/ theorem Field.localization_map_bijective {K Kₘ : Type*} [Field K] [CommRing Kₘ] {M : Submonoid K} diff --git a/Mathlib/RingTheory/Localization/Cardinality.lean b/Mathlib/RingTheory/Localization/Cardinality.lean index bc4e2828f5f1b..1c11c039219dd 100644 --- a/Mathlib/RingTheory/Localization/Cardinality.lean +++ b/Mathlib/RingTheory/Localization/Cardinality.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Eric Rodriguez. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Rodriguez -/ -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.RingTheory.Artinian /-! @@ -36,7 +36,7 @@ theorem card_le (S : Submonoid R) [IsLocalization S L] : #L ≤ #R := by classical cases fintypeOrInfinite R · exact Cardinal.mk_le_of_surjective (IsArtinianRing.localization_surjective S _) - erw [← Cardinal.mul_eq_self <| Cardinal.aleph0_le_mk R] + rw [← Cardinal.mul_eq_self <| Cardinal.aleph0_le_mk R] set f : R × R → L := fun aa => IsLocalization.mk' _ aa.1 (if h : aa.2 ∈ S then ⟨aa.2, h⟩ else 1) refine @Cardinal.mk_le_of_surjective _ _ f fun a => ?_ obtain ⟨x, y, h⟩ := IsLocalization.mk'_surjective S a diff --git a/Mathlib/RingTheory/Localization/FractionRing.lean b/Mathlib/RingTheory/Localization/FractionRing.lean index 1960bbcd7e01d..f4b231a725789 100644 --- a/Mathlib/RingTheory/Localization/FractionRing.lean +++ b/Mathlib/RingTheory/Localization/FractionRing.lean @@ -132,7 +132,7 @@ noncomputable abbrev toField : Field K where lemma surjective_iff_isField [IsDomain R] : Function.Surjective (algebraMap R K) ↔ IsField R where mp h := (RingEquiv.ofBijective (algebraMap R K) - ⟨IsFractionRing.injective R K, h⟩).toMulEquiv.isField (IsFractionRing.toField R).toIsField + ⟨IsFractionRing.injective R K, h⟩).toMulEquiv.isField _ (IsFractionRing.toField R).toIsField mpr h := letI := h.toField (IsLocalization.atUnits R _ (S := K) diff --git a/Mathlib/RingTheory/Localization/Integral.lean b/Mathlib/RingTheory/Localization/Integral.lean index c2f2e77d4b431..2c8a8157c19db 100644 --- a/Mathlib/RingTheory/Localization/Integral.lean +++ b/Mathlib/RingTheory/Localization/Integral.lean @@ -182,7 +182,7 @@ theorem RingHom.isIntegralElem_localization_at_leadingCoeff {R S : Type*} [CommR refine fun hfp => zero_ne_one (_root_.trans (zero_mul b).symm (hfp ▸ hb) : (0 : Rₘ) = 1) · refine eval₂_mul_eq_zero_of_left _ _ _ ?_ - erw [eval₂_map, IsLocalization.map_comp, ← hom_eval₂ _ f (algebraMap S Sₘ) x] + rw [eval₂_map, IsLocalization.map_comp, ← hom_eval₂ _ f (algebraMap S Sₘ) x] exact _root_.trans (congr_arg (algebraMap S Sₘ) hf) (RingHom.map_zero _) /-- Given a particular witness to an element being algebraic over an algebra `R → S`, diff --git a/Mathlib/RingTheory/Localization/LocalizationLocalization.lean b/Mathlib/RingTheory/Localization/LocalizationLocalization.lean index a8796591c0f6c..62db6f2a12761 100644 --- a/Mathlib/RingTheory/Localization/LocalizationLocalization.lean +++ b/Mathlib/RingTheory/Localization/LocalizationLocalization.lean @@ -231,7 +231,7 @@ theorem isLocalization_of_is_exists_mul_mem (M N : Submonoid R) [IsLocalization { map_units' := fun y => by obtain ⟨m, hm⟩ := h' y have := IsLocalization.map_units S ⟨_, hm⟩ - erw [map_mul] at this + rw [map_mul] at this exact (IsUnit.mul_iff.mp this).2 surj' := fun z => by obtain ⟨⟨y, s⟩, e⟩ := IsLocalization.surj M z diff --git a/Mathlib/RingTheory/Localization/NumDen.lean b/Mathlib/RingTheory/Localization/NumDen.lean index 07a87d3552ccd..d9d828d11ba3f 100644 --- a/Mathlib/RingTheory/Localization/NumDen.lean +++ b/Mathlib/RingTheory/Localization/NumDen.lean @@ -42,7 +42,7 @@ theorem exists_reduced_fraction (x : K) : refine ⟨a', ⟨b', b'_nonzero⟩, no_factor, ?_⟩ refine mul_left_cancel₀ (IsFractionRing.to_map_ne_zero_of_mem_nonZeroDivisors b_nonzero) ?_ simp only [Subtype.coe_mk, RingHom.map_mul, Algebra.smul_def] at * - erw [← hab, mul_assoc, mk'_spec' _ a' ⟨b', b'_nonzero⟩] + rw [← hab, mul_assoc, mk'_spec' _ a' ⟨b', b'_nonzero⟩] /-- `f.num x` is the numerator of `x : f.codomain` as a reduced fraction. -/ noncomputable def num (x : K) : A := diff --git a/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean b/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean index 4d835d7c912f4..717b6f8ac0bf2 100644 --- a/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean +++ b/Mathlib/RingTheory/MvPolynomial/Symmetric/FundamentalTheorem.lean @@ -146,7 +146,7 @@ variable (σ) in noncomputable def esymmAlgHomMonomial (t : Fin n →₀ ℕ) (r : R) : MvPolynomial σ R := (esymmAlgHom σ R n <| monomial t r).val -variable {i : Fin n} {j : Fin m} {r : R} +variable {i : Fin n} {r : R} lemma isSymmetric_esymmAlgHomMonomial (t : Fin n →₀ ℕ) (r : R) : (esymmAlgHomMonomial σ t r).IsSymmetric := (esymmAlgHom _ _ _ _).2 @@ -235,6 +235,7 @@ lemma supDegree_esymmAlgHomMonomial (hr : r ≠ 0) (t : Fin n →₀ ℕ) (hnm : · exact (monic_esymm this).pow toLex_add toLex.injective · rwa [Ne, ← leadingCoeff_eq_zero toLex.injective, leadingCoeff_esymmAlgHomMonomial _ hnm] +omit [Fintype σ] in lemma IsSymmetric.antitone_supDegree [LinearOrder σ] {p : MvPolynomial σ R} (hp : p.IsSymmetric) : Antitone ↑(ofLex <| p.supDegree toLex) := by obtain rfl | h0 := eq_or_ne p 0 diff --git a/Mathlib/RingTheory/MvPowerSeries/Inverse.lean b/Mathlib/RingTheory/MvPowerSeries/Inverse.lean index a7e076eb389ea..d53136ff960c2 100644 --- a/Mathlib/RingTheory/MvPowerSeries/Inverse.lean +++ b/Mathlib/RingTheory/MvPowerSeries/Inverse.lean @@ -7,7 +7,7 @@ Authors: Johan Commelin, Kenny Lau import Mathlib.Algebra.Group.Units import Mathlib.RingTheory.MvPowerSeries.Basic import Mathlib.RingTheory.MvPowerSeries.NoZeroDivisors -import Mathlib.RingTheory.LocalRing.RingHom.Basic +import Mathlib.RingTheory.LocalRing.Basic /-! # Formal (multivariate) power series - Inverses diff --git a/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean b/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean index aaab1b9cc3f6b..13ecad6b47dce 100644 --- a/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean +++ b/Mathlib/RingTheory/MvPowerSeries/LexOrder.lean @@ -34,8 +34,8 @@ noncomputable def lexOrder (φ : MvPowerSeries σ R) : (WithTop (Lex (σ →₀ simp only [Set.image_nonempty, Function.support_nonempty_iff, ne_eq, h, not_false_eq_true] apply WithTop.some apply WellFounded.min _ (toLex '' φ.support) ne - exact Finsupp.instLTLex.lt - exact wellFounded_lt + · exact Finsupp.instLTLex.lt + · exact wellFounded_lt theorem lexOrder_def_of_ne_zero {φ : MvPowerSeries σ R} (hφ : φ ≠ 0) : ∃ (ne : Set.Nonempty (toLex '' φ.support)), @@ -104,13 +104,10 @@ theorem le_lexOrder_iff {φ : MvPowerSeries σ R} {w : WithTop (Lex (σ →₀ intro h' have hφ : φ ≠ 0 := by rw [ne_eq, ← lexOrder_eq_top_iff_eq_zero] - intro h'' - rw [h'', ← not_le] at h' - apply h' - exact le_top + exact ne_top_of_lt h' obtain ⟨d, hd⟩ := exists_finsupp_eq_lexOrder_of_ne_zero hφ refine coeff_ne_zero_of_lexOrder hd.symm (h d ?_) - exact (lt_of_eq_of_lt hd.symm h') + rwa [← hd] theorem min_lexOrder_le {φ ψ : MvPowerSeries σ R} : min (lexOrder φ) (lexOrder ψ) ≤ lexOrder (φ + ψ) := by diff --git a/Mathlib/RingTheory/Nilpotent/Basic.lean b/Mathlib/RingTheory/Nilpotent/Basic.lean index 0080e768a4300..71e196c394db9 100644 --- a/Mathlib/RingTheory/Nilpotent/Basic.lean +++ b/Mathlib/RingTheory/Nilpotent/Basic.lean @@ -82,6 +82,15 @@ theorem IsNilpotent.isUnit_add_right_of_commute [Ring R] {r u : R} IsUnit (r + u) := add_comm r u ▸ hnil.isUnit_add_left_of_commute hu h_comm +lemma IsUnit.not_isNilpotent [Ring R] [Nontrivial R] {x : R} (hx : IsUnit x) : + ¬ IsNilpotent x := by + intro H + simpa using H.isUnit_add_right_of_commute hx.neg (by simp) + +lemma IsNilpotent.not_isUnit [Ring R] [Nontrivial R] {x : R} (hx : IsNilpotent x) : + ¬ IsUnit x := + mt IsUnit.not_isNilpotent (by simpa only [not_not] using hx) + instance [Zero R] [Pow R ℕ] [Zero S] [Pow S ℕ] [IsReduced R] [IsReduced S] : IsReduced (R × S) where eq_zero _ := fun ⟨n, hn⟩ ↦ have hn := Prod.ext_iff.1 hn Prod.ext (IsReduced.eq_zero _ ⟨n, hn.1⟩) (IsReduced.eq_zero _ ⟨n, hn.2⟩) diff --git a/Mathlib/RingTheory/Nilpotent/Defs.lean b/Mathlib/RingTheory/Nilpotent/Defs.lean index 0404b768832fa..cbdde6aab35bc 100644 --- a/Mathlib/RingTheory/Nilpotent/Defs.lean +++ b/Mathlib/RingTheory/Nilpotent/Defs.lean @@ -168,6 +168,29 @@ class IsReduced (R : Type*) [Zero R] [Pow R ℕ] : Prop where /-- A reduced structure has no nonzero nilpotent elements. -/ eq_zero : ∀ x : R, IsNilpotent x → x = 0 +namespace IsReduced + +theorem pow_eq_zero [Zero R] [Pow R ℕ] [IsReduced R] {n : ℕ} (h : x ^ n = 0) : + x = 0 := IsReduced.eq_zero x ⟨n, h⟩ + +@[simp] +theorem pow_eq_zero_iff [MonoidWithZero R] [IsReduced R] {n : ℕ} (hn : n ≠ 0) : + x ^ n = 0 ↔ x = 0 := ⟨pow_eq_zero, fun h ↦ h.symm ▸ zero_pow hn⟩ + +theorem pow_ne_zero_iff [MonoidWithZero R] [IsReduced R] {n : ℕ} (hn : n ≠ 0) : + x ^ n ≠ 0 ↔ x ≠ 0 := not_congr (pow_eq_zero_iff hn) + +theorem pow_ne_zero [Zero R] [Pow R ℕ] [IsReduced R] (n : ℕ) (h : x ≠ 0) : + x ^ n ≠ 0 := fun H ↦ h (pow_eq_zero H) + +/-- A variant of `IsReduced.pow_eq_zero_iff` assuming `R` is not trivial. -/ +@[simp] +theorem pow_eq_zero_iff' [MonoidWithZero R] [IsReduced R] [Nontrivial R] {n : ℕ} : + x ^ n = 0 ↔ x = 0 ∧ n ≠ 0 := by + cases n <;> simp + +end IsReduced + instance (priority := 900) isReduced_of_noZeroDivisors [MonoidWithZero R] [NoZeroDivisors R] : IsReduced R := ⟨fun _ ⟨_, hn⟩ => pow_eq_zero hn⟩ diff --git a/Mathlib/RingTheory/Nilpotent/Lemmas.lean b/Mathlib/RingTheory/Nilpotent/Lemmas.lean index d5d61f66838de..fdbae3b577172 100644 --- a/Mathlib/RingTheory/Nilpotent/Lemmas.lean +++ b/Mathlib/RingTheory/Nilpotent/Lemmas.lean @@ -31,16 +31,6 @@ theorem isRadical_iff_span_singleton [CommSemiring R] : simp_rw [IsRadical, ← Ideal.mem_span_singleton] exact forall_swap.trans (forall_congr' fun r => exists_imp.symm) -namespace Commute - -section Semiring - -variable [Semiring R] (h_comm : Commute x y) - -end Semiring - -end Commute - section CommSemiring variable [CommSemiring R] {x y : R} @@ -99,13 +89,31 @@ end LinearMap namespace Module.End -lemma isNilpotent.restrict {R M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] +section + +variable {M : Type*} [Semiring R] [AddCommMonoid M] [Module R M] + +lemma isNilpotent_restrict_of_le {f : End R M} {p q : Submodule R M} + {hp : MapsTo f p p} {hq : MapsTo f q q} (h : p ≤ q) (hf : IsNilpotent (f.restrict hq)) : + IsNilpotent (f.restrict hp) := by + obtain ⟨n, hn⟩ := hf + use n + ext ⟨x, hx⟩ + replace hn := DFunLike.congr_fun hn ⟨x, h hx⟩ + simp_rw [LinearMap.zero_apply, ZeroMemClass.coe_zero, ZeroMemClass.coe_eq_zero] at hn ⊢ + rw [LinearMap.pow_restrict, LinearMap.restrict_apply] at hn ⊢ + ext + exact (congr_arg Subtype.val hn : _) + +lemma isNilpotent.restrict {f : M →ₗ[R] M} {p : Submodule R M} (hf : MapsTo f p p) (hnil : IsNilpotent f) : IsNilpotent (f.restrict hf) := by obtain ⟨n, hn⟩ := hnil exact ⟨n, LinearMap.ext fun m ↦ by simp only [LinearMap.pow_restrict n, hn, LinearMap.restrict_apply, LinearMap.zero_apply]; rfl⟩ +end + variable {M : Type v} [Ring R] [AddCommGroup M] [Module R M] variable {f : Module.End R M} {p : Submodule R M} (hp : p ≤ p.comap f) diff --git a/Mathlib/RingTheory/Noetherian.lean b/Mathlib/RingTheory/Noetherian.lean index f3e0b396a8eb4..903c8862e2b78 100644 --- a/Mathlib/RingTheory/Noetherian.lean +++ b/Mathlib/RingTheory/Noetherian.lean @@ -145,17 +145,21 @@ variable [Semiring R] [AddCommMonoid M] [AddCommMonoid N] [Module R M] [Module R variable (R M) -- see Note [lower instance priority] -instance (priority := 100) IsNoetherian.finite [IsNoetherian R M] : Finite R M := +instance (priority := 80) _root_.isNoetherian_of_finite [Finite M] : IsNoetherian R M := + ⟨fun s => ⟨(s : Set M).toFinite.toFinset, by rw [Set.Finite.coe_toFinset, Submodule.span_eq]⟩⟩ + +-- see Note [lower instance priority] +instance (priority := 100) IsNoetherian.finite [IsNoetherian R M] : Module.Finite R M := ⟨IsNoetherian.noetherian ⊤⟩ instance {R₁ S : Type*} [CommSemiring R₁] [Semiring S] [Algebra R₁ S] - [IsNoetherian R₁ S] (I : Ideal S) : Finite R₁ I := + [IsNoetherian R₁ S] (I : Ideal S) : Module.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) : - Finite R M := + Module.Finite R M := ⟨fg_of_injective f hf⟩ end Module @@ -184,77 +188,13 @@ instance isNoetherian_prod [IsNoetherian R M] [IsNoetherian R P] : IsNoetherian fun x ⟨_, hx2⟩ => ⟨x.1, Prod.ext rfl <| Eq.symm <| LinearMap.mem_ker.1 hx2⟩ Submodule.map_comap_eq_self this ▸ (noetherian _).map _⟩ -instance isNoetherian_pi {R ι : Type*} {M : ι → Type*} - [Ring R] [∀ i, AddCommGroup (M i)] [∀ i, Module R (M i)] [Finite ι] - [∀ i, IsNoetherian R (M i)] : IsNoetherian R (∀ i, M i) := by - cases nonempty_fintype ι - haveI := Classical.decEq ι - suffices on_finset : ∀ s : Finset ι, IsNoetherian R (∀ i : s, M i) by - let coe_e := Equiv.subtypeUnivEquiv <| @Finset.mem_univ ι _ - letI : IsNoetherian R (∀ i : Finset.univ, M (coe_e i)) := on_finset Finset.univ - exact isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R M coe_e) - intro s - induction' s using Finset.induction with a s has ih - · exact ⟨fun s => by - have : s = ⊥ := by simp only [eq_iff_true_of_subsingleton] - rw [this] - apply Submodule.fg_bot⟩ - refine - @isNoetherian_of_linearEquiv R (M a × ((i : s) → M i)) _ _ _ _ _ _ ?_ <| - @isNoetherian_prod R (M a) _ _ _ _ _ _ _ ih - refine - { toFun := fun f i => - (Finset.mem_insert.1 i.2).by_cases - (fun h : i.1 = a => show M i.1 from Eq.recOn h.symm f.1) - (fun h : i.1 ∈ s => show M i.1 from f.2 ⟨i.1, h⟩), - invFun := fun f => - (f ⟨a, Finset.mem_insert_self _ _⟩, fun i => f ⟨i.1, Finset.mem_insert_of_mem i.2⟩), - map_add' := ?_, - map_smul' := ?_ - left_inv := ?_, - right_inv := ?_ } - · intro f g - ext i - unfold Or.by_cases - cases' i with i hi - rcases Finset.mem_insert.1 hi with (rfl | h) - · change _ = _ + _ - simp only [dif_pos] - rfl - · change _ = _ + _ - have : ¬i = a := by - rintro rfl - exact has h - simp only [dif_neg this, dif_pos h] - rfl - · intro c f - ext i - unfold Or.by_cases - cases' i with i hi - rcases Finset.mem_insert.1 hi with (rfl | h) - · dsimp - simp only [dif_pos] - · dsimp - have : ¬i = a := by - rintro rfl - exact has h - simp only [dif_neg this, dif_pos h] - · intro f - apply Prod.ext - · simp only [Or.by_cases, dif_pos] - · ext ⟨i, his⟩ - have : ¬i = a := by - rintro rfl - exact has his - simp only [Or.by_cases, this, not_false_iff, dif_neg] - · intro f - ext ⟨i, hi⟩ - rcases Finset.mem_insert.1 hi with (rfl | h) - · simp only [Or.by_cases, dif_pos] - · have : ¬i = a := by - rintro rfl - exact has h - simp only [Or.by_cases, dif_neg this, dif_pos h] +instance isNoetherian_pi {R ι : Type*} [Finite ι] : + ∀ {M : ι → Type*} [Ring R] [∀ i, AddCommGroup (M i)] + [∀ i, Module R (M i)] [∀ i, IsNoetherian R (M i)], IsNoetherian R (∀ i, M i) := by + apply Finite.induction_empty_option _ _ _ ι + · exact fun e h ↦ isNoetherian_of_linearEquiv (LinearEquiv.piCongrLeft R _ e) + · infer_instance + · exact fun ih ↦ isNoetherian_of_linearEquiv (LinearEquiv.piOptionEquivProd R).symm /-- A version of `isNoetherian_pi` for non-dependent functions. We need this instance because sometimes Lean fails to apply the dependent version in non-dependent settings (e.g., it fails to @@ -289,19 +229,19 @@ universe w variable {R M P : Type*} {N : Type w} [Semiring R] [AddCommMonoid M] [Module R M] [AddCommMonoid N] [Module R N] [AddCommMonoid P] [Module R P] -theorem isNoetherian_iff : - IsNoetherian R M ↔ WellFounded ((· > ·) : Submodule R M → Submodule R M → Prop) := by - have := (CompleteLattice.wellFounded_characterisations <| Submodule R M).out 0 3 +theorem isNoetherian_iff' : IsNoetherian R M ↔ WellFoundedGT (Submodule R M) := by + have := (CompleteLattice.wellFoundedGT_characterisations <| Submodule R M).out 0 3 -- Porting note: inlining this makes rw complain about it being a metavariable rw [this] exact ⟨fun ⟨h⟩ => fun k => (fg_iff_compact k).mp (h k), fun h => ⟨fun k => (fg_iff_compact k).mpr (h k)⟩⟩ -alias ⟨IsNoetherian.wf, _⟩ := isNoetherian_iff +theorem isNoetherian_iff : + IsNoetherian R M ↔ WellFounded ((· > ·) : Submodule R M → Submodule R M → Prop) := by + rw [isNoetherian_iff', ← isWellFounded_iff] -theorem isNoetherian_iff' : IsNoetherian R M ↔ WellFoundedGT (Submodule R M) := by - rw [isNoetherian_iff, ← isWellFounded_iff] +alias ⟨IsNoetherian.wf, _⟩ := isNoetherian_iff alias ⟨IsNoetherian.wellFoundedGT, isNoetherian_mk⟩ := isNoetherian_iff' @@ -363,14 +303,13 @@ variable {R M P : Type*} {N : Type w} [Ring R] [AddCommGroup M] [Module R M] [Ad lemma Submodule.finite_ne_bot_of_independent {ι : Type*} {N : ι → Submodule R M} (h : CompleteLattice.Independent N) : Set.Finite {i | N i ≠ ⊥} := - CompleteLattice.WellFounded.finite_ne_bot_of_independent - (IsWellFounded.wf) h + CompleteLattice.WellFoundedGT.finite_ne_bot_of_independent h /-- A linearly-independent family of vectors in a module over a non-trivial ring must be finite if the module is Noetherian. -/ theorem LinearIndependent.finite_of_isNoetherian [Nontrivial R] {ι} {v : ι → M} (hv : LinearIndependent R v) : Finite ι := by - refine CompleteLattice.WellFounded.finite_of_independent IsWellFounded.wf + refine CompleteLattice.WellFoundedGT.finite_of_independent hv.independent_span_singleton fun i contra => ?_ apply hv.ne_zero i @@ -381,9 +320,6 @@ theorem LinearIndependent.set_finite_of_isNoetherian [Nontrivial R] {s : Set M} (hi : LinearIndependent R ((↑) : s → M)) : s.Finite := @Set.toFinite _ _ hi.finite_of_isNoetherian -@[deprecated (since := "2023-12-30")] -alias finite_of_linearIndependent := LinearIndependent.set_finite_of_isNoetherian - /-- If the first and final modules in an exact sequence are Noetherian, then the middle module is also Noetherian. -/ theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] @@ -392,15 +328,20 @@ theorem isNoetherian_of_range_eq_ker [IsNoetherian R P] isNoetherian_mk <| wellFounded_gt_exact_sequence (LinearMap.range f) - (Submodule.map (f.ker.liftQ f <| le_rfl)) - (Submodule.comap (f.ker.liftQ f <| le_rfl)) + (Submodule.map (f.ker.liftQ f le_rfl)) + (Submodule.comap (f.ker.liftQ f le_rfl)) (Submodule.comap g.rangeRestrict) (Submodule.map g.rangeRestrict) - (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| - Submodule.ker_liftQ_eq_bot _ _ _ (le_refl _)) + (Submodule.gciMapComap <| LinearMap.ker_eq_bot.mp <| Submodule.ker_liftQ_eq_bot _ _ _ le_rfl) (Submodule.giMapComap g.surjective_rangeRestrict) (by simp [Submodule.map_comap_eq, inf_comm, Submodule.range_liftQ]) (by simp [Submodule.comap_map_eq, h]) +theorem isNoetherian_iff_submodule_quotient (S : Submodule R P) : + IsNoetherian R P ↔ IsNoetherian R S ∧ IsNoetherian R (P ⧸ S) := by + refine ⟨fun _ ↦ ⟨inferInstance, inferInstance⟩, fun ⟨_, _⟩ ↦ ?_⟩ + apply isNoetherian_of_range_eq_ker S.subtype S.mkQ + rw [Submodule.ker_mkQ, Submodule.range_subtype] + /-- For an endomorphism of a Noetherian module, any sufficiently large iterate has disjoint kernel and range. -/ theorem LinearMap.eventually_disjoint_ker_pow_range_pow (f : M →ₗ[R] M) : @@ -503,11 +444,6 @@ theorem isNoetherianRing_iff_ideal_fg (R : Type*) [Semiring R] : IsNoetherianRing R ↔ ∀ I : Ideal R, I.FG := isNoetherianRing_iff.trans isNoetherian_def --- see Note [lower instance priority] -instance (priority := 80) isNoetherian_of_finite (R M) [Finite M] [Semiring R] [AddCommMonoid M] - [Module R M] : IsNoetherian R M := - ⟨fun s => ⟨(s : Set M).toFinite.toFinset, by rw [Set.Finite.coe_toFinset, Submodule.span_eq]⟩⟩ - -- see Note [lower instance priority] /-- Modules over the trivial ring are Noetherian. -/ instance (priority := 100) isNoetherian_of_subsingleton (R M) [Subsingleton R] [Semiring R] diff --git a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean index 69c9fcd2931b4..f71dbda3f4e85 100644 --- a/Mathlib/RingTheory/NonUnitalSubring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubring/Basic.lean @@ -71,7 +71,7 @@ universe u v w section Basic -variable {R : Type u} {S : Type v} {T : Type w} [NonUnitalNonAssocRing R] +variable {R : Type u} {S : Type v} [NonUnitalNonAssocRing R] section NonUnitalSubringClass @@ -124,8 +124,6 @@ end NonUnitalSubringClass end NonUnitalSubringClass -variable [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] - /-- `NonUnitalSubring R` is the type of non-unital subrings of `R`. A non-unital subring of `R` is a subset `s` that is a multiplicative subsemigroup and an additive subgroup. Note in particular that it shares the same 0 as R. -/ @@ -387,7 +385,7 @@ section Hom namespace NonUnitalSubring -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} {SR : Type*} +variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] [FunLike F R S] [NonUnitalRingHomClass F R S] (s : NonUnitalSubring R) @@ -503,10 +501,7 @@ namespace NonUnitalSubring section Order -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} - [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] - [FunLike F R S] [NonUnitalRingHomClass F R S] - (g : S →ₙ+* T) (f : R →ₙ+* S) +variable {R : Type u} [NonUnitalNonAssocRing R] /-! ## bot -/ @@ -640,10 +635,9 @@ end Center /-! ## `NonUnitalSubring` closure of a subset -/ -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} - [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] +variable {F : Type w} {R : Type u} {S : Type v} + [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [FunLike F R S] [NonUnitalRingHomClass F R S] - (g : S →ₙ+* T) (f : R →ₙ+* S) /-- The `NonUnitalSubring` generated by a set. -/ def closure (s : Set R) : NonUnitalSubring R := @@ -910,11 +904,8 @@ end NonUnitalSubring namespace NonUnitalRingHom -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} - [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] - [FunLike F R S] [NonUnitalRingHomClass F R S] - (g : S →ₙ+* T) (f : R →ₙ+* S) - {s : NonUnitalSubring R} +variable {R : Type u} {S : Type v} + [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] open NonUnitalSubring @@ -980,11 +971,8 @@ end NonUnitalRingHom namespace NonUnitalSubring -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} - [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] [NonUnitalNonAssocRing T] - [FunLike F R S] [NonUnitalRingHomClass F R S] - (g : S →ₙ+* T) (f : R →ₙ+* S) - {s : NonUnitalSubring R} +variable {R : Type u} {S : Type v} + [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] open NonUnitalRingHom @@ -1006,11 +994,7 @@ end NonUnitalSubring namespace RingEquiv -variable {F : Type w} {R : Type u} {S : Type v} {T : Type*} - [NonUnitalRing R] [NonUnitalRing S] [NonUnitalRing T] - [FunLike F R S] [NonUnitalRingHomClass F R S] - (g : S →ₙ+* T) (f : R →ₙ+* S) - {s t : NonUnitalSubring R} +variable {R : Type u} {S : Type v} [NonUnitalRing R] [NonUnitalRing S] {s t : NonUnitalSubring R} /-- Makes the identity isomorphism from a proof two `NonUnitalSubring`s of a multiplicative monoid are equal. -/ diff --git a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean index 55bb7d2fd0d44..891e01b70140c 100644 --- a/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean +++ b/Mathlib/RingTheory/NonUnitalSubsemiring/Basic.lean @@ -29,7 +29,7 @@ variable {R : Type u} {S : Type v} {T : Type w} [NonUnitalNonAssocSemiring R] (M /-- `NonUnitalSubsemiringClass S R` states that `S` is a type of subsets `s ⊆ R` that are both an additive submonoid and also a multiplicative subsemigroup. -/ -class NonUnitalSubsemiringClass (S : Type*) (R : Type u) [NonUnitalNonAssocSemiring R] +class NonUnitalSubsemiringClass (S : Type*) (R : outParam (Type u)) [NonUnitalNonAssocSemiring R] [SetLike S R] extends AddSubmonoidClass S R : Prop where mul_mem : ∀ {s : S} {a b : R}, a ∈ s → b ∈ s → a * b ∈ s diff --git a/Mathlib/RingTheory/Norm/Basic.lean b/Mathlib/RingTheory/Norm/Basic.lean index a051d47766d54..e58b1fc23e208 100644 --- a/Mathlib/RingTheory/Norm/Basic.lean +++ b/Mathlib/RingTheory/Norm/Basic.lean @@ -8,7 +8,7 @@ import Mathlib.FieldTheory.PrimitiveElement import Mathlib.LinearAlgebra.Matrix.Charpoly.Minpoly import Mathlib.LinearAlgebra.Matrix.ToLinearEquiv import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic /-! # Norm for (finite) ring extensions @@ -46,7 +46,7 @@ variable {K L F : Type*} [Field K] [Field L] [Field F] variable [Algebra K L] [Algebra K F] variable {ι : Type w} -open FiniteDimensional +open Module open LinearMap @@ -74,7 +74,7 @@ theorem PowerBasis.norm_gen_eq_prod_roots [Algebra R F] (pb : PowerBasis R S) have := minpoly.monic pb.isIntegral_gen rw [PowerBasis.norm_gen_eq_coeff_zero_minpoly, ← pb.natDegree_minpoly, RingHom.map_mul, ← coeff_map, - prod_roots_eq_coeff_zero_of_monic_of_split (this.map _) ((splits_id_iff_splits _).2 hf), + prod_roots_eq_coeff_zero_of_monic_of_splits (this.map _) ((splits_id_iff_splits _).2 hf), this.natDegree_map, map_pow, ← mul_assoc, ← mul_pow] simp only [map_neg, _root_.map_one, neg_mul, neg_neg, one_pow, one_mul] @@ -153,7 +153,7 @@ theorem _root_.IntermediateField.AdjoinSimple.norm_gen_eq_one {x : L} (hx : ¬Is contrapose! hx obtain ⟨s, ⟨b⟩⟩ := hx refine .of_mem_of_fg K⟮x⟯.toSubalgebra ?_ x ?_ - · exact (Submodule.fg_iff_finiteDimensional _).mpr (of_fintype_basis b) + · exact (Submodule.fg_iff_finiteDimensional _).mpr (.of_fintype_basis b) · exact IntermediateField.subset_adjoin K _ (Set.mem_singleton x) theorem _root_.IntermediateField.AdjoinSimple.norm_gen_eq_prod_roots (x : L) diff --git a/Mathlib/RingTheory/Norm/Defs.lean b/Mathlib/RingTheory/Norm/Defs.lean index 6f1c21fae5c00..b7f2ce47f5c97 100644 --- a/Mathlib/RingTheory/Norm/Defs.lean +++ b/Mathlib/RingTheory/Norm/Defs.lean @@ -41,7 +41,7 @@ variable {K L F : Type*} [Field K] [Field L] [Field F] variable [Algebra K L] [Algebra K F] variable {ι : Type w} -open FiniteDimensional +open Module open LinearMap diff --git a/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean b/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean index 5f2544087a31a..d66fdc3f66ab9 100644 --- a/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean +++ b/Mathlib/RingTheory/Polynomial/Cyclotomic/Expand.lean @@ -3,8 +3,8 @@ Copyright (c) 2020 Riccardo Brasca. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Riccardo Brasca -/ +import Mathlib.Algebra.Algebra.ZMod import Mathlib.RingTheory.Polynomial.Cyclotomic.Roots -import Mathlib.Data.ZMod.Algebra /-! # Cyclotomic polynomials and `expand`. diff --git a/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean b/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean index a7f446664bdad..6365d391b724f 100644 --- a/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean +++ b/Mathlib/RingTheory/Polynomial/Eisenstein/IsIntegral.lean @@ -137,7 +137,7 @@ theorem dvd_coeff_zero_of_aeval_eq_prime_smul_of_minpoly_isEisensteinAt {B : Pow letI := B.finite let P := minpoly R B.gen obtain ⟨n, hn⟩ := Nat.exists_eq_succ_of_ne_zero B.dim_pos.ne' - have finrank_K_L : FiniteDimensional.finrank K L = B.dim := B.finrank + have finrank_K_L : Module.finrank K L = B.dim := B.finrank have deg_K_P : (minpoly K B.gen).natDegree = B.dim := B.natDegree_minpoly have deg_R_P : P.natDegree = B.dim := by rw [← deg_K_P, minpoly.isIntegrallyClosed_eq_field_fractions' K hBint, diff --git a/Mathlib/RingTheory/Polynomial/Quotient.lean b/Mathlib/RingTheory/Polynomial/Quotient.lean index 1f6608a4850b7..6d9f4b7aa653f 100644 --- a/Mathlib/RingTheory/Polynomial/Quotient.lean +++ b/Mathlib/RingTheory/Polynomial/Quotient.lean @@ -244,7 +244,7 @@ lemma quotientEquivQuotientMvPolynomial_leftInverse (I : Ideal R) : rw [Ideal.Quotient.lift_mk, eval₂Hom_C, RingHom.comp_apply, eval₂_C, Ideal.Quotient.lift_mk, RingHom.comp_apply] · intros p q hp hq - erw [Ideal.Quotient.lift_mk] at hp hq ⊢ + rw [Ideal.Quotient.lift_mk] at hp hq ⊢ simp only [Submodule.Quotient.quot_mk_eq_mk, eval₂_add, RingHom.map_add, coe_eval₂Hom, Ideal.Quotient.lift_mk, Ideal.Quotient.mk_eq_mk] at hp hq ⊢ rw [hp, hq] diff --git a/Mathlib/RingTheory/PolynomialAlgebra.lean b/Mathlib/RingTheory/PolynomialAlgebra.lean index 410b46c3aec39..278543baf82c4 100644 --- a/Mathlib/RingTheory/PolynomialAlgebra.lean +++ b/Mathlib/RingTheory/PolynomialAlgebra.lean @@ -251,7 +251,7 @@ theorem matPolyEquiv_coeff_apply (m : Matrix n n R[X]) (k : ℕ) (i j : n) : · intro p q hp hq simp [hp, hq] · intro i' j' x - erw [matPolyEquiv_coeff_apply_aux_2] + rw [matPolyEquiv_coeff_apply_aux_2] dsimp [stdBasisMatrix] split_ifs <;> rename_i h · rcases h with ⟨rfl, rfl⟩ diff --git a/Mathlib/RingTheory/PowerBasis.lean b/Mathlib/RingTheory/PowerBasis.lean index b0b9c2d3d7536..a9cf86b0049c1 100644 --- a/Mathlib/RingTheory/PowerBasis.lean +++ b/Mathlib/RingTheory/PowerBasis.lean @@ -19,7 +19,7 @@ gives a `PowerBasis` structure generated by `x`. * `PowerBasis R A`: a structure containing an `x` and an `n` such that `1, x, ..., x^n` is a basis for the `R`-algebra `A` (viewed as an `R`-module). -* `finrank (hf : f ≠ 0) : FiniteDimensional.finrank K (AdjoinRoot f) = f.natDegree`, +* `finrank (hf : f ≠ 0) : Module.finrank K (AdjoinRoot f) = f.natDegree`, the dimension of `AdjoinRoot f` equals the degree of `f` * `PowerBasis.lift (pb : PowerBasis R S)`: if `y : S'` satisfies the same @@ -77,8 +77,8 @@ theorem finite (pb : PowerBasis R S) : Module.Finite R S := .of_basis pb.basis @[deprecated (since := "2024-03-05")] alias finiteDimensional := PowerBasis.finite theorem finrank [StrongRankCondition R] (pb : PowerBasis R S) : - FiniteDimensional.finrank R S = pb.dim := by - rw [FiniteDimensional.finrank_eq_card_basis pb.basis, Fintype.card_fin] + Module.finrank R S = pb.dim := by + rw [Module.finrank_eq_card_basis pb.basis, Fintype.card_fin] theorem mem_span_pow' {x y : S} {d : ℕ} : y ∈ Submodule.span R (Set.range fun i : Fin d => x ^ (i : ℕ)) ↔ diff --git a/Mathlib/RingTheory/PowerSeries/Basic.lean b/Mathlib/RingTheory/PowerSeries/Basic.lean index 33cea1c3cd017..bae1dcd02e069 100644 --- a/Mathlib/RingTheory/PowerSeries/Basic.lean +++ b/Mathlib/RingTheory/PowerSeries/Basic.lean @@ -145,7 +145,7 @@ def monomial (n : ℕ) : R →ₗ[R] R⟦X⟧ := variable {R} theorem coeff_def {s : Unit →₀ ℕ} {n : ℕ} (h : s () = n) : coeff R n = MvPowerSeries.coeff R s := by - erw [coeff, ← h, ← Finsupp.unique_single s] + rw [coeff, ← h, ← Finsupp.unique_single s] /-- Two formal power series are equal if all their coefficients are equal. -/ @[ext] @@ -214,8 +214,9 @@ theorem coeff_zero_eq_constantCoeff_apply (φ : R⟦X⟧) : coeff R 0 φ = const @[simp] theorem monomial_zero_eq_C : ⇑(monomial R 0) = C R := by - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [monomial, Finsupp.single_zero, MvPowerSeries.monomial_zero_eq_C] + -- This used to be `rw`, but we need `rw; rfl` after leanprover/lean4#2644 + rw [monomial, Finsupp.single_zero, MvPowerSeries.monomial_zero_eq_C] + rfl theorem monomial_zero_eq_C_apply (a : R) : monomial R 0 a = C R a := by simp @@ -251,8 +252,7 @@ theorem coeff_X (n : ℕ) : coeff R n (X : R⟦X⟧) = if n = 1 then 1 else 0 := @[simp] theorem coeff_zero_X : coeff R 0 (X : R⟦X⟧) = 0 := by - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [coeff, Finsupp.single_zero, X, MvPowerSeries.coeff_zero_X] + rw [coeff, Finsupp.single_zero, X, MvPowerSeries.coeff_zero_X] @[simp] theorem coeff_one_X : coeff R 1 (X : R⟦X⟧) = 1 := by rw [coeff_X, if_pos rfl] @@ -603,14 +603,14 @@ lemma coeff_one_pow (n : ℕ) (φ : R⟦X⟧) : CharP.cast_eq_zero, zero_add, mul_one, not_true_eq_false] at h'' norm_num at h'' · rw [ih] - conv => lhs; arg 2; rw [mul_comm, ← mul_assoc] - move_mul [← (constantCoeff R) φ ^ (n' - 1)] - conv => enter [1, 2, 1, 1, 2]; rw [← pow_one (a := constantCoeff R φ)] - rw [← pow_add (a := constantCoeff R φ)] - conv => enter [1, 2, 1, 1]; rw [Nat.sub_add_cancel h'] - conv => enter [1, 2, 1]; rw [mul_comm] - rw [mul_assoc, ← one_add_mul, add_comm, mul_assoc] - conv => enter [1, 2]; rw [mul_comm] + · conv => lhs; arg 2; rw [mul_comm, ← mul_assoc] + move_mul [← (constantCoeff R) φ ^ (n' - 1)] + conv => enter [1, 2, 1, 1, 2]; rw [← pow_one (a := constantCoeff R φ)] + rw [← pow_add (a := constantCoeff R φ)] + conv => enter [1, 2, 1, 1]; rw [Nat.sub_add_cancel h'] + conv => enter [1, 2, 1]; rw [mul_comm] + rw [mul_assoc, ← one_add_mul, add_comm, mul_assoc] + conv => enter [1, 2]; rw [mul_comm] exact h' · decide diff --git a/Mathlib/RingTheory/PowerSeries/Inverse.lean b/Mathlib/RingTheory/PowerSeries/Inverse.lean index a8d96e7a4b2ac..b08f4125a38a0 100644 --- a/Mathlib/RingTheory/PowerSeries/Inverse.lean +++ b/Mathlib/RingTheory/PowerSeries/Inverse.lean @@ -54,8 +54,7 @@ theorem coeff_inv_aux (n : ℕ) (a : R) (φ : R⟦X⟧) : -a * ∑ x ∈ antidiagonal n, if x.2 < n then coeff R x.1 φ * coeff R x.2 (inv.aux a φ) else 0 := by - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [coeff, inv.aux, MvPowerSeries.coeff_inv_aux] + rw [coeff, inv.aux, MvPowerSeries.coeff_inv_aux] simp only [Finsupp.single_eq_zero] split_ifs; · rfl congr 1 diff --git a/Mathlib/RingTheory/Presentation.lean b/Mathlib/RingTheory/Presentation.lean index 1fbea429322dc..8cdc5f61d50d6 100644 --- a/Mathlib/RingTheory/Presentation.lean +++ b/Mathlib/RingTheory/Presentation.lean @@ -179,6 +179,7 @@ private lemma span_range_relation_eq_ker_localizationAway : show Ideal.span {C r * X () - 1} = Ideal.comap _ (RingHom.ker (mvPolynomialQuotientEquiv S r)) simp [RingHom.ker_equiv, ← RingHom.ker_eq_comap_bot] +variable (S) in /-- If `S` is the localization of `R` away from `r`, we can construct a natural presentation of `S` as `R`-algebra with a single generator `X` and the relation `r * X - 1 = 0`. -/ @[simps relation, simps (config := .lemmasOnly) rels] @@ -190,12 +191,15 @@ noncomputable def localizationAway : Presentation R S where simp only [Generators.localizationAway_vars, Set.range_const] apply span_range_relation_eq_ker_localizationAway r -instance localizationAway_isFinite : (localizationAway r (S := S)).IsFinite where +instance localizationAway_isFinite : (localizationAway S r).IsFinite where finite_vars := inferInstanceAs <| Finite Unit finite_rels := inferInstanceAs <| Finite Unit +instance : Fintype (localizationAway S r).rels := + inferInstanceAs (Fintype Unit) + @[simp] -lemma localizationAway_dimension_zero : (localizationAway r (S := S)).dimension = 0 := by +lemma localizationAway_dimension_zero : (localizationAway S r).dimension = 0 := by simp [Presentation.dimension, localizationAway, Generators.localizationAway_vars] end Localization @@ -232,7 +236,7 @@ private lemma span_range_relation_eq_ker_baseChange : | h_C a => simp only [Generators.algebraMap_apply, algHom_C, TensorProduct.algebraMap_apply, id.map_eq_id, RingHom.id_apply, e] - erw [← MvPolynomial.algebraMap_eq, AlgEquiv.commutes] + rw [← MvPolynomial.algebraMap_eq, AlgEquiv.commutes] simp only [TensorProduct.algebraMap_apply, id.map_eq_id, RingHom.id_apply, TensorProduct.map_tmul, AlgHom.coe_id, id_eq, map_one, algebraMap_eq] erw [aeval_C] @@ -244,7 +248,7 @@ private lemma span_range_relation_eq_ker_baseChange : congr erw [aeval_X] rw [Generators.baseChange_val] - erw [H] at H' + rw [H] at H' replace H' : e.symm x ∈ Ideal.map TensorProduct.includeRight P.ker := H' erw [← P.span_range_relation_eq_ker, ← Ideal.mem_comap, Ideal.comap_symm, Ideal.map_map, Ideal.map_span, ← Set.range_comp] at H' @@ -408,7 +412,12 @@ noncomputable def comp : Presentation R T where (fun rp ↦ MvPolynomial.rename Sum.inr <| P.relation rp) span_range_relation_eq_ker := Q.span_range_relation_eq_ker_comp P -lemma comp_relation_map (r : Q.rels) : +@[simp] +lemma comp_relation_inr (r : P.rels) : + (Q.comp P).relation (Sum.inr r) = rename Sum.inr (P.relation r) := + rfl + +lemma comp_aeval_relation_inl (r : Q.rels) : aeval (Sum.elim X (MvPolynomial.C ∘ P.val)) ((Q.comp P).relation (Sum.inl r)) = Q.relation r := by show (Q.aux P) _ = _ diff --git a/Mathlib/RingTheory/PrimeSpectrum.lean b/Mathlib/RingTheory/PrimeSpectrum.lean index 07320e17cdf81..e97719ff6ca9f 100644 --- a/Mathlib/RingTheory/PrimeSpectrum.lean +++ b/Mathlib/RingTheory/PrimeSpectrum.lean @@ -5,6 +5,7 @@ Authors: Johan Commelin, Filippo A. E. Nuccio, Andrew Yang -/ import Mathlib.LinearAlgebra.Finsupp import Mathlib.RingTheory.Ideal.Prod +import Mathlib.RingTheory.Localization.Ideal import Mathlib.RingTheory.Nilpotent.Lemmas import Mathlib.RingTheory.Noetherian @@ -480,3 +481,112 @@ end Noetherian end CommSemiRing end PrimeSpectrum + +open PrimeSpectrum + +/-- The pullback of an element of `PrimeSpectrum S` along a ring homomorphism `f : R →+* S`. +The bundled continuous version is `PrimeSpectrum.comap`. -/ +abbrev RingHom.specComap {R S : Type*} [CommSemiring R] [CommSemiring S] (f : R →+* S) : + PrimeSpectrum S → PrimeSpectrum R := + fun y => ⟨Ideal.comap f y.asIdeal, inferInstance⟩ + +namespace PrimeSpectrum + +open RingHom + +variable {R S} {S' : Type*} [CommSemiring R] [CommSemiring S] [CommSemiring S'] + +theorem preimage_specComap_zeroLocus_aux (f : R →+* S) (s : Set R) : + f.specComap ⁻¹' zeroLocus s = zeroLocus (f '' s) := by + ext x + simp only [mem_zeroLocus, Set.image_subset_iff, Set.mem_preimage, mem_zeroLocus, Ideal.coe_comap] + +variable (f : R →+* S) + +@[simp] +theorem specComap_asIdeal (y : PrimeSpectrum S) : + (f.specComap y).asIdeal = Ideal.comap f y.asIdeal := + rfl + +@[simp] +theorem specComap_id : (RingHom.id R).specComap = fun x => x := + rfl + +@[simp] +theorem specComap_comp (f : R →+* S) (g : S →+* S') : + (g.comp f).specComap = f.specComap.comp g.specComap := + rfl + +theorem specComap_comp_apply (f : R →+* S) (g : S →+* S') (x : PrimeSpectrum S') : + (g.comp f).specComap x = f.specComap (g.specComap x) := + rfl + +@[simp] +theorem preimage_specComap_zeroLocus (s : Set R) : + f.specComap ⁻¹' zeroLocus s = zeroLocus (f '' s) := + preimage_specComap_zeroLocus_aux f s + +theorem specComap_injective_of_surjective (f : R →+* S) (hf : Function.Surjective f) : + Function.Injective f.specComap := fun x y h => + PrimeSpectrum.ext + (Ideal.comap_injective_of_surjective f hf + (congr_arg PrimeSpectrum.asIdeal h : (f.specComap x).asIdeal = (f.specComap y).asIdeal)) + +variable (S) + +theorem localization_specComap_injective [Algebra R S] (M : Submonoid R) [IsLocalization M S] : + Function.Injective (algebraMap R S).specComap := by + intro p q h + replace h := _root_.congr_arg (fun x : PrimeSpectrum R => Ideal.map (algebraMap R S) x.asIdeal) h + dsimp only [specComap] at h + rw [IsLocalization.map_comap M S, IsLocalization.map_comap M S] at h + ext1 + exact h + +theorem localization_specComap_range [Algebra R S] (M : Submonoid R) [IsLocalization M S] : + Set.range (algebraMap R S).specComap = { p | Disjoint (M : Set R) p.asIdeal } := by + ext x + constructor + · simp_rw [disjoint_iff_inf_le] + rintro ⟨p, rfl⟩ x ⟨hx₁, hx₂⟩ + exact (p.2.1 : ¬_) (p.asIdeal.eq_top_of_isUnit_mem hx₂ (IsLocalization.map_units S ⟨x, hx₁⟩)) + · intro h + use ⟨x.asIdeal.map (algebraMap R S), IsLocalization.isPrime_of_isPrime_disjoint M S _ x.2 h⟩ + ext1 + exact IsLocalization.comap_map_of_isPrime_disjoint M S _ x.2 h + +end PrimeSpectrum + +section SpecOfSurjective + +open Function RingHom + +variable [CommRing R] [CommRing S] +variable (f : R →+* S) +variable {R} + +theorem image_specComap_zeroLocus_eq_zeroLocus_comap (hf : Surjective f) (I : Ideal S) : + f.specComap '' zeroLocus I = zeroLocus (I.comap f) := by + simp only [Set.ext_iff, Set.mem_image, mem_zeroLocus, SetLike.coe_subset_coe] + refine fun p => ⟨?_, fun h_I_p => ?_⟩ + · rintro ⟨p, hp, rfl⟩ a ha + exact hp ha + · have hp : ker f ≤ p.asIdeal := (Ideal.comap_mono bot_le).trans h_I_p + refine ⟨⟨p.asIdeal.map f, Ideal.map_isPrime_of_surjective hf hp⟩, fun x hx => ?_, ?_⟩ + · obtain ⟨x', rfl⟩ := hf x + exact Ideal.mem_map_of_mem f (h_I_p hx) + · ext x + rw [specComap_asIdeal, Ideal.mem_comap, Ideal.mem_map_iff_of_surjective f hf] + refine ⟨?_, fun hx => ⟨x, hx, rfl⟩⟩ + rintro ⟨x', hx', heq⟩ + rw [← sub_sub_cancel x' x] + refine p.asIdeal.sub_mem hx' (hp ?_) + rwa [mem_ker, map_sub, sub_eq_zero] + +theorem range_specComap_of_surjective (hf : Surjective f) : + Set.range f.specComap = zeroLocus (ker f) := by + rw [← Set.image_univ] + convert image_specComap_zeroLocus_eq_zeroLocus_comap _ _ hf _ + rw [zeroLocus_bot] + +end SpecOfSurjective diff --git a/Mathlib/RingTheory/RingHom/Locally.lean b/Mathlib/RingTheory/RingHom/Locally.lean new file mode 100644 index 0000000000000..fc54b147cef5b --- /dev/null +++ b/Mathlib/RingTheory/RingHom/Locally.lean @@ -0,0 +1,146 @@ +/- +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.RingTheory.LocalProperties.Basic +import Mathlib.RingTheory.Localization.Away.Lemmas + +/-! +# Target local closure of ring homomorphism properties + +If `P` is a property of ring homomorphisms, we call `Locally P` the closure of `P` with +respect to standard open coverings on the (algebraic) target (i.e. geometric source). Hence +for `f : R →+* S`, the property `Locally P` holds if it holds locally on `S`, i.e. if there exists +a subset `{ t }` of `S` generating the unit ideal, such that `P` holds for all compositions +`R →+* Sₜ`. + +Assuming without further mention that `P` is stable under composition with isomorphisms, +`Locally P` is local on the target by construction, i.e. it satisfies +`OfLocalizationSpanTarget`. If `P` itself is local on the target, `Locally P` coincides with `P`. + +The `Locally` construction preserves various properties of `P`, e.g. if `P` is stable under +composition, base change, etc., so is `Locally P`. + +## Main results + +- `RingHom.locally_ofLocalizationSpanTarget`: `Locally P` is local on the target. + +-/ + +universe u v + +open TensorProduct + +namespace RingHom + +variable (P : ∀ {R S : Type u} [CommRing R] [CommRing S] (_ : R →+* S), Prop) + +/-- +For a property of ring homomorphisms `P`, `Locally P` holds for `f : R →+* S` if +it holds locally on `S`, i.e. if there exists a subset `{ t }` of `S` generating +the unit ideal, such that `P` holds for all compositions `R →+* Sₜ`. + +We may require `s` to be finite here, for the equivalence, see `locally_iff_finite`. +-/ +def Locally {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) : Prop := + ∃ (s : Set S) (_ : Ideal.span s = ⊤), + ∀ t ∈ s, P ((algebraMap S (Localization.Away t)).comp f) + +variable {R S : Type u} [CommRing R] [CommRing S] + +lemma locally_iff_finite (f : R →+* S) : + Locally P f ↔ ∃ (s : Finset S) (_ : Ideal.span (s : Set S) = ⊤), + ∀ t ∈ s, P ((algebraMap S (Localization.Away t)).comp f) := by + constructor + · intro ⟨s, hsone, hs⟩ + obtain ⟨s', h₁, h₂⟩ := (Ideal.span_eq_top_iff_finite s).mp hsone + exact ⟨s', h₂, fun t ht ↦ hs t (h₁ ht)⟩ + · intro ⟨s, hsone, hs⟩ + use s, hsone, hs + +variable {P} + +/-- If `P` respects isomorphisms, to check `P` holds locally for `f : R →+* S`, it suffices +to check `P` holds on a standard open cover. -/ +lemma locally_of_exists (hP : RespectsIso P) (f : R →+* S) {ι : Type*} (s : ι → S) + (hsone : Ideal.span (Set.range s) = ⊤) + (Sₜ : ι → Type u) [∀ i, CommRing (Sₜ i)] [∀ i, Algebra S (Sₜ i)] + [∀ i, IsLocalization.Away (s i) (Sₜ i)] (hf : ∀ i, P ((algebraMap S (Sₜ i)).comp f)) : + Locally P f := by + use Set.range s, hsone + rintro - ⟨i, rfl⟩ + let e : Localization.Away (s i) ≃+* Sₜ i := + (IsLocalization.algEquiv (Submonoid.powers (s i)) _ _).toRingEquiv + have : algebraMap S (Localization.Away (s i)) = e.symm.toRingHom.comp (algebraMap S (Sₜ i)) := + RingHom.ext (fun x ↦ (AlgEquiv.commutes (IsLocalization.algEquiv _ _ _).symm _).symm) + rw [this, RingHom.comp_assoc] + exact hP.left _ _ (hf i) + +/-- Equivalence variant of `locally_of_exists`. This is sometimes easier to use, if the +`IsLocalization.Away` instance can't be automatically inferred. -/ +lemma locally_iff_exists (hP : RespectsIso P) (f : R →+* S) : + Locally P f ↔ ∃ (ι : Type u) (s : ι → S) (_ : Ideal.span (Set.range s) = ⊤) (Sₜ : ι → Type u) + (_ : (i : ι) → CommRing (Sₜ i)) (_ : (i : ι) → Algebra S (Sₜ i)) + (_ : (i : ι) → IsLocalization.Away (s i : S) (Sₜ i)), + ∀ i, P ((algebraMap S (Sₜ i)).comp f) := + ⟨fun ⟨s, hsone, hs⟩ ↦ ⟨s, fun t : s ↦ (t : S), by simpa, fun t ↦ Localization.Away (t : S), + inferInstance, inferInstance, inferInstance, fun t ↦ hs t.val t.property⟩, + fun ⟨ι, s, hsone, Sₜ, _, _, hislocal, hs⟩ ↦ locally_of_exists hP f s hsone Sₜ hs⟩ + +/-- In the definition of `Locally` we may replace `Localization.Away` with an arbitrary +algebra satisfying `IsLocalization.Away`. -/ +lemma locally_iff_isLocalization (hP : RespectsIso P) (f : R →+* S) : + Locally P f ↔ ∃ (s : Finset S) (_ : Ideal.span (s : Set S) = ⊤), + ∀ t ∈ s, ∀ (Sₜ : Type u) [CommRing Sₜ] [Algebra S Sₜ] [IsLocalization.Away t Sₜ], + P ((algebraMap S Sₜ).comp f) := by + rw [locally_iff_finite P f] + refine ⟨fun ⟨s, hsone, hs⟩ ↦ ⟨s, hsone, fun t ht Sₜ _ _ _ ↦ ?_⟩, fun ⟨s, hsone, hs⟩ ↦ ?_⟩ + · let e : Localization.Away t ≃+* Sₜ := + (IsLocalization.algEquiv (Submonoid.powers t) _ _).toRingEquiv + have : algebraMap S Sₜ = e.toRingHom.comp (algebraMap S (Localization.Away t)) := + RingHom.ext (fun x ↦ (AlgEquiv.commutes (IsLocalization.algEquiv _ _ _) _).symm) + rw [this, RingHom.comp_assoc] + exact hP.left _ _ (hs t ht) + · exact ⟨s, hsone, fun t ht ↦ hs t ht _⟩ + +/-- If `f` satisfies `P`, then in particular it satisfies `Locally P`. -/ +lemma locally_of (hP : RespectsIso P) (f : R →+* S) (hf : P f) : Locally P f := by + use {1} + let e : S ≃+* Localization.Away (1 : S) := + (IsLocalization.atUnits S (Submonoid.powers 1) (by simp)).toRingEquiv + simp only [Set.mem_singleton_iff, forall_eq, Ideal.span_singleton_one, exists_const] + exact hP.left f e hf + +/-- If `P` is local on the target, then `Locally P` coincides with `P`. -/ +lemma locally_iff_of_localizationSpanTarget (hPi : RespectsIso P) + (hPs : OfLocalizationSpanTarget P) {R S : Type u} [CommRing R] [CommRing S] (f : R →+* S) : + Locally P f ↔ P f := + ⟨fun ⟨s, hsone, hs⟩ ↦ hPs f s hsone (fun a ↦ hs a.val a.property), locally_of hPi f⟩ + +section OfLocalizationSpanTarget + +/-- `Locally P` is local on the target. -/ +lemma locally_ofLocalizationSpanTarget (hP : RespectsIso P) : + OfLocalizationSpanTarget (Locally P) := by + intro R S _ _ f s hsone hs + choose t htone ht using hs + rw [locally_iff_exists hP] + refine ⟨(a : s) × t a, IsLocalization.Away.mulNumerator s t, + IsLocalization.Away.span_range_mulNumerator_eq_top hsone htone, + fun ⟨a, b⟩ ↦ Localization.Away b.val, inferInstance, inferInstance, fun ⟨a, b⟩ ↦ ?_, ?_⟩ + · haveI : IsLocalization.Away ((algebraMap S (Localization.Away a.val)) + (IsLocalization.Away.sec a.val b.val).1) (Localization.Away b.val) := by + apply IsLocalization.Away.of_associated (r := b.val) + rw [← IsLocalization.Away.sec_spec] + apply associated_mul_unit_right + rw [map_pow _ _] + exact IsUnit.pow _ (IsLocalization.Away.algebraMap_isUnit _) + apply IsLocalization.Away.mul' (Localization.Away a.val) (Localization.Away b.val) + · intro ⟨a, b⟩ + rw [IsScalarTower.algebraMap_eq S (Localization.Away a.val) (Localization.Away b.val)] + apply ht _ _ b.property + +end OfLocalizationSpanTarget + +end RingHom diff --git a/Mathlib/RingTheory/RingHomProperties.lean b/Mathlib/RingTheory/RingHomProperties.lean index 280f3184fd167..7008cd0ef9a74 100644 --- a/Mathlib/RingTheory/RingHomProperties.lean +++ b/Mathlib/RingTheory/RingHomProperties.lean @@ -179,15 +179,17 @@ variable {P} lemma toMorphismProperty_respectsIso_iff : RespectsIso P ↔ (toMorphismProperty P).RespectsIso := by - refine ⟨fun h ↦ ⟨?_, ?_⟩, fun h ↦ ⟨?_, ?_⟩⟩ + refine ⟨fun h ↦ MorphismProperty.RespectsIso.mk _ ?_ ?_, fun h ↦ ⟨?_, ?_⟩⟩ · intro X Y Z e f hf exact h.right f e.commRingCatIsoToRingEquiv hf · intro X Y Z e f hf exact h.left f e.commRingCatIsoToRingEquiv hf + · intro X Y Z _ _ _ f e hf + exact MorphismProperty.RespectsIso.postcomp (toMorphismProperty P) + e.toCommRingCatIso.hom (CommRingCat.ofHom f) hf · intro X Y Z _ _ _ f e - exact h.postcomp e.toCommRingCatIso (CommRingCat.ofHom f) - · intro X Y Z _ _ _ f e - exact h.precomp e.toCommRingCatIso (CommRingCat.ofHom f) + exact MorphismProperty.RespectsIso.precomp (toMorphismProperty P) + e.toCommRingCatIso.hom (CommRingCat.ofHom f) end ToMorphismProperty diff --git a/Mathlib/RingTheory/RootsOfUnity/Complex.lean b/Mathlib/RingTheory/RootsOfUnity/Complex.lean index ec56155951282..a11bd30bfad0a 100644 --- a/Mathlib/RingTheory/RootsOfUnity/Complex.lean +++ b/Mathlib/RingTheory/RootsOfUnity/Complex.lean @@ -168,7 +168,7 @@ theorem IsPrimitiveRoot.arg {n : ℕ} {ζ : ℂ} (h : IsPrimitiveRoot ζ n) (hn exact mul_nonpos_of_nonpos_of_nonneg (sub_nonpos.mpr <| mod_cast h.le) (div_nonneg (by simp [Real.pi_pos.le]) <| by simp) rw [← mul_rotate', mul_div_assoc, neg_lt, ← mul_neg, mul_lt_iff_lt_one_right Real.pi_pos, ← - neg_div, ← neg_mul, neg_sub, div_lt_iff, one_mul, sub_mul, sub_lt_comm, ← mul_sub_one] + neg_div, ← neg_mul, neg_sub, div_lt_iff₀, one_mul, sub_mul, sub_lt_comm, ← mul_sub_one] · norm_num exact mod_cast not_le.mp h₂ · exact Nat.cast_pos.mpr hn.bot_lt diff --git a/Mathlib/RingTheory/SimpleModule.lean b/Mathlib/RingTheory/SimpleModule.lean index 5bc001188d6d1..9a27c4b72d304 100644 --- a/Mathlib/RingTheory/SimpleModule.lean +++ b/Mathlib/RingTheory/SimpleModule.lean @@ -163,7 +163,7 @@ theorem isSimpleModule_self_iff_isUnit : exact ⟨⟨x, y, left_inv_eq_right_inv hzy hyx ▸ hzy, hyx⟩, rfl⟩ theorem isSimpleModule_iff_finrank_eq_one {R} [DivisionRing R] [Module R M] : - IsSimpleModule R M ↔ FiniteDimensional.finrank R M = 1 := + IsSimpleModule R M ↔ Module.finrank R M = 1 := ⟨fun h ↦ have := h.nontrivial; have ⟨v, hv⟩ := exists_ne (0 : M) (finrank_eq_one_iff_of_nonzero' v hv).mpr (IsSimpleModule.toSpanSingleton_surjective R hv), is_simple_module_of_finrank_eq_one⟩ @@ -338,7 +338,7 @@ variable (ι R) proof_wanted IsSemisimpleRing.mulOpposite [IsSemisimpleRing R] : IsSemisimpleRing Rᵐᵒᵖ -proof_wanted IsSemisimpleRing.module_end [IsSemisimpleRing R] [Module.Finite R M] : +proof_wanted IsSemisimpleRing.module_end [IsSemisimpleModule R M] [Module.Finite R M] : IsSemisimpleRing (Module.End R M) proof_wanted IsSemisimpleRing.matrix [Fintype ι] [DecidableEq ι] [IsSemisimpleRing R] : diff --git a/Mathlib/RingTheory/SimpleRing/Basic.lean b/Mathlib/RingTheory/SimpleRing/Basic.lean index c9f5a875cc0b8..3f9711cafff02 100644 --- a/Mathlib/RingTheory/SimpleRing/Basic.lean +++ b/Mathlib/RingTheory/SimpleRing/Basic.lean @@ -82,6 +82,6 @@ lemma isField_center (A : Type*) [Ring A] [IsSimpleRing A] : IsField (Subring.ce end IsSimpleRing lemma isSimpleRing_iff_isField (A : Type*) [CommRing A] : IsSimpleRing A ↔ IsField A := - ⟨fun _ ↦ Subring.topEquiv.symm.toMulEquiv.isField <| by + ⟨fun _ ↦ Subring.topEquiv.symm.toMulEquiv.isField _ <| by rw [← Subring.center_eq_top A]; exact IsSimpleRing.isField_center A, fun h ↦ letI := h.toField; inferInstance⟩ diff --git a/Mathlib/RingTheory/Smooth/Basic.lean b/Mathlib/RingTheory/Smooth/Basic.lean index d61b49519ff71..179e34269a3af 100644 --- a/Mathlib/RingTheory/Smooth/Basic.lean +++ b/Mathlib/RingTheory/Smooth/Basic.lean @@ -60,7 +60,7 @@ section variable {R : Type u} [CommSemiring R] variable {A : Type u} [Semiring A] [Algebra R A] -variable {B : Type u} [CommRing B] [Algebra R B] (I : Ideal B) +variable {B : Type u} [CommRing B] [Algebra R B] theorem exists_lift {B : Type u} [CommRing B] [_RB : Algebra R B] [FormallySmooth R A] (I : Ideal B) (hI : IsNilpotent I) (g : A →ₐ[R] B ⧸ I) : @@ -187,9 +187,9 @@ end Comp section OfSurjective -variable {R S : Type u} [CommRing R] [CommSemiring S] +variable {R : Type u} [CommRing R] variable {P A : Type u} [CommRing A] [Algebra R A] [CommRing P] [Algebra R P] -variable (I : Ideal P) (f : P →ₐ[R] A) +variable (f : P →ₐ[R] A) theorem of_split [FormallySmooth R P] (g : A →ₐ[R] P ⧸ (RingHom.ker f.toRingHom) ^ 2) (hg : f.kerSquareLift.comp g = AlgHom.id R A) : FormallySmooth R A := by diff --git a/Mathlib/RingTheory/Smooth/StandardSmooth.lean b/Mathlib/RingTheory/Smooth/StandardSmooth.lean index d8064eb6a7e8c..988a61b9c879e 100644 --- a/Mathlib/RingTheory/Smooth/StandardSmooth.lean +++ b/Mathlib/RingTheory/Smooth/StandardSmooth.lean @@ -62,10 +62,6 @@ Finally, for ring homomorphisms we define: ## TODO -- Show that the canonical presentation for localization away from an element is standard smooth - of relative dimension 0. -- Show that the composition of submersive presentations of relative dimensions `n` and `m` is - submersive of relative dimension `n + m`. - Show that the module of Kaehler differentials of a standard smooth `R`-algebra `S` of relative dimension `n` is `S`-free of rank `n`. In particular this shows that the relative dimension is independent of the choice of the standard smooth presentation. @@ -87,9 +83,9 @@ in June 2024. universe t t' w w' u v -open TensorProduct Classical +open TensorProduct MvPolynomial Classical -variable (n : ℕ) +variable (n m : ℕ) namespace Algebra @@ -161,7 +157,7 @@ lemma jacobian_eq_jacobiMatrix_det : P.jacobian = algebraMap P.Ring S P.jacobiMa lemma jacobiMatrix_apply (i j : P.rels) : P.jacobiMatrix i j = MvPolynomial.pderiv (P.map i) (P.relation j) := by - simp [jacobiMatrix, LinearMap.toMatrix, differential] + simp [jacobiMatrix, LinearMap.toMatrix, differential, basis] end Matrix @@ -182,6 +178,7 @@ instance (h : Function.Bijective (algebraMap R S)) : Fintype (ofBijectiveAlgebra instance (h : Function.Bijective (algebraMap R S)) : Fintype (ofBijectiveAlgebraMap h).rels := inferInstanceAs (Fintype PEmpty) +@[simp] lemma ofBijectiveAlgebraMap_jacobian (h : Function.Bijective (algebraMap R S)) : (ofBijectiveAlgebraMap h).jacobian = 1 := by have : (algebraMap (ofBijectiveAlgebraMap h).Ring S).mapMatrix @@ -190,7 +187,167 @@ lemma ofBijectiveAlgebraMap_jacobian (h : Function.Bijective (algebraMap R S)) : contradiction rw [jacobian_eq_jacobiMatrix_det, RingHom.map_det, this, Matrix.det_one] -open MvPolynomial +section Localization + +variable (r : R) [IsLocalization.Away r S] + +variable (S) in +/-- If `S` is the localization of `R` at `r`, this is the canonical submersive presentation +of `S` as `R`-algebra. -/ +@[simps map] +noncomputable def localizationAway : PreSubmersivePresentation R S where + __ := Presentation.localizationAway S r + map _ := () + map_inj _ _ h := h + relations_finite := inferInstanceAs <| Finite Unit + +instance : Fintype (localizationAway S r).rels := + inferInstanceAs (Fintype Unit) + +instance : DecidableEq (localizationAway S r).rels := + inferInstanceAs (DecidableEq Unit) + +@[simp] +lemma localizationAway_jacobiMatrix : + (localizationAway S r).jacobiMatrix = Matrix.diagonal (fun () ↦ MvPolynomial.C r) := by + have h : (pderiv ()) (C r * X () - 1) = C r := by simp + ext (i : Unit) (j : Unit) : 1 + rwa [jacobiMatrix_apply] + +@[simp] +lemma localizationAway_jacobian : (localizationAway S r).jacobian = algebraMap R S r := by + rw [jacobian_eq_jacobiMatrix_det, localizationAway_jacobiMatrix] + simp [show Fintype.card (localizationAway r (S := S)).rels = 1 from rfl] + +end Localization + +section Composition + +variable {T} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] +variable (Q : PreSubmersivePresentation S T) (P : PreSubmersivePresentation R S) + +/-- Given an `R`-algebra `S` and an `S`-algebra `T` with pre-submersive presentations, +this is the canonical pre-submersive presentation of `T` as an `R`-algebra. -/ +@[simps map] +noncomputable def comp : PreSubmersivePresentation R T where + __ := Q.toPresentation.comp P.toPresentation + map := Sum.elim (fun rq ↦ Sum.inl <| Q.map rq) (fun rp ↦ Sum.inr <| P.map rp) + map_inj := Function.Injective.sum_elim ((Sum.inl_injective).comp (Q.map_inj)) + ((Sum.inr_injective).comp (P.map_inj)) <| by simp + relations_finite := inferInstanceAs <| Finite (Q.rels ⊕ P.rels) + +/-- The dimension of the composition of two finite submersive presentations is +the sum of the dimensions. -/ +lemma dimension_comp_eq_dimension_add_dimension [Q.IsFinite] [P.IsFinite] : + (Q.comp P).dimension = Q.dimension + P.dimension := by + simp only [Presentation.dimension] + erw [Presentation.comp_rels, Generators.comp_vars] + have : Nat.card P.rels ≤ Nat.card P.vars := + card_relations_le_card_vars_of_isFinite P + have : Nat.card Q.rels ≤ Nat.card Q.vars := + card_relations_le_card_vars_of_isFinite Q + simp only [Nat.card_sum] + omega + +section + +/-! +### Jacobian of composition + +Let `S` be an `R`-algebra and `T` be an `S`-algebra with presentations `P` and `Q` respectively. +In this section we compute the jacobian of the composition of `Q` and `P` to be +the product of the jacobians. For this we use a block decomposition of the jacobi matrix and show +that the upper-right block vanishes, the upper-left block has determinant jacobian of `Q` and +the lower-right block has determinant jacobian of `P`. + +-/ + +variable [Fintype (Q.comp P).rels] + +private lemma jacobiMatrix_comp_inl_inr (i : Q.rels) (j : P.rels) : + (Q.comp P).jacobiMatrix (Sum.inl i) (Sum.inr j) = 0 := by + rw [jacobiMatrix_apply] + refine MvPolynomial.pderiv_eq_zero_of_not_mem_vars (fun hmem ↦ ?_) + apply MvPolynomial.vars_rename at hmem + simp at hmem + +private lemma jacobiMatrix_comp_₁₂ : (Q.comp P).jacobiMatrix.toBlocks₁₂ = 0 := by + ext i j : 1 + simp [Matrix.toBlocks₁₂, jacobiMatrix_comp_inl_inr] + +section Q + +variable [Fintype Q.rels] + +private lemma jacobiMatrix_comp_inl_inl (i j : Q.rels) : + aeval (Sum.elim X (MvPolynomial.C ∘ P.val)) + ((Q.comp P).jacobiMatrix (Sum.inl j) (Sum.inl i)) = Q.jacobiMatrix j i := by + rw [jacobiMatrix_apply, jacobiMatrix_apply, comp_map, Sum.elim_inl, + ← Q.comp_aeval_relation_inl P.toPresentation] + apply aeval_sum_elim_pderiv_inl + +private lemma jacobiMatrix_comp_₁₁_det : + (aeval (Q.comp P).val) (Q.comp P).jacobiMatrix.toBlocks₁₁.det = Q.jacobian := by + rw [jacobian_eq_jacobiMatrix_det, AlgHom.map_det (aeval (Q.comp P).val), RingHom.map_det] + congr + ext i j : 1 + simp only [Matrix.map_apply, RingHom.mapMatrix_apply, ← Q.jacobiMatrix_comp_inl_inl P] + apply aeval_sum_elim + +end Q + +section P + +variable [Fintype P.rels] + +private lemma jacobiMatrix_comp_inr_inr (i j : P.rels) : + (Q.comp P).jacobiMatrix (Sum.inr i) (Sum.inr j) = + MvPolynomial.rename Sum.inr (P.jacobiMatrix i j) := by + rw [jacobiMatrix_apply, jacobiMatrix_apply] + simp only [comp_map, Sum.elim_inr] + apply pderiv_rename Sum.inr_injective + +private lemma jacobiMatrix_comp_₂₂_det : + (aeval (Q.comp P).val) (Q.comp P).jacobiMatrix.toBlocks₂₂.det = algebraMap S T P.jacobian := by + rw [jacobian_eq_jacobiMatrix_det] + rw [AlgHom.map_det (aeval (Q.comp P).val), RingHom.map_det, RingHom.map_det] + congr + ext i j : 1 + simp only [Matrix.toBlocks₂₂, AlgHom.mapMatrix_apply, Matrix.map_apply, Matrix.of_apply, + RingHom.mapMatrix_apply, Generators.algebraMap_apply, map_aeval, coe_eval₂Hom] + rw [jacobiMatrix_comp_inr_inr, ← IsScalarTower.algebraMap_eq] + simp only [aeval, AlgHom.coe_mk, coe_eval₂Hom] + generalize P.jacobiMatrix i j = p + induction' p using MvPolynomial.induction_on with a p q hp hq p i hp + · simp only [algHom_C, algebraMap_eq, eval₂_C] + erw [MvPolynomial.eval₂_C] + · simp [hp, hq] + · simp only [map_mul, rename_X, eval₂_mul, hp, eval₂_X] + erw [Generators.comp_val] + simp + +end P + +end + +/-- The jacobian of the composition of presentations is the product of the jacobians. -/ +@[simp] +lemma comp_jacobian_eq_jacobian_smul_jacobian : (Q.comp P).jacobian = P.jacobian • Q.jacobian := by + cases nonempty_fintype Q.rels + cases nonempty_fintype P.rels + letI : Fintype (Q.comp P).rels := inferInstanceAs <| Fintype (Q.rels ⊕ P.rels) + rw [jacobian_eq_jacobiMatrix_det, ← Matrix.fromBlocks_toBlocks ((Q.comp P).jacobiMatrix), + jacobiMatrix_comp_₁₂] + convert_to + (aeval (Q.comp P).val) (Q.comp P).jacobiMatrix.toBlocks₁₁.det * + (aeval (Q.comp P).val) (Q.comp P).jacobiMatrix.toBlocks₂₂.det = P.jacobian • Q.jacobian + · simp only [Generators.algebraMap_apply, ← map_mul] + congr + convert Matrix.det_fromBlocks_zero₁₂ (Q.comp P).jacobiMatrix.toBlocks₁₁ + (Q.comp P).jacobiMatrix.toBlocks₂₁ (Q.comp P).jacobiMatrix.toBlocks₂₂ + · rw [jacobiMatrix_comp_₁₁_det, jacobiMatrix_comp_₂₂_det, mul_comm, Algebra.smul_def] + +end Composition section BaseChange @@ -204,6 +361,7 @@ noncomputable def baseChange : PreSubmersivePresentation T (T ⊗[R] S) where map_inj := P.map_inj relations_finite := P.relations_finite +@[simp] lemma baseChange_jacobian : (P.baseChange T).jacobian = 1 ⊗ₜ P.jacobian := by classical cases nonempty_fintype P.rels @@ -258,6 +416,37 @@ noncomputable def ofBijectiveAlgebraMap (h : Function.Bijective (algebraMap R S) noncomputable def id : SubmersivePresentation.{t, w} R R := ofBijectiveAlgebraMap Function.bijective_id +section Composition + +variable {R S T} [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] +variable (Q : SubmersivePresentation S T) (P : SubmersivePresentation R S) + +/-- Given an `R`-algebra `S` and an `S`-algebra `T` with submersive presentations, +this is the canonical submersive presentation of `T` as an `R`-algebra. -/ +noncomputable def comp : SubmersivePresentation R T where + __ := Q.toPreSubmersivePresentation.comp P.toPreSubmersivePresentation + jacobian_isUnit := by + rw [comp_jacobian_eq_jacobian_smul_jacobian, Algebra.smul_def, IsUnit.mul_iff] + exact ⟨RingHom.isUnit_map _ <| P.jacobian_isUnit, Q.jacobian_isUnit⟩ + isFinite := Presentation.comp_isFinite Q.toPresentation P.toPresentation + +end Composition + +section Localization + +variable {R} (r : R) [IsLocalization.Away r S] + +/-- If `S` is the localization of `R` at `r`, this is the canonical submersive presentation +of `S` as `R`-algebra. -/ +noncomputable def localizationAway : SubmersivePresentation R S where + __ := PreSubmersivePresentation.localizationAway S r + jacobian_isUnit := by + rw [localizationAway_jacobian] + apply IsLocalization.map_units' (⟨r, 1, by simp⟩ : Submonoid.powers r) + isFinite := Presentation.localizationAway_isFinite r + +end Localization + section BaseChange variable (T) [CommRing T] [Algebra R T] (P : SubmersivePresentation R S) @@ -316,6 +505,37 @@ instance IsStandardSmoothOfRelativeDimension.id : IsStandardSmoothOfRelativeDimension.{t, w} 0 R R := IsStandardSmoothOfRelativeDimension.of_algebraMap_bijective Function.bijective_id +section Composition + +variable (R S T) [CommRing T] [Algebra R T] [Algebra S T] [IsScalarTower R S T] + +lemma IsStandardSmooth.trans [IsStandardSmooth.{t, w} R S] [IsStandardSmooth.{t', w'} S T] : + IsStandardSmooth.{max t t', max w w'} R T where + out := by + obtain ⟨⟨P⟩⟩ := ‹IsStandardSmooth R S› + obtain ⟨⟨Q⟩⟩ := ‹IsStandardSmooth S T› + exact ⟨Q.comp P⟩ + +lemma IsStandardSmoothOfRelativeDimension.trans [IsStandardSmoothOfRelativeDimension.{t, w} n R S] + [IsStandardSmoothOfRelativeDimension.{t', w'} m S T] : + IsStandardSmoothOfRelativeDimension.{max t t', max w w'} (m + n) R T where + out := by + obtain ⟨P, hP⟩ := ‹IsStandardSmoothOfRelativeDimension n R S› + obtain ⟨Q, hQ⟩ := ‹IsStandardSmoothOfRelativeDimension m S T› + refine ⟨Q.comp P, hP ▸ hQ ▸ ?_⟩ + apply PreSubmersivePresentation.dimension_comp_eq_dimension_add_dimension + +end Composition + +lemma IsStandardSmooth.localization_away (r : R) [IsLocalization.Away r S] : + IsStandardSmooth.{0, 0} R S where + out := ⟨SubmersivePresentation.localizationAway S r⟩ + +lemma IsStandardSmoothOfRelativeDimension.localization_away (r : R) [IsLocalization.Away r S] : + IsStandardSmoothOfRelativeDimension.{0, 0} 0 R S where + out := ⟨SubmersivePresentation.localizationAway S r, + Presentation.localizationAway_dimension_zero r⟩ + section BaseChange variable (T) [CommRing T] [Algebra R T] @@ -324,14 +544,14 @@ instance IsStandardSmooth.baseChange [IsStandardSmooth.{t, w} R S] : IsStandardSmooth.{t, w} T (T ⊗[R] S) where out := by obtain ⟨⟨P⟩⟩ := ‹IsStandardSmooth R S› - exact ⟨P.baseChange T⟩ + exact ⟨P.baseChange R S T⟩ instance IsStandardSmoothOfRelativeDimension.baseChange [IsStandardSmoothOfRelativeDimension.{t, w} n R S] : IsStandardSmoothOfRelativeDimension.{t, w} n T (T ⊗[R] S) where out := by obtain ⟨P, hP⟩ := ‹IsStandardSmoothOfRelativeDimension n R S› - exact ⟨P.baseChange T, hP⟩ + exact ⟨P.baseChange R S T, hP⟩ end BaseChange diff --git a/Mathlib/RingTheory/SurjectiveOnStalks.lean b/Mathlib/RingTheory/SurjectiveOnStalks.lean index 67f0451472874..94c5443047b71 100644 --- a/Mathlib/RingTheory/SurjectiveOnStalks.lean +++ b/Mathlib/RingTheory/SurjectiveOnStalks.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Andrew Yang -/ import Mathlib.RingTheory.Localization.AtPrime -import Mathlib.RingTheory.LocalRing.RingHom.Basic import Mathlib.RingTheory.TensorProduct.Basic /-! diff --git a/Mathlib/RingTheory/Trace/Basic.lean b/Mathlib/RingTheory/Trace/Basic.lean index ee8a5a44c08f7..e06b0141ff923 100644 --- a/Mathlib/RingTheory/Trace/Basic.lean +++ b/Mathlib/RingTheory/Trace/Basic.lean @@ -5,7 +5,7 @@ Authors: Anne Baanen -/ import Mathlib.RingTheory.Trace.Defs import Mathlib.LinearAlgebra.Determinant -import Mathlib.FieldTheory.Galois +import Mathlib.FieldTheory.Galois.Basic import Mathlib.LinearAlgebra.Matrix.Charpoly.Minpoly import Mathlib.LinearAlgebra.Vandermonde import Mathlib.FieldTheory.Minpoly.MinpolyDiv @@ -47,7 +47,7 @@ variable [Algebra R S] [Algebra R T] variable {K L : Type*} [Field K] [Field L] [Algebra K L] variable {ι κ : Type w} [Fintype ι] -open FiniteDimensional +open Module open LinearMap (BilinForm) open LinearMap @@ -435,7 +435,7 @@ variable (K L) theorem traceForm_nondegenerate [FiniteDimensional K L] [Algebra.IsSeparable K L] : (traceForm K L).Nondegenerate := BilinForm.nondegenerate_of_det_ne_zero (traceForm K L) _ - (det_traceForm_ne_zero (FiniteDimensional.finBasis K L)) + (det_traceForm_ne_zero (Module.finBasis K L)) theorem Algebra.trace_ne_zero [FiniteDimensional K L] [Algebra.IsSeparable K L] : Algebra.trace K L ≠ 0 := by diff --git a/Mathlib/RingTheory/Trace/Defs.lean b/Mathlib/RingTheory/Trace/Defs.lean index 86218f0b3ecff..8d961bf7c82e6 100644 --- a/Mathlib/RingTheory/Trace/Defs.lean +++ b/Mathlib/RingTheory/Trace/Defs.lean @@ -48,7 +48,7 @@ variable {R S T : Type*} [CommRing R] [CommRing S] [CommRing T] variable [Algebra R S] [Algebra R T] variable {ι κ : Type w} [Fintype ι] -open FiniteDimensional +open Module open LinearMap (BilinForm) open LinearMap diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean b/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean index 8be0b86366462..dd7cee192929b 100644 --- a/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean +++ b/Mathlib/RingTheory/TwoSidedIdeal/Basic.lean @@ -156,17 +156,18 @@ def mk' (carrier : Set R) rw [show a + c - (b + d) = (a - b) + (c - d) by abel] exact add_mem h1 h2 } -lemma mem_mk' (carrier : Set R) - (zero_mem : 0 ∈ carrier) - (add_mem : ∀ {x y}, x ∈ carrier → y ∈ carrier → x + y ∈ carrier) - (neg_mem : ∀ {x}, x ∈ carrier → -x ∈ carrier) - (mul_mem_left : ∀ {x y}, y ∈ carrier → x * y ∈ carrier) - (mul_mem_right : ∀ {x y}, x ∈ carrier → x * y ∈ carrier) - (x : R) : +@[simp] +lemma mem_mk' (carrier : Set R) (zero_mem add_mem neg_mem mul_mem_left mul_mem_right) (x : R) : x ∈ mk' carrier zero_mem add_mem neg_mem mul_mem_left mul_mem_right ↔ x ∈ carrier := by rw [mem_iff] simp [mk'] +set_option linter.docPrime false in +@[simp] +lemma coe_mk' (carrier : Set R) (zero_mem add_mem neg_mem mul_mem_left mul_mem_right) : + (mk' carrier zero_mem add_mem neg_mem mul_mem_left mul_mem_right : Set R) = carrier := + Set.ext <| mem_mk' carrier zero_mem add_mem neg_mem mul_mem_left mul_mem_right + instance : SMulMemClass (TwoSidedIdeal R) R R where smul_mem _ _ h := TwoSidedIdeal.mul_mem_left _ _ _ h diff --git a/Mathlib/RingTheory/TwoSidedIdeal/BigOperators.lean b/Mathlib/RingTheory/TwoSidedIdeal/BigOperators.lean new file mode 100644 index 0000000000000..8ed5a222e9ed2 --- /dev/null +++ b/Mathlib/RingTheory/TwoSidedIdeal/BigOperators.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jujian Zhang +-/ + +import Mathlib.RingTheory.Congruence.BigOperators +import Mathlib.RingTheory.TwoSidedIdeal.Basic + +/-! +# Interactions between `∑, ∏` and two sided ideals + +-/ + +namespace TwoSidedIdeal + +section sum + +variable {R : Type*} [NonUnitalNonAssocRing R] (I : TwoSidedIdeal R) + +lemma listSum_mem {ι : Type*} (l : List ι) (f : ι → R) (hl : ∀ x ∈ l, f x ∈ I) : + (l.map f).sum ∈ I := by + rw [mem_iff, ← List.sum_map_zero] + exact I.ringCon.listSum l hl + +lemma multisetSum_mem {ι : Type*} (s : Multiset ι) (f : ι → R) (hs : ∀ x ∈ s, f x ∈ I) : + (s.map f).sum ∈ I := by + rw [mem_iff, ← Multiset.sum_map_zero] + exact I.ringCon.multisetSum s hs + +lemma finsetSum_mem {ι : Type*} (s : Finset ι) (f : ι → R) (hs : ∀ x ∈ s, f x ∈ I) : + s.sum f ∈ I := by + rw [mem_iff, ← Finset.sum_const_zero] + exact I.ringCon.finsetSum s hs + +end sum + +section prod + +section ring + +variable {R : Type*} [Ring R] (I : TwoSidedIdeal R) + +lemma listProd_mem {ι : Type*} (l : List ι) (f : ι → R) (hl : ∃ x ∈ l, f x ∈ I) : + (l.map f).prod ∈ I := by + induction l with + | nil => simp only [List.not_mem_nil, false_and, exists_false] at hl + | cons x l ih => + simp only [List.mem_cons, exists_eq_or_imp] at hl + rcases hl with h | hal + · simpa only [List.map_cons, List.prod_cons] using I.mul_mem_right _ _ h + · simpa only [List.map_cons, List.prod_cons] using I.mul_mem_left _ _ <| ih hal + +end ring + +section commRing + +variable {R : Type*} [CommRing R] (I : TwoSidedIdeal R) + +lemma multiSetProd_mem {ι : Type*} (s : Multiset ι) (f : ι → R) (hs : ∃ x ∈ s, f x ∈ I) : + (s.map f).prod ∈ I := by + rcases s + simpa using listProd_mem (hl := hs) + +lemma finsetProd_mem {ι : Type*} (s : Finset ι) (f : ι → R) (hs : ∃ x ∈ s, f x ∈ I) : + s.prod f ∈ I := by + rcases s + simpa using multiSetProd_mem (hs := hs) + +end commRing + +end prod + +end TwoSidedIdeal diff --git a/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean b/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean new file mode 100644 index 0000000000000..78ccd01d0a217 --- /dev/null +++ b/Mathlib/RingTheory/TwoSidedIdeal/Operations.lean @@ -0,0 +1,300 @@ +/- +Copyright (c) 2024 Jujian Zhang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jujian Zhang, Jireh Loreaux +-/ + +import Mathlib.RingTheory.TwoSidedIdeal.Lattice +import Mathlib.RingTheory.Congruence.Opposite +import Mathlib.Algebra.BigOperators.Ring +import Mathlib.Data.Fintype.BigOperators +import Mathlib.RingTheory.Ideal.Basic +import Mathlib.Order.GaloisConnection + +/-! +# Operations on two-sided ideals + +This file defines operations on two-sided ideals of a ring `R`. + +## Main definitions and results + +- `TwoSidedIdeal.span`: the span of `s ⊆ R` is the smallest two-sided ideal containing the set. +- `TwoSidedIdeal.mem_span_iff_mem_addSubgroup_closure_nonunital`: in an associative but non-unital + ring, an element `x` is in the two-sided ideal spanned by `s` if and only if `x` is in the closure + of `s ∪ {y * a | y ∈ s, a ∈ R} ∪ {a * y | y ∈ s, a ∈ R} ∪ {a * y * b | y ∈ s, a, b ∈ R}` as an + additive subgroup. +- `TwoSidedIdeal.mem_span_iff_mem_addSubgroup_closure`: in a unital and associative ring, an + element `x` is in the two-sided ideal spanned by `s` if and only if `x` is in the closure of + `{a*y*b | a, b ∈ R, y ∈ s}` as an additive subgroup. + + +- `TwoSidedIdeal.comap`: pullback of a two-sided ideal; defined as the preimage of a + two-sided ideal. +- `TwoSidedIdeal.map`: pushforward of a two-sided ideal; defined as the span of the image of a + two-sided ideal. +- `TwoSidedIdeal.ker`: the kernel of a ring homomorphism as a two-sided ideal. + +- `TwoSidedIdeal.gc`: `fromIdeal` and `asIdeal` form a Galois connection where + `fromIdeal : Ideal R → TwoSidedIdeal R` is defined as the smallest two-sided ideal containing an + ideal and `asIdeal : TwoSidedIdeal R → Ideal R` the inclusion map. +-/ + +namespace TwoSidedIdeal + +section NonUnitalNonAssocRing + +variable {R S : Type*} [NonUnitalNonAssocRing R] [NonUnitalNonAssocRing S] +variable {F : Type*} [FunLike F R S] +variable (f : F) + +/-- +The smallest two-sided ideal containing a set. +-/ +abbrev span (s : Set R) : TwoSidedIdeal R := + { ringCon := ringConGen (fun a b ↦ a - b ∈ s) } + +lemma subset_span {s : Set R} : s ⊆ (span s : Set R) := by + intro x hx + rw [SetLike.mem_coe, mem_iff] + exact RingConGen.Rel.of _ _ (by simpa using hx) + +lemma mem_span_iff {s : Set R} {x} : + x ∈ span s ↔ ∀ (I : TwoSidedIdeal R), s ⊆ I → x ∈ I := by + refine ⟨?_, fun h => h _ subset_span⟩ + delta span + rw [RingCon.ringConGen_eq] + intro h I hI + refine sInf_le (α := RingCon R) ?_ h + intro x y hxy + specialize hI hxy + rwa [SetLike.mem_coe, ← rel_iff] at hI + +lemma span_mono {s t : Set R} (h : s ⊆ t) : span s ≤ span t := by + intro x hx + rw [mem_span_iff] at hx ⊢ + exact fun I hI => hx I <| h.trans hI + +/-- +Pushout of a two-sided ideal. Defined as the span of the image of a two-sided ideal under a ring +homomorphism. +-/ +def map (I : TwoSidedIdeal R) : TwoSidedIdeal S := + span (f '' I) + +lemma map_mono {I J : TwoSidedIdeal R} (h : I ≤ J) : + map f I ≤ map f J := + span_mono <| Set.image_mono h + +variable [NonUnitalRingHomClass F R S] + +/-- +Preimage of a two-sided ideal, as a two-sided ideal. -/ +def comap (I : TwoSidedIdeal S) : TwoSidedIdeal R := +{ ringCon := I.ringCon.comap f } + +lemma mem_comap {I : TwoSidedIdeal S} {x : R} : + x ∈ I.comap f ↔ f x ∈ I := by + simp [comap, RingCon.comap, mem_iff] + +/-- +The kernel of a ring homomorphism, as a two-sided ideal. +-/ +def ker : TwoSidedIdeal R := + .mk' + {r | f r = 0} (map_zero _) (by rintro _ _ (h1 : f _ = 0) (h2 : f _ = 0); simp [h1, h2]) + (by rintro _ (h : f _ = 0); simp [h]) (by rintro _ _ (h : f _ = 0); simp [h]) + (by rintro _ _ (h : f _ = 0); simp [h]) + +lemma mem_ker {x : R} : x ∈ ker f ↔ f x = 0 := by + delta ker; rw [mem_mk']; rfl + +end NonUnitalNonAssocRing + +section NonUnitalRing + +variable {R : Type*} [NonUnitalRing R] + +open AddSubgroup in +/-- If `s : Set R` is absorbing under multiplication, then its `TwoSidedIdeal.span` coincides with +its `AddSubgroup.closure`, as sets. -/ +lemma mem_span_iff_mem_addSubgroup_closure_absorbing {s : Set R} + (h_left : ∀ x y, y ∈ s → x * y ∈ s) (h_right : ∀ y x, y ∈ s → y * x ∈ s) {z : R} : + z ∈ span s ↔ z ∈ closure s := by + have h_left' {x y} (hy : y ∈ closure s) : x * y ∈ closure s := by + have := (AddMonoidHom.mulLeft x).map_closure s ▸ mem_map_of_mem _ hy + refine closure_mono ?_ this + rintro - ⟨y, hy, rfl⟩ + exact h_left x y hy + have h_right' {y x} (hy : y ∈ closure s) : y * x ∈ closure s := by + have := (AddMonoidHom.mulRight x).map_closure s ▸ mem_map_of_mem _ hy + refine closure_mono ?_ this + rintro - ⟨y, hy, rfl⟩ + exact h_right y x hy + let I : TwoSidedIdeal R := .mk' (closure s) (AddSubgroup.zero_mem _) + (AddSubgroup.add_mem _) (AddSubgroup.neg_mem _) h_left' h_right' + suffices z ∈ span s ↔ z ∈ I by simpa only [I, mem_mk', SetLike.mem_coe] + rw [mem_span_iff] + -- Suppose that for every ideal `J` with `s ⊆ J`, then `z ∈ J`. Apply this to `I` to get `z ∈ I`. + refine ⟨fun h ↦ h I fun x hx ↦ ?mem_closure_of_forall, fun hz J hJ ↦ ?mem_ideal_of_subset⟩ + case mem_closure_of_forall => simpa only [I, SetLike.mem_coe, mem_mk'] using subset_closure hx + /- Conversely, suppose that `z ∈ I` and that `J` is any ideal containing `s`. Then by the + induction principle for `AddSubgroup`, we must also have `z ∈ J`. -/ + case mem_ideal_of_subset => + simp only [I, SetLike.mem_coe, mem_mk'] at hz + induction hz using closure_induction' with + | mem x hx => exact hJ hx + | one => exact zero_mem _ + | mul x _ y _ hx hy => exact J.add_mem hx hy + | inv x _ hx => exact J.neg_mem hx + +open Pointwise Set + +lemma set_mul_subset {s : Set R} {I : TwoSidedIdeal R} (h : s ⊆ I) (t : Set R): + t * s ⊆ I := by + rintro - ⟨r, -, x, hx, rfl⟩ + exact mul_mem_left _ _ _ (h hx) + +lemma subset_mul_set {s : Set R} {I : TwoSidedIdeal R} (h : s ⊆ I) (t : Set R): + s * t ⊆ I := by + rintro - ⟨x, hx, r, -, rfl⟩ + exact mul_mem_right _ _ _ (h hx) + +lemma mem_span_iff_mem_addSubgroup_closure_nonunital {s : Set R} {z : R} : + z ∈ span s ↔ z ∈ AddSubgroup.closure (s ∪ s * univ ∪ univ * s ∪ univ * s * univ) := by + trans z ∈ span (s ∪ s * univ ∪ univ * s ∪ univ * s * univ) + · refine ⟨(span_mono (by simp only [Set.union_assoc, Set.subset_union_left]) ·), fun h ↦ ?_⟩ + refine mem_span_iff.mp h (span s) ?_ + simp only [union_subset_iff, union_assoc] + exact ⟨subset_span, subset_mul_set subset_span _, set_mul_subset subset_span _, + subset_mul_set (set_mul_subset subset_span _) _⟩ + · refine mem_span_iff_mem_addSubgroup_closure_absorbing ?_ ?_ + · rintro x y (((hy | ⟨y, hy, r, -, rfl⟩) | ⟨r, -, y, hy, rfl⟩) | + ⟨-, ⟨r', -, y, hy, rfl⟩, r, -, rfl⟩) + · exact .inl <| .inr <| ⟨x, mem_univ _, y, hy, rfl⟩ + · exact .inr <| ⟨x * y, ⟨x, mem_univ _, y, hy, rfl⟩, r, mem_univ _, mul_assoc ..⟩ + · exact .inl <| .inr <| ⟨x * r, mem_univ _, y, hy, mul_assoc ..⟩ + · refine .inr <| ⟨x * r' * y, ⟨x * r', mem_univ _, y, hy, ?_⟩, ⟨r, mem_univ _, ?_⟩⟩ + all_goals simp [mul_assoc] + · rintro y x (((hy | ⟨y, hy, r, -, rfl⟩) | ⟨r, -, y, hy, rfl⟩) | + ⟨-, ⟨r', -, y, hy, rfl⟩, r, -, rfl⟩) + · exact .inl <| .inl <| .inr ⟨y, hy, x, mem_univ _, rfl⟩ + · exact .inl <| .inl <| .inr ⟨y, hy, r * x, mem_univ _, (mul_assoc ..).symm⟩ + · exact .inr <| ⟨r * y, ⟨r, mem_univ _, y, hy, rfl⟩, x, mem_univ _, rfl⟩ + · refine .inr <| ⟨r' * y, ⟨r', mem_univ _, y, hy, rfl⟩, r * x, mem_univ _, ?_⟩ + simp [mul_assoc] + +end NonUnitalRing + +section Ring + +variable {R : Type*} [Ring R] + +open Pointwise Set in +lemma mem_span_iff_mem_addSubgroup_closure {s : Set R} {z : R} : + z ∈ span s ↔ z ∈ AddSubgroup.closure (univ * s * univ) := by + trans z ∈ span (univ * s * univ) + · refine ⟨(span_mono (fun x hx ↦ ?_) ·), fun hz ↦ ?_⟩ + · exact ⟨1 * x, ⟨1, mem_univ _, x, hx, rfl⟩, 1, mem_univ _, by simp⟩ + · exact mem_span_iff.mp hz (span s) <| subset_mul_set (set_mul_subset subset_span _) _ + · refine mem_span_iff_mem_addSubgroup_closure_absorbing ?_ ?_ + · intro x y hy + rw [mul_assoc] at hy ⊢ + obtain ⟨r, -, y, hy, rfl⟩ := hy + exact ⟨x * r, mem_univ _, y, hy, mul_assoc ..⟩ + · rintro - x ⟨y, hy, r, -, rfl⟩ + exact ⟨y, hy, r * x, mem_univ _, (mul_assoc ..).symm⟩ + +/-- Given an ideal `I`, `span I` is the smallest two-sided ideal containing `I`. -/ +def fromIdeal : Ideal R →o TwoSidedIdeal R where + toFun I := span I + monotone' _ _ := span_mono + +lemma mem_fromIdeal {I : Ideal R} {x : R} : + x ∈ fromIdeal I ↔ x ∈ span I := by simp [fromIdeal] + +/-- Every two-sided ideal is also a left ideal. -/ +def asIdeal : TwoSidedIdeal R →o Ideal R where + toFun I := + { carrier := I + add_mem' := I.add_mem + zero_mem' := I.zero_mem + smul_mem' := fun r x hx => I.mul_mem_left r x hx } + monotone' _ _ h _ h' := h h' + +@[simp] +lemma mem_asIdeal {I : TwoSidedIdeal R} {x : R} : + x ∈ asIdeal I ↔ x ∈ I := by simp [asIdeal] + +lemma gc : GaloisConnection fromIdeal (asIdeal (R := R)) := + fun I J => ⟨fun h x hx ↦ h <| mem_span_iff.2 fun _ H ↦ H hx, fun h x hx ↦ by + simp only [fromIdeal, OrderHom.coe_mk, mem_span_iff] at hx + exact hx _ h⟩ + +@[simp] +lemma coe_asIdeal {I : TwoSidedIdeal R} : (asIdeal I : Set R) = I := rfl + +/-- Every two-sided ideal is also a right ideal. -/ +def asIdealOpposite : TwoSidedIdeal R →o Ideal Rᵐᵒᵖ where + toFun I := asIdeal ⟨I.ringCon.op⟩ + monotone' I J h x h' := by + simp only [mem_asIdeal, mem_iff, RingCon.op_iff, MulOpposite.unop_zero] at h' ⊢ + exact J.rel_iff _ _ |>.2 <| h <| I.rel_iff 0 x.unop |>.1 h' + +lemma mem_asIdealOpposite {I : TwoSidedIdeal R} {x : Rᵐᵒᵖ} : + x ∈ asIdealOpposite I ↔ x.unop ∈ I := by + simpa [asIdealOpposite, asIdeal, TwoSidedIdeal.mem_iff, RingCon.op_iff] using + ⟨I.ringCon.symm, I.ringCon.symm⟩ + +end Ring + +section CommRing + +variable {R : Type*} [CommRing R] + +/-- +When the ring is commutative, two-sided ideals are exactly the same as left ideals. +-/ +def orderIsoIdeal : TwoSidedIdeal R ≃o Ideal R where + toFun := asIdeal + invFun := fromIdeal + map_rel_iff' := ⟨fun h _ hx ↦ h hx, fun h ↦ asIdeal.monotone' h⟩ + left_inv _ := SetLike.ext fun _ ↦ mem_span_iff.trans <| by aesop + right_inv J := SetLike.ext fun x ↦ mem_span_iff.trans + ⟨fun h ↦ mem_mk' _ _ _ _ _ _ _ |>.1 <| h (mk' + J J.zero_mem J.add_mem J.neg_mem (J.mul_mem_left _) (J.mul_mem_right _)) + (fun x => by simp), by aesop⟩ + +end CommRing + +end TwoSidedIdeal + +namespace Ideal +variable {R : Type*} [Ring R] + +/-- Bundle an `Ideal` that is already two-sided as a `TwoSidedIdeal`. -/ +def toTwoSided (I : Ideal R) (mul_mem_right : ∀ {x y}, x ∈ I → x * y ∈ I) : TwoSidedIdeal R := + TwoSidedIdeal.mk' I I.zero_mem I.add_mem I.neg_mem (I.smul_mem _) mul_mem_right + +@[simp] +lemma mem_toTwoSided {I : Ideal R} {h} {x : R} : + x ∈ I.toTwoSided h ↔ x ∈ I := by + simp [toTwoSided] + +@[simp] +lemma coe_toTwoSided (I : Ideal R) (h) : (I.toTwoSided h : Set R) = I := by + simp [toTwoSided] + +@[simp] +lemma toTwoSided_asIdeal (I : TwoSidedIdeal R) (h) : (TwoSidedIdeal.asIdeal I).toTwoSided h = I := + by ext; simp + +@[simp] +lemma asIdeal_toTwoSided (I : Ideal R) (h) : TwoSidedIdeal.asIdeal (I.toTwoSided h) = I := by + ext + simp + +instance : CanLift (Ideal R) (TwoSidedIdeal R) TwoSidedIdeal.asIdeal + (fun I => ∀ {x y}, x ∈ I → x * y ∈ I) where + prf I mul_mem_right := ⟨I.toTwoSided mul_mem_right, asIdeal_toTwoSided ..⟩ + +end Ideal diff --git a/Mathlib/RingTheory/UniqueFactorizationDomain.lean b/Mathlib/RingTheory/UniqueFactorizationDomain.lean index edce0ce9c8677..ab4db15117b06 100644 --- a/Mathlib/RingTheory/UniqueFactorizationDomain.lean +++ b/Mathlib/RingTheory/UniqueFactorizationDomain.lean @@ -323,8 +323,7 @@ theorem WfDvdMonoid.of_exists_prime_factors : WfDvdMonoid α := rw [dif_neg ane0] by_cases h : b = 0 · simp [h, lt_top_iff_ne_top] - · rw [dif_neg h] - erw [WithTop.coe_lt_coe] + · rw [dif_neg h, Nat.cast_lt] have cne0 : c ≠ 0 := by refine mt (fun con => ?_) h rw [b_eq, con, mul_zero] @@ -390,8 +389,8 @@ theorem MulEquiv.uniqueFactorizationMonoid (e : α ≃* β) (hα : UniqueFactori he ▸ e.prime_iff.1 (hp c hc), Units.map e.toMonoidHom u, by - erw [Multiset.prod_hom, ← map_mul e, h] - simp⟩ + rw [Multiset.prod_hom, toMonoidHom_eq_coe, Units.coe_map, MonoidHom.coe_coe, ← map_mul e, h, + apply_symm_apply]⟩ theorem MulEquiv.uniqueFactorizationMonoid_iff (e : α ≃* β) : UniqueFactorizationMonoid α ↔ UniqueFactorizationMonoid β := @@ -570,7 +569,7 @@ noncomputable def normalizedFactors (a : α) : Multiset α := if `M` has a trivial group of units. -/ @[simp] theorem factors_eq_normalizedFactors {M : Type*} [CancelCommMonoidWithZero M] - [UniqueFactorizationMonoid M] [Unique Mˣ] (x : M) : factors x = normalizedFactors x := by + [UniqueFactorizationMonoid M] [Subsingleton Mˣ] (x : M) : factors x = normalizedFactors x := by unfold normalizedFactors convert (Multiset.map_id (factors x)).symm ext p @@ -743,7 +742,7 @@ theorem dvd_of_mem_normalizedFactors {a p : α} (H : p ∈ normalizedFactors a) exact dvd_zero p · exact dvd_trans (Multiset.dvd_prod H) (Associated.dvd (normalizedFactors_prod hcases)) -theorem mem_normalizedFactors_iff [Unique αˣ] {p x : α} (hx : x ≠ 0) : +theorem mem_normalizedFactors_iff [Subsingleton αˣ] {p x : α} (hx : x ≠ 0) : p ∈ normalizedFactors x ↔ Prime p ∧ p ∣ x := by constructor · intro h @@ -759,11 +758,16 @@ theorem exists_associated_prime_pow_of_unique_normalized_factor {p r : α} have := UniqueFactorizationMonoid.normalizedFactors_prod hr rwa [Multiset.eq_replicate_of_mem fun b => h, Multiset.prod_replicate] at this -theorem normalizedFactors_prod_of_prime [Nontrivial α] [Unique αˣ] {m : Multiset α} +theorem normalizedFactors_prod_of_prime [Subsingleton αˣ] {m : Multiset α} (h : ∀ p ∈ m, Prime p) : normalizedFactors m.prod = m := by - simpa only [← Multiset.rel_eq, ← associated_eq_eq] using - prime_factors_unique prime_of_normalized_factor h - (normalizedFactors_prod (m.prod_ne_zero_of_prime h)) + cases subsingleton_or_nontrivial α + · obtain rfl : m = 0 := by + refine Multiset.eq_zero_of_forall_not_mem fun x hx ↦ ?_ + simpa [Subsingleton.elim x 0] using h x hx + simp + · simpa only [← Multiset.rel_eq, ← associated_eq_eq] using + prime_factors_unique prime_of_normalized_factor h + (normalizedFactors_prod (m.prod_ne_zero_of_prime h)) theorem mem_normalizedFactors_eq_of_associated {a b c : α} (ha : a ∈ normalizedFactors c) (hb : b ∈ normalizedFactors c) (h : Associated a b) : a = b := by @@ -1023,7 +1027,7 @@ theorem prime_pow_coprime_prod_of_coprime_insert [DecidableEq α] {s : Finset α /-- If `P` holds for units and powers of primes, and `P x ∧ P y` for coprime `x, y` implies `P (x * y)`, then `P` holds on a product of powers of distinct primes. -/ --- @[elab_as_elim] Porting note: commented out +@[elab_as_elim] theorem induction_on_prime_power {P : α → Prop} (s : Finset α) (i : α → ℕ) (is_prime : ∀ p ∈ s, Prime p) (is_coprime : ∀ᵉ (p ∈ s) (q ∈ s), p ∣ q → p = q) (h1 : ∀ {x}, IsUnit x → P x) (hpr : ∀ {p} (i : ℕ), Prime p → P (p ^ i)) @@ -1062,7 +1066,6 @@ theorem induction_on_coprime {P : α → Prop} (a : α) (h0 : P 0) (h1 : ∀ {x} /-- If `f` maps `p ^ i` to `(f p) ^ i` for primes `p`, and `f` is multiplicative on coprime elements, then `f` is multiplicative on all products of primes. -/ --- @[elab_as_elim] Porting note: commented out theorem multiplicative_prime_power {f : α → β} (s : Finset α) (i j : α → ℕ) (is_prime : ∀ p ∈ s, Prime p) (is_coprime : ∀ᵉ (p ∈ s) (q ∈ s), p ∣ q → p = q) (h1 : ∀ {x y}, IsUnit y → f (x * y) = f x * f y) diff --git a/Mathlib/RingTheory/Unramified/Basic.lean b/Mathlib/RingTheory/Unramified/Basic.lean index af45772e8e3eb..baf22e56e7160 100644 --- a/Mathlib/RingTheory/Unramified/Basic.lean +++ b/Mathlib/RingTheory/Unramified/Basic.lean @@ -104,23 +104,12 @@ theorem lift_unique' [FormallyUnramified R A] {C : Type u} [CommRing C] (g₁ g₂ : A →ₐ[R] B) (h : f.comp g₁ = f.comp g₂) : g₁ = g₂ := FormallyUnramified.ext' _ hf g₁ g₂ (AlgHom.congr_fun h) -end - -section OfEquiv - -variable {R : Type u} [CommSemiring R] -variable {A B : Type u} [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] - -theorem of_equiv [FormallyUnramified R A] (e : A ≃ₐ[R] B) : - FormallyUnramified R B := by +instance : FormallyUnramified R R := by constructor - intro C _ _ I hI f₁ f₂ e' - rw [← f₁.comp_id, ← f₂.comp_id, ← e.comp_symm, ← AlgHom.comp_assoc, ← AlgHom.comp_assoc] - congr 1 - refine FormallyUnramified.comp_injective I hI ?_ - rw [← AlgHom.comp_assoc, e', AlgHom.comp_assoc] + intros B _ _ _ _ f₁ f₂ _ + exact Subsingleton.elim _ _ -end OfEquiv +end section Comp @@ -155,6 +144,33 @@ theorem of_comp [FormallyUnramified R B] : FormallyUnramified A B := by end Comp +section of_surjective + +variable {R : Type u} [CommSemiring R] +variable {A B : Type u} [Semiring A] [Algebra R A] [Semiring B] [Algebra R B] + +/-- This holds in general for epimorphisms. -/ +theorem of_surjective [FormallyUnramified R A] (f : A →ₐ[R] B) (H : Function.Surjective f) : + FormallyUnramified R B := by + constructor + intro Q _ _ I hI f₁ f₂ e + ext x + obtain ⟨x, rfl⟩ := H x + rw [← AlgHom.comp_apply, ← AlgHom.comp_apply] + congr 1 + apply FormallyUnramified.comp_injective I hI + ext x; exact DFunLike.congr_fun e (f x) + +instance quotient {A} [CommRing A] [Algebra R A] [FormallyUnramified R A] (I : Ideal A) : + FormallyUnramified R (A ⧸ I) := + FormallyUnramified.of_surjective (IsScalarTower.toAlgHom _ _ _) Ideal.Quotient.mk_surjective + +theorem of_equiv [FormallyUnramified R A] (e : A ≃ₐ[R] B) : + FormallyUnramified R B := + of_surjective e.toAlgHom e.surjective + +end of_surjective + section BaseChange open scoped TensorProduct diff --git a/Mathlib/RingTheory/Unramified/Field.lean b/Mathlib/RingTheory/Unramified/Field.lean new file mode 100644 index 0000000000000..3a0152d738c1c --- /dev/null +++ b/Mathlib/RingTheory/Unramified/Field.lean @@ -0,0 +1,213 @@ +/- +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.FieldTheory.PurelyInseparable +import Mathlib.RingTheory.Artinian +import Mathlib.RingTheory.LocalProperties.Basic +import Mathlib.Algebra.Polynomial.Taylor +import Mathlib.RingTheory.Unramified.Finite + +/-! +# Unramified algebras over fields + +## Main results + +Let `K` be a field, `A` be a `K`-algebra and `L` be a field extension of `K`. + +- `Algebra.FormallyUnramified.bijective_of_isAlgClosed_of_localRing`: + If `A` is `K`-unramified and `K` is alg-closed, then `K = A`. +- `Algebra.FormallyUnramified.isReduced_of_field`: + If `A` is `K`-unramified then `A` is reduced. +- `Algebra.FormallyUnramified.iff_isSeparable`: + `L` is unramified over `K` iff `L` is separable over `K`. + +## References + +- [B. Iversen, *Generic Local Structure of the Morphisms in Commutative Algebra*][iversen] + +-/ + +universe u + +variable (K A L : Type u) [Field K] [Field L] [CommRing A] [Algebra K A] [Algebra K L] + +open Algebra Polynomial + +open scoped TensorProduct + +namespace Algebra.FormallyUnramified + +theorem of_isSeparable [Algebra.IsSeparable K L] : FormallyUnramified K L := by + constructor + intros B _ _ I hI f₁ f₂ e + ext x + have : f₁ x - f₂ x ∈ I := by + simpa [Ideal.Quotient.mk_eq_mk_iff_sub_mem] using AlgHom.congr_fun e x + have := Polynomial.eval_add_of_sq_eq_zero ((minpoly K x).map (algebraMap K B)) (f₂ x) + (f₁ x - f₂ x) (show (f₁ x - f₂ x) ^ 2 ∈ ⊥ from hI ▸ Ideal.pow_mem_pow this 2) + simp only [add_sub_cancel, eval_map_algebraMap, aeval_algHom_apply, minpoly.aeval, map_zero, + derivative_map, zero_add] at this + rwa [eq_comm, ((isUnit_iff_ne_zero.mpr + ((Algebra.IsSeparable.isSeparable K x).aeval_derivative_ne_zero + (minpoly.aeval K x))).map f₂).mul_right_eq_zero, sub_eq_zero] at this + +variable [FormallyUnramified K A] [EssFiniteType K A] +variable [FormallyUnramified K L] [EssFiniteType K L] + +theorem bijective_of_isAlgClosed_of_localRing + [IsAlgClosed K] [LocalRing A] : + Function.Bijective (algebraMap K A) := by + have := finite_of_free (R := K) (S := A) + have : IsArtinianRing A := isArtinian_of_tower K inferInstance + have hA : IsNilpotent (LocalRing.maximalIdeal A) := by + rw [← LocalRing.jacobson_eq_maximalIdeal ⊥] + · exact IsArtinianRing.isNilpotent_jacobson_bot + · exact bot_ne_top + have : Function.Bijective (Algebra.ofId K (A ⧸ LocalRing.maximalIdeal A)) := + ⟨RingHom.injective _, IsAlgClosed.algebraMap_surjective_of_isIntegral⟩ + let e : K ≃ₐ[K] A ⧸ LocalRing.maximalIdeal A := { + __ := Algebra.ofId K (A ⧸ LocalRing.maximalIdeal A) + __ := Equiv.ofBijective _ this } + let e' : A ⊗[K] (A ⧸ LocalRing.maximalIdeal A) ≃ₐ[A] A := + (Algebra.TensorProduct.congr AlgEquiv.refl e.symm).trans (Algebra.TensorProduct.rid K A A) + let f : A ⧸ LocalRing.maximalIdeal A →ₗ[A] A := e'.toLinearMap.comp (sec K A _) + have hf : (Algebra.ofId _ _).toLinearMap ∘ₗ f = LinearMap.id := by + dsimp [f] + rw [← LinearMap.comp_assoc, ← comp_sec K A] + congr 1 + apply LinearMap.restrictScalars_injective K + apply _root_.TensorProduct.ext' + intros r s + obtain ⟨s, rfl⟩ := e.surjective s + suffices s • (Ideal.Quotient.mk (LocalRing.maximalIdeal A)) r = r • e s by + simpa [ofId, e'] + simp [Algebra.smul_def, e, ofId, mul_comm] + have hf₁ : f 1 • (1 : A ⧸ LocalRing.maximalIdeal A) = 1 := by + rw [← algebraMap_eq_smul_one] + exact LinearMap.congr_fun hf 1 + have hf₂ : 1 - f 1 ∈ LocalRing.maximalIdeal A := by + rw [← Ideal.Quotient.eq_zero_iff_mem, map_sub, map_one, ← Ideal.Quotient.algebraMap_eq, + algebraMap_eq_smul_one, hf₁, sub_self] + have hf₃ : IsIdempotentElem (1 - f 1) := by + apply IsIdempotentElem.one_sub + rw [IsIdempotentElem, ← smul_eq_mul, ← map_smul, hf₁] + have hf₄ : f 1 = 1 := by + obtain ⟨n, hn⟩ := hA + have : (1 - f 1) ^ n = 0 := by + rw [← Ideal.mem_bot, ← Ideal.zero_eq_bot, ← hn] + exact Ideal.pow_mem_pow hf₂ n + rw [eq_comm, ← sub_eq_zero, ← hf₃.pow_succ_eq n, pow_succ, this, zero_mul] + refine Equiv.bijective ⟨algebraMap K A, ⇑e.symm ∘ ⇑(algebraMap A _), fun x ↦ by simp, fun x ↦ ?_⟩ + have : ⇑(algebraMap K A) = ⇑f ∘ ⇑e := by + ext k + conv_rhs => rw [← mul_one k, ← smul_eq_mul, Function.comp_apply, map_smul, + LinearMap.map_smul_of_tower, map_one, hf₄, ← algebraMap_eq_smul_one] + rw [this] + simp only [Function.comp_apply, AlgEquiv.apply_symm_apply, algebraMap_eq_smul_one, + map_smul, hf₄, smul_eq_mul, mul_one] + +theorem isField_of_isAlgClosed_of_localRing + [IsAlgClosed K] [LocalRing A] : IsField A := by + rw [LocalRing.isField_iff_maximalIdeal_eq, eq_bot_iff] + intro x hx + obtain ⟨x, rfl⟩ := (bijective_of_isAlgClosed_of_localRing K A).surjective x + show _ = 0 + rw [← (algebraMap K A).map_zero] + by_contra hx' + exact hx ((isUnit_iff_ne_zero.mpr + (fun e ↦ hx' ((algebraMap K A).congr_arg e))).map (algebraMap K A)) + +include K in +theorem isReduced_of_field : + IsReduced A := by + constructor + intro x hx + let f := (Algebra.TensorProduct.includeRight (R := K) (A := AlgebraicClosure K) (B := A)) + have : Function.Injective f := by + have : ⇑f = (LinearMap.rTensor A (Algebra.ofId K (AlgebraicClosure K)).toLinearMap).comp + (Algebra.TensorProduct.lid K A).symm.toLinearMap := by + ext x; simp [f] + rw [this] + suffices Function.Injective + (LinearMap.rTensor A (Algebra.ofId K (AlgebraicClosure K)).toLinearMap) by + exact this.comp (Algebra.TensorProduct.lid K A).symm.injective + apply Module.Flat.rTensor_preserves_injective_linearMap + exact (algebraMap K _).injective + apply this + rw [map_zero] + apply eq_zero_of_localization + intro M hM + have hy := (hx.map f).map (algebraMap _ (Localization.AtPrime M)) + generalize algebraMap _ (Localization.AtPrime M) (f x) = y at * + have := EssFiniteType.of_isLocalization (Localization.AtPrime M) M.primeCompl + have := of_isLocalization (Rₘ := Localization.AtPrime M) M.primeCompl + have := EssFiniteType.comp (AlgebraicClosure K) (AlgebraicClosure K ⊗[K] A) + (Localization.AtPrime M) + have := comp (AlgebraicClosure K) (AlgebraicClosure K ⊗[K] A) + (Localization.AtPrime M) + letI := (isField_of_isAlgClosed_of_localRing (AlgebraicClosure K) + (A := Localization.AtPrime M)).toField + exact hy.eq_zero + +theorem range_eq_top_of_isPurelyInseparable + [IsPurelyInseparable K L] : (algebraMap K L).range = ⊤ := by + classical + have : Nontrivial (L ⊗[K] L) := by + rw [← not_subsingleton_iff_nontrivial, ← rank_zero_iff (R := K), rank_tensorProduct', + mul_eq_zero, or_self, rank_zero_iff, not_subsingleton_iff_nontrivial] + infer_instance + rw [← top_le_iff] + intro x _ + obtain ⟨n, hn⟩ := IsPurelyInseparable.pow_mem K (ringExpChar K) x + have : ExpChar (L ⊗[K] L) (ringExpChar K) := by + refine expChar_of_injective_ringHom (algebraMap K _).injective (ringExpChar K) + have : (1 ⊗ₜ x - x ⊗ₜ 1 : L ⊗[K] L) ^ (ringExpChar K) ^ n = 0 := by + rw [sub_pow_expChar_pow, TensorProduct.tmul_pow, one_pow, TensorProduct.tmul_pow, one_pow] + obtain ⟨r, hr⟩ := hn + rw [← hr, algebraMap_eq_smul_one, TensorProduct.smul_tmul, sub_self] + have H : (1 ⊗ₜ x : L ⊗[K] L) = x ⊗ₜ 1 := by + have inst : IsReduced (L ⊗[K] L) := isReduced_of_field L _ + exact sub_eq_zero.mp (IsNilpotent.eq_zero ⟨_, this⟩) + by_cases h' : LinearIndependent K ![1, x] + · have h := h'.coe_range + let S := h.extend (Set.subset_univ _) + let a : S := ⟨1, h.subset_extend _ (by simp)⟩; have ha : Basis.extend h a = 1 := by simp + let b : S := ⟨x, h.subset_extend _ (by simp)⟩; have hb : Basis.extend h b = x := by simp + by_cases e : a = b + · obtain rfl : 1 = x := congr_arg Subtype.val e + exact ⟨1, map_one _⟩ + have := DFunLike.congr_fun + (DFunLike.congr_arg ((Basis.extend h).tensorProduct (Basis.extend h)).repr H) (a, b) + simp only [Basis.tensorProduct_repr_tmul_apply, ← ha, ← hb, Basis.repr_self, smul_eq_mul, + Finsupp.single_apply, e, Ne.symm e, ↓reduceIte, mul_one, mul_zero, one_ne_zero] at this + · rw [LinearIndependent.pair_iff] at h' + simp only [not_forall, not_and, exists_prop] at h' + obtain ⟨a, b, e, hab⟩ := h' + have : IsUnit b := by + rw [isUnit_iff_ne_zero] + rintro rfl + rw [zero_smul, ← algebraMap_eq_smul_one, add_zero, + (injective_iff_map_eq_zero' _).mp (algebraMap K L).injective] at e + cases hab e rfl + use (-this.unit⁻¹ * a) + rw [map_mul, ← Algebra.smul_def, algebraMap_eq_smul_one, eq_neg_iff_add_eq_zero.mpr e, + smul_neg, neg_smul, neg_neg, smul_smul, this.val_inv_mul, one_smul] + +theorem isSeparable : Algebra.IsSeparable K L := by + have := finite_of_free (R := K) (S := L) + rw [← separableClosure.eq_top_iff] + have := of_comp K (separableClosure K L) L + have := EssFiniteType.of_comp K (separableClosure K L) L + have := separableClosure.isPurelyInseparable K L + ext + show _ ↔ _ ∈ (⊤ : Subring _) + rw [← range_eq_top_of_isPurelyInseparable (separableClosure K L) L] + simp + +theorem iff_isSeparable (L) [Field L] [Algebra K L] [EssFiniteType K L] : + FormallyUnramified K L ↔ Algebra.IsSeparable K L := + ⟨fun _ ↦ isSeparable K L, fun _ ↦ of_isSeparable K L⟩ + +end Algebra.FormallyUnramified diff --git a/Mathlib/RingTheory/Unramified/Pi.lean b/Mathlib/RingTheory/Unramified/Pi.lean new file mode 100644 index 0000000000000..dc1d2ec8c816b --- /dev/null +++ b/Mathlib/RingTheory/Unramified/Pi.lean @@ -0,0 +1,98 @@ +/- +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.RingTheory.Unramified.Basic + +/-! + +# Formal-unramification of finite products of rings + +## Main result + +- `Algebra.FormallyUnramified.pi_iff`: If `I` is finite, `Π i : I, A i` is `R`-formally-smooth + if and only if each `A i` is `R`-formally-smooth. + +-/ + +namespace Algebra.FormallyUnramified + +universe u v + +variable {R : Type max u v} {I : Type v} [Finite I] (f : I → Type max u v) +variable [CommRing R] [∀ i, CommRing (f i)] [∀ i, Algebra R (f i)] + +theorem pi_iff : + FormallyUnramified R (∀ i, f i) ↔ ∀ i, FormallyUnramified R (f i) := by + classical + cases nonempty_fintype I + constructor + · intro _ i + exact FormallyUnramified.of_surjective (Pi.evalAlgHom R f i) (Function.surjective_eval i) + · intro H + constructor + intros B _ _ J hJ f₁ f₂ e + ext g + rw [← Finset.univ_sum_single g, map_sum, map_sum] + refine Finset.sum_congr rfl ?_ + rintro x - + have hf : ∀ x, f₁ x - f₂ x ∈ J := by + intro g + rw [← Ideal.Quotient.eq_zero_iff_mem, map_sub, sub_eq_zero] + exact AlgHom.congr_fun e g + let e : ∀ i, f i := Pi.single x 1 + have he : IsIdempotentElem e := by simp [IsIdempotentElem, e, ← Pi.single_mul] + have h₁ : (f₁ e) * (1 - f₂ e) = 0 := by + rw [← Ideal.mem_bot, ← hJ, ← ((he.map f₁).mul (he.map f₂).one_sub).eq, ← pow_two] + apply Ideal.pow_mem_pow + convert Ideal.mul_mem_left _ (f₁ e) (hf e) using 1 + rw [mul_sub, mul_sub, mul_one, (he.map f₁).eq] + have h₂ : (f₂ e) * (1 - f₁ e) = 0 := by + rw [← Ideal.mem_bot, ← hJ, ← ((he.map f₂).mul (he.map f₁).one_sub).eq, ← pow_two] + apply Ideal.pow_mem_pow + convert Ideal.mul_mem_left _ (-f₂ e) (hf e) using 1 + rw [neg_mul, mul_sub, mul_sub, mul_one, neg_sub, (he.map f₂).eq] + have H : f₁ e = f₂ e := by + trans f₁ e * f₂ e + · rw [← sub_eq_zero, ← h₁, mul_sub, mul_one] + · rw [eq_comm, ← sub_eq_zero, ← h₂, mul_sub, mul_one, mul_comm] + let J' := Ideal.span {1 - f₁ e} + let f₁' : f x →ₐ[R] B ⧸ J' := by + apply AlgHom.ofLinearMap + (((Ideal.Quotient.mkₐ R J').comp f₁).toLinearMap.comp (LinearMap.single _ _ x)) + · simp only [AlgHom.comp_toLinearMap, LinearMap.coe_comp, LinearMap.coe_single, + Function.comp_apply, AlgHom.toLinearMap_apply, Ideal.Quotient.mkₐ_eq_mk] + rw [eq_comm, ← sub_eq_zero, ← (Ideal.Quotient.mk J').map_one, ← map_sub, + Ideal.Quotient.eq_zero_iff_mem, Ideal.mem_span_singleton] + · intros r s; simp [Pi.single_mul] + let f₂' : f x →ₐ[R] B ⧸ J' := by + apply AlgHom.ofLinearMap + (((Ideal.Quotient.mkₐ R J').comp f₂).toLinearMap.comp (LinearMap.single _ _ x)) + · simp only [AlgHom.comp_toLinearMap, LinearMap.coe_comp, LinearMap.coe_single, + Function.comp_apply, AlgHom.toLinearMap_apply, Ideal.Quotient.mkₐ_eq_mk] + rw [eq_comm, ← sub_eq_zero, ← (Ideal.Quotient.mk J').map_one, ← map_sub, + Ideal.Quotient.eq_zero_iff_mem, Ideal.mem_span_singleton, H] + · intros r s; simp [Pi.single_mul] + suffices f₁' = f₂' by + have := AlgHom.congr_fun this (g x) + simp only [AlgHom.comp_toLinearMap, AlgHom.ofLinearMap_apply, LinearMap.coe_comp, + LinearMap.coe_single, Function.comp_apply, AlgHom.toLinearMap_apply, ← map_sub, + Ideal.Quotient.mkₐ_eq_mk, ← sub_eq_zero (b := Ideal.Quotient.mk J' _), sub_zero, f₁', f₂', + Ideal.Quotient.eq_zero_iff_mem, Ideal.mem_span_singleton, J'] at this + obtain ⟨c, hc⟩ := this + apply_fun (f₁ e * ·) at hc + rwa [← mul_assoc, mul_sub, mul_sub, mul_one, (he.map f₁).eq, sub_self, zero_mul, + ← map_mul, H, ← map_mul, ← Pi.single_mul, one_mul, sub_eq_zero] at hc + apply FormallyUnramified.comp_injective (I := J.map (algebraMap _ _)) + · rw [← Ideal.map_pow, hJ, Ideal.map_bot] + · ext r + rw [← sub_eq_zero] + simp only [Ideal.Quotient.algebraMap_eq, AlgHom.coe_comp, Ideal.Quotient.mkₐ_eq_mk, + Function.comp_apply, ← map_sub, Ideal.Quotient.eq_zero_iff_mem, f₁', f₂', + AlgHom.comp_toLinearMap, AlgHom.ofLinearMap_apply, LinearMap.coe_comp, + LinearMap.coe_single, Function.comp_apply, AlgHom.toLinearMap_apply, + Ideal.Quotient.mkₐ_eq_mk] + exact Ideal.mem_map_of_mem (Ideal.Quotient.mk J') (hf (Pi.single x r)) + +end Algebra.FormallyUnramified diff --git a/Mathlib/RingTheory/Valuation/Basic.lean b/Mathlib/RingTheory/Valuation/Basic.lean index 77bb5ceacdaaf..eec13a2b17f5f 100644 --- a/Mathlib/RingTheory/Valuation/Basic.lean +++ b/Mathlib/RingTheory/Valuation/Basic.lean @@ -207,6 +207,9 @@ theorem zero_iff [Nontrivial Γ₀] (v : Valuation K Γ₀) {x : K} : v x = 0 theorem ne_zero_iff [Nontrivial Γ₀] (v : Valuation K Γ₀) {x : K} : v x ≠ 0 ↔ x ≠ 0 := map_ne_zero v +lemma pos_iff [Nontrivial Γ₀] (v : Valuation K Γ₀) {x : K} : 0 < v x ↔ x ≠ 0 := by + rw [zero_lt_iff, ne_zero_iff] + theorem unit_map_eq (u : Rˣ) : (Units.map (v : R →* Γ₀) u : Γ₀) = v u := rfl @@ -322,17 +325,16 @@ theorem map_one_sub_of_lt (h : v x < 1) : v (1 - x) = 1 := by simpa only [v.map_one, v.map_neg] using v.map_add_eq_of_lt_left h theorem one_lt_val_iff (v : Valuation K Γ₀) {x : K} (h : x ≠ 0) : 1 < v x ↔ v x⁻¹ < 1 := by - simpa using (inv_lt_inv₀ (v.ne_zero_iff.2 h) one_ne_zero).symm + simp [inv_lt_one₀ (v.pos_iff.2 h)] theorem one_le_val_iff (v : Valuation K Γ₀) {x : K} (h : x ≠ 0) : 1 ≤ v x ↔ v x⁻¹ ≤ 1 := by - convert (one_lt_val_iff v (inv_ne_zero h)).symm.not <;> - push_neg <;> simp only [inv_inv] + simp [inv_le_one₀ (v.pos_iff.2 h)] theorem val_lt_one_iff (v : Valuation K Γ₀) {x : K} (h : x ≠ 0) : v x < 1 ↔ 1 < v x⁻¹ := by - simpa only [inv_inv] using (one_lt_val_iff v (inv_ne_zero h)).symm + simp [one_lt_inv₀ (v.pos_iff.2 h)] theorem val_le_one_iff (v : Valuation K Γ₀) {x : K} (h : x ≠ 0) : v x ≤ 1 ↔ 1 ≤ v x⁻¹ := by - simpa [inv_inv] using (one_le_val_iff v (inv_ne_zero h)).symm + simp [one_le_inv₀ (v.pos_iff.2 h)] theorem val_eq_one_iff (v : Valuation K Γ₀) {x : K} : v x = 1 ↔ v x⁻¹ = 1 := by by_cases h : x = 0 @@ -421,7 +423,7 @@ theorem isEquiv_iff_val_lt_val [LinearOrderedCommGroupWithZero Γ₀] alias ⟨IsEquiv.lt_iff_lt, _⟩ := isEquiv_iff_val_lt_val theorem isEquiv_of_val_le_one [LinearOrderedCommGroupWithZero Γ₀] - [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} (h : ∀ {x : K}, v x ≤ 1 ↔ v' x ≤ 1) : v.IsEquiv v' := by intro x y obtain rfl | hy := eq_or_ne y 0 @@ -430,12 +432,14 @@ theorem isEquiv_of_val_le_one [LinearOrderedCommGroupWithZero Γ₀] rwa [zero_lt_iff, ne_zero_iff] theorem isEquiv_iff_val_le_one [LinearOrderedCommGroupWithZero Γ₀] - [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} : v.IsEquiv v' ↔ ∀ {x : K}, v x ≤ 1 ↔ v' x ≤ 1 := - ⟨fun h x => by simpa using h x 1, isEquiv_of_val_le_one _ _⟩ + ⟨fun h x => by simpa using h x 1, isEquiv_of_val_le_one⟩ + +alias ⟨IsEquiv.le_one_iff_le_one, _⟩ := isEquiv_iff_val_le_one theorem isEquiv_iff_val_eq_one [LinearOrderedCommGroupWithZero Γ₀] - [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} : v.IsEquiv v' ↔ ∀ {x : K}, v x = 1 ↔ v' x = 1 := by constructor · intro h x @@ -469,13 +473,15 @@ theorem isEquiv_iff_val_eq_one [LinearOrderedCommGroupWithZero Γ₀] · rw [← h] at hx' exact le_of_eq hx' +alias ⟨IsEquiv.eq_one_iff_eq_one, _⟩ := isEquiv_iff_val_eq_one + theorem isEquiv_iff_val_lt_one [LinearOrderedCommGroupWithZero Γ₀] - [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} : v.IsEquiv v' ↔ ∀ {x : K}, v x < 1 ↔ v' x < 1 := by constructor · intro h x simp only [lt_iff_le_and_ne, - and_congr ((isEquiv_iff_val_le_one _ _).1 h) ((isEquiv_iff_val_eq_one _ _).1 h).not] + and_congr h.le_one_iff_le_one h.eq_one_iff_eq_one.not] · rw [isEquiv_iff_val_eq_one] intro h x by_cases hx : x = 0 @@ -496,20 +502,29 @@ theorem isEquiv_iff_val_lt_one [LinearOrderedCommGroupWithZero Γ₀] rw [← inv_one, ← inv_eq_iff_eq_inv, ← map_inv₀] at hh exact hh.not_lt (h.1 ((one_lt_val_iff v hx).1 h_2)) +alias ⟨IsEquiv.lt_one_iff_lt_one, _⟩ := isEquiv_iff_val_lt_one + theorem isEquiv_iff_val_sub_one_lt_one [LinearOrderedCommGroupWithZero Γ₀] - [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : + [LinearOrderedCommGroupWithZero Γ'₀] {v : Valuation K Γ₀} {v' : Valuation K Γ'₀} : v.IsEquiv v' ↔ ∀ {x : K}, v (x - 1) < 1 ↔ v' (x - 1) < 1 := by rw [isEquiv_iff_val_lt_one] exact (Equiv.subRight 1).surjective.forall +alias ⟨IsEquiv.val_sub_one_lt_one_iff, _⟩ := isEquiv_iff_val_sub_one_lt_one + theorem isEquiv_tfae [LinearOrderedCommGroupWithZero Γ₀] [LinearOrderedCommGroupWithZero Γ'₀] (v : Valuation K Γ₀) (v' : Valuation K Γ'₀) : - [v.IsEquiv v', ∀ {x}, v x ≤ 1 ↔ v' x ≤ 1, ∀ {x}, v x = 1 ↔ v' x = 1, ∀ {x}, v x < 1 ↔ v' x < 1, - ∀ {x}, v (x - 1) < 1 ↔ v' (x - 1) < 1].TFAE := by - tfae_have 1 ↔ 2 := isEquiv_iff_val_le_one .. - tfae_have 1 ↔ 3 := isEquiv_iff_val_eq_one .. - tfae_have 1 ↔ 4 := isEquiv_iff_val_lt_one .. - tfae_have 1 ↔ 5 := isEquiv_iff_val_sub_one_lt_one .. + [ v.IsEquiv v', + ∀ {x y}, v x < v y ↔ v' x < v' y, + ∀ {x}, v x ≤ 1 ↔ v' x ≤ 1, + ∀ {x}, v x = 1 ↔ v' x = 1, + ∀ {x}, v x < 1 ↔ v' x < 1, + ∀ {x}, v (x - 1) < 1 ↔ v' (x - 1) < 1 ].TFAE := by + tfae_have 1 ↔ 2; · apply isEquiv_iff_val_lt_val + tfae_have 1 ↔ 3; · apply isEquiv_iff_val_le_one + tfae_have 1 ↔ 4; · apply isEquiv_iff_val_eq_one + tfae_have 1 ↔ 5; · apply isEquiv_iff_val_lt_one + tfae_have 1 ↔ 6; · apply isEquiv_iff_val_sub_one_lt_one tfae_finish end diff --git a/Mathlib/RingTheory/Valuation/Integral.lean b/Mathlib/RingTheory/Valuation/Integral.lean index 35bd2ff83d00d..c8e1a11e3d970 100644 --- a/Mathlib/RingTheory/Valuation/Integral.lean +++ b/Mathlib/RingTheory/Valuation/Integral.lean @@ -38,7 +38,7 @@ theorem mem_of_integral {x : R} (hx : IsIntegral O x) : x ∈ v.integer := one_mul (v x ^ p.natDegree)] cases' (hv.2 <| p.coeff i).lt_or_eq with hvpi hvpi · exact mul_lt_mul₀ hvpi (pow_lt_pow_right₀ hvx <| Finset.mem_range.1 hi) - · erw [hvpi]; rw [one_mul, one_mul]; exact pow_lt_pow_right₀ hvx (Finset.mem_range.1 hi) + · rw [hvpi, one_mul, one_mul]; exact pow_lt_pow_right₀ hvx (Finset.mem_range.1 hi) protected theorem integralClosure : integralClosure O R = ⊥ := bot_unique fun _ hr => diff --git a/Mathlib/RingTheory/Valuation/Minpoly.lean b/Mathlib/RingTheory/Valuation/Minpoly.lean index 3448962da4e70..00094cc933c86 100644 --- a/Mathlib/RingTheory/Valuation/Minpoly.lean +++ b/Mathlib/RingTheory/Valuation/Minpoly.lean @@ -21,7 +21,7 @@ Let `K` be a field with a valuation `v` and let `L` be a field extension of `K`. is helpful for defining the valuation on `L` inducing `v`. -/ -open FiniteDimensional minpoly Polynomial +open Module minpoly Polynomial variable {K : Type*} [Field K] {Γ₀ : Type*} [LinearOrderedCommGroupWithZero Γ₀] (v : Valuation K Γ₀) (L : Type*) [Field L] [Algebra K L] diff --git a/Mathlib/RingTheory/Valuation/ValExtension.lean b/Mathlib/RingTheory/Valuation/ValExtension.lean index 888369fc04bb9..566aa0f741a77 100644 --- a/Mathlib/RingTheory/Valuation/ValExtension.lean +++ b/Mathlib/RingTheory/Valuation/ValExtension.lean @@ -4,8 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jiedong Jiang, Bichang Lei -/ import Mathlib.RingTheory.Valuation.Integers -import Mathlib.RingTheory.LocalRing.RingHom.Basic -import Mathlib.RingTheory.LocalRing.RingHom.Defs +import Mathlib.Algebra.Group.Units.Hom /-! # Extension of Valuation @@ -53,7 +52,7 @@ variable {R A ΓR ΓA : Type*} [CommRing R] [Ring A] /-- The class `IsValExtension R A` states that the valuation of `A` is an extension of the valuation -on `R`. More precisely, the valuation on `R` is equivlent to the comap of the valuation on `A`. +on `R`. More precisely, the valuation on `R` is equivalent to the comap of the valuation on `A`. -/ class IsValExtension : Prop where /-- The valuation on `R` is equivalent to the comap of the valuation on `A` -/ diff --git a/Mathlib/RingTheory/Valuation/ValuationRing.lean b/Mathlib/RingTheory/Valuation/ValuationRing.lean index 864d73e5b39e6..e95d7d322ff0d 100644 --- a/Mathlib/RingTheory/Valuation/ValuationRing.lean +++ b/Mathlib/RingTheory/Valuation/ValuationRing.lean @@ -335,8 +335,8 @@ instance (priority := 100) [ValuationRing R] : IsBezout R := by intro x y rw [Ideal.span_insert] rcases le_total (Ideal.span {x} : Ideal R) (Ideal.span {y}) with h | h - · erw [sup_eq_right.mpr h]; exact ⟨⟨_, rfl⟩⟩ - · erw [sup_eq_left.mpr h]; exact ⟨⟨_, rfl⟩⟩ + · rw [sup_eq_right.mpr h]; exact ⟨⟨_, rfl⟩⟩ + · rw [sup_eq_left.mpr h]; exact ⟨⟨_, rfl⟩⟩ instance (priority := 100) [LocalRing R] [IsBezout R] : ValuationRing R := by classical diff --git a/Mathlib/RingTheory/Valuation/ValuationSubring.lean b/Mathlib/RingTheory/Valuation/ValuationSubring.lean index d3e74258289fb..a62a8375a1d0a 100644 --- a/Mathlib/RingTheory/Valuation/ValuationSubring.lean +++ b/Mathlib/RingTheory/Valuation/ValuationSubring.lean @@ -300,9 +300,8 @@ theorem ofPrime_idealOfLE (R S : ValuationSubring K) (h : R ≤ S) : · rintro ⟨a, r, hr, rfl⟩; apply mul_mem; · exact h a.2 · rw [← valuation_le_one_iff, map_inv₀, ← inv_one, inv_le_inv₀] · exact not_lt.1 ((not_iff_not.2 <| valuation_lt_one_iff S _).1 hr) - · intro hh; erw [Valuation.zero_iff, Subring.coe_eq_zero_iff] at hh - apply hr; rw [hh]; apply Ideal.zero_mem (R.idealOfLE S h) - · exact one_ne_zero + · simpa [Valuation.pos_iff] using fun hr₀ ↦ hr₀ ▸ hr <| Ideal.zero_mem (R.idealOfLE S h) + · exact zero_lt_one · intro hx; by_cases hr : x ∈ R; · exact R.le_ofPrime _ hr have : x ≠ 0 := fun h => hr (by rw [h]; exact R.zero_mem) replace hr := (R.mem_or_inv_mem x).resolve_left hr @@ -530,7 +529,7 @@ theorem mem_nonunits_iff_exists_mem_maximalIdeal {a : K} : theorem image_maximalIdeal : ((↑) : A → K) '' LocalRing.maximalIdeal A = A.nonunits := by ext a simp only [Set.mem_image, SetLike.mem_coe, mem_nonunits_iff_exists_mem_maximalIdeal] - erw [Subtype.exists] + rw [Subtype.exists] simp_rw [exists_and_right, exists_eq_right] end nonunits @@ -788,6 +787,6 @@ variable {Γ : Type*} [LinearOrderedCommGroupWithZero Γ] (v : Valuation K Γ) ( -- @[simp] -- Porting note: not in simpNF theorem mem_unitGroup_iff : x ∈ v.valuationSubring.unitGroup ↔ v x = 1 := - (Valuation.isEquiv_iff_val_eq_one _ _).mp (Valuation.isEquiv_valuation_valuationSubring _).symm + IsEquiv.eq_one_iff_eq_one (Valuation.isEquiv_valuation_valuationSubring _).symm end Valuation diff --git a/Mathlib/RingTheory/WittVector/Basic.lean b/Mathlib/RingTheory/WittVector/Basic.lean index 5630d6a00254e..e2c5bfed3057c 100644 --- a/Mathlib/RingTheory/WittVector/Basic.lean +++ b/Mathlib/RingTheory/WittVector/Basic.lean @@ -49,7 +49,7 @@ noncomputable section open MvPolynomial Function -variable {p : ℕ} {R S T : Type*} [CommRing R] [CommRing S] [CommRing T] +variable {p : ℕ} {R S : Type*} [CommRing R] [CommRing S] variable {α : Type*} {β : Type*} local notation "𝕎" => WittVector p diff --git a/Mathlib/RingTheory/WittVector/Frobenius.lean b/Mathlib/RingTheory/WittVector/Frobenius.lean index 0492664ca9471..3a15c88d7c9d5 100644 --- a/Mathlib/RingTheory/WittVector/Frobenius.lean +++ b/Mathlib/RingTheory/WittVector/Frobenius.lean @@ -3,11 +3,11 @@ 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.Algebra.ZMod import Mathlib.Data.Nat.Multiplicity -import Mathlib.Data.ZMod.Algebra +import Mathlib.FieldTheory.Perfect import Mathlib.RingTheory.WittVector.Basic import Mathlib.RingTheory.WittVector.IsPoly -import Mathlib.FieldTheory.Perfect /-! ## The Frobenius operator @@ -48,7 +48,7 @@ and bundle it into `WittVector.frobenius`. namespace WittVector -variable {p : ℕ} {R S : Type*} [hp : Fact p.Prime] [CommRing R] [CommRing S] +variable {p : ℕ} {R : Type*} [hp : Fact p.Prime] [CommRing R] local notation "𝕎" => WittVector p -- type as `\bbW` diff --git a/Mathlib/RingTheory/WittVector/IsPoly.lean b/Mathlib/RingTheory/WittVector/IsPoly.lean index ef5430b614c18..2e6c8619172e2 100644 --- a/Mathlib/RingTheory/WittVector/IsPoly.lean +++ b/Mathlib/RingTheory/WittVector/IsPoly.lean @@ -92,7 +92,7 @@ namespace WittVector universe u -variable {p : ℕ} {R S : Type u} {σ idx : Type*} [CommRing R] [CommRing S] +variable {p : ℕ} {R S : Type u} {idx : Type*} [CommRing R] [CommRing S] local notation "𝕎" => WittVector p -- type as `\bbW` diff --git a/Mathlib/RingTheory/WittVector/Isocrystal.lean b/Mathlib/RingTheory/WittVector/Isocrystal.lean index 5ba7feb02f7c6..0f5d266cc6c93 100644 --- a/Mathlib/RingTheory/WittVector/Isocrystal.lean +++ b/Mathlib/RingTheory/WittVector/Isocrystal.lean @@ -54,7 +54,7 @@ This file introduces notation in the locale `Isocrystal`. noncomputable section -open FiniteDimensional +open Module namespace WittVector @@ -181,7 +181,7 @@ admits an isomorphism to one of the standard (indexed by `m : ℤ`) one-dimensio theorem isocrystal_classification (k : Type*) [Field k] [IsAlgClosed k] [CharP k p] (V : Type*) [AddCommGroup V] [Isocrystal p k V] (h_dim : finrank K(p, k) V = 1) : ∃ m : ℤ, Nonempty (StandardOneDimIsocrystal p k m ≃ᶠⁱ[p, k] V) := by - haveI : Nontrivial V := FiniteDimensional.nontrivial_of_finrank_eq_succ h_dim + haveI : Nontrivial V := Module.nontrivial_of_finrank_eq_succ h_dim obtain ⟨x, hx⟩ : ∃ x : V, x ≠ 0 := exists_ne 0 have : Φ(p, k) x ≠ 0 := by simpa only [map_zero] using Φ(p, k).injective.ne hx obtain ⟨a, ha, hax⟩ : ∃ a : K(p, k), a ≠ 0 ∧ Φ(p, k) x = a • x := by diff --git a/Mathlib/SetTheory/Cardinal/Aleph.lean b/Mathlib/SetTheory/Cardinal/Aleph.lean new file mode 100644 index 0000000000000..a2d762c20d204 --- /dev/null +++ b/Mathlib/SetTheory/Cardinal/Aleph.lean @@ -0,0 +1,424 @@ +/- +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, Floris van Doorn +-/ +import Mathlib.Order.Bounded +import Mathlib.SetTheory.Cardinal.PartENat +import Mathlib.SetTheory.Ordinal.Arithmetic + +/-! +# Aleph and beth functions + +* The function `Cardinal.aleph'` gives the cardinals listed by their ordinal index. + `aleph' n = n`, `aleph' ω = ℵ₀`, `aleph' (ω + 1) = succ ℵ₀`, etc. + It is an order isomorphism between ordinals and cardinals. +* The function `Cardinal.aleph` gives the infinite cardinals listed by their + ordinal index. `aleph 0 = ℵ₀`, `aleph 1 = succ ℵ₀` is the first + uncountable cardinal, and so on. The notation `ω_` combines the latter with `Cardinal.ord`, + giving an enumeration of (infinite) initial ordinals. + Thus `ω_ 0 = ω` and `ω₁ = ω_ 1` is the first uncountable ordinal. +* The function `Cardinal.beth` enumerates the Beth cardinals. `beth 0 = ℵ₀`, + `beth (succ o) = 2 ^ beth o`, and for a limit ordinal `o`, `beth o` is the supremum of `beth a` + for `a < o`. +-/ + +assert_not_exists Module +assert_not_exists Finsupp +assert_not_exists Cardinal.mul_eq_self + +noncomputable section + +open Function Set Cardinal Equiv Order Ordinal + +universe u v w + +namespace Cardinal + +/-! ### Aleph cardinals -/ + +/-- The `aleph'` function gives the cardinals listed by their ordinal index. `aleph' n = n`, +`aleph' ω = ℵ₀`, `aleph' (ω + 1) = succ ℵ₀`, etc. + +For the more common aleph function skipping over finite cardinals, see `Cardinal.aleph`. -/ +def aleph' : Ordinal.{u} ≃o Cardinal.{u} := by + let f := RelEmbedding.collapse Cardinal.ord.orderEmbedding.ltEmbedding.{u} + refine (OrderIso.ofRelIsoLT <| RelIso.ofSurjective f ?_).symm + apply f.eq_or_principal.resolve_right + rintro ⟨o, e⟩ + have : ∀ c, f c < o := fun c => (e _).1 ⟨_, rfl⟩ + refine Ordinal.inductionOn o ?_ this + intro α r _ h + let s := ⨆ a, invFun f (Ordinal.typein r a) + apply (lt_succ s).not_le + have I : Injective f := f.toEmbedding.injective + simpa only [typein_enum, leftInverse_invFun I (succ s)] using + le_ciSup + (Cardinal.bddAbove_range.{u, u} fun a : α => invFun f (Ordinal.typein r a)) + (Ordinal.enum r ⟨_, h (succ s)⟩) + +/-- The `aleph'` index function, which gives the ordinal index of a cardinal. + (The `aleph'` part is because unlike `aleph` this counts also the + finite stages. So `alephIdx n = n`, `alephIdx ω = ω`, + `alephIdx ℵ₁ = ω + 1` and so on.) + In this definition, we register additionally that this function is an initial segment, + i.e., it is order preserving and its range is an initial segment of the ordinals. + For the basic function version, see `alephIdx`. + For an upgraded version stating that the range is everything, see `AlephIdx.rel_iso`. -/ +@[deprecated aleph' (since := "2024-08-28")] +def alephIdx.initialSeg : @InitialSeg Cardinal Ordinal (· < ·) (· < ·) := + @RelEmbedding.collapse Cardinal Ordinal (· < ·) (· < ·) _ Cardinal.ord.orderEmbedding.ltEmbedding + +/-- The `aleph'` index function, which gives the ordinal index of a cardinal. + (The `aleph'` part is because unlike `aleph` this counts also the + finite stages. So `alephIdx n = n`, `alephIdx ℵ₀ = ω`, + `alephIdx ℵ₁ = ω + 1` and so on.) + In this version, we register additionally that this function is an order isomorphism + between cardinals and ordinals. + For the basic function version, see `alephIdx`. -/ +@[deprecated aleph' (since := "2024-08-28")] +def alephIdx.relIso : @RelIso Cardinal.{u} Ordinal.{u} (· < ·) (· < ·) := + aleph'.symm.toRelIsoLT + +/-- The `aleph'` index function, which gives the ordinal index of a cardinal. + (The `aleph'` part is because unlike `aleph` this counts also the + finite stages. So `alephIdx n = n`, `alephIdx ω = ω`, + `alephIdx ℵ₁ = ω + 1` and so on.) + For an upgraded version stating that the range is everything, see `AlephIdx.rel_iso`. -/ +@[deprecated aleph' (since := "2024-08-28")] +def alephIdx : Cardinal → Ordinal := + aleph'.symm + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx.initialSeg_coe : (alephIdx.initialSeg : Cardinal → Ordinal) = alephIdx := + rfl + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx_lt {a b} : alephIdx a < alephIdx b ↔ a < b := + alephIdx.initialSeg.toRelEmbedding.map_rel_iff + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx_le {a b} : alephIdx a ≤ alephIdx b ↔ a ≤ b := by + rw [← not_lt, ← not_lt, alephIdx_lt] + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx.init {a b} : b < alephIdx a → ∃ c, alephIdx c = b := + alephIdx.initialSeg.init + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx.relIso_coe : (alephIdx.relIso : Cardinal → Ordinal) = alephIdx := + rfl + +@[simp] +theorem type_cardinal : @type Cardinal (· < ·) _ = Ordinal.univ.{u, u + 1} := by + rw [Ordinal.univ_id] + exact Quotient.sound ⟨aleph'.symm.toRelIsoLT⟩ + +@[simp] +theorem mk_cardinal : #Cardinal = univ.{u, u + 1} := by + simpa only [card_type, card_univ] using congr_arg card type_cardinal + +/-- The `aleph'` function gives the cardinals listed by their ordinal + index, and is the inverse of `aleph_idx`. + `aleph' n = n`, `aleph' ω = ω`, `aleph' (ω + 1) = succ ℵ₀`, etc. + In this version, we register additionally that this function is an order isomorphism + between ordinals and cardinals. + For the basic function version, see `aleph'`. -/ +@[deprecated aleph' (since := "2024-08-28")] +def Aleph'.relIso := + aleph' + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem aleph'.relIso_coe : (Aleph'.relIso : Ordinal → Cardinal) = aleph' := + rfl + +theorem aleph'_lt {o₁ o₂ : Ordinal} : aleph' o₁ < aleph' o₂ ↔ o₁ < o₂ := + aleph'.lt_iff_lt + +theorem aleph'_le {o₁ o₂ : Ordinal} : aleph' o₁ ≤ aleph' o₂ ↔ o₁ ≤ o₂ := + aleph'.le_iff_le + +theorem aleph'_max (o₁ o₂ : Ordinal) : aleph' (max o₁ o₂) = max (aleph' o₁) (aleph' o₂) := + aleph'.monotone.map_max + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem aleph'_alephIdx (c : Cardinal) : aleph' c.alephIdx = c := + Cardinal.alephIdx.relIso.toEquiv.symm_apply_apply c + +set_option linter.deprecated false in +@[deprecated (since := "2024-08-28")] +theorem alephIdx_aleph' (o : Ordinal) : (aleph' o).alephIdx = o := + Cardinal.alephIdx.relIso.toEquiv.apply_symm_apply o + +@[simp] +theorem aleph'_zero : aleph' 0 = 0 := + aleph'.map_bot + +@[simp] +theorem aleph'_succ (o : Ordinal) : aleph' (succ o) = succ (aleph' o) := + aleph'.map_succ o + +@[simp] +theorem aleph'_nat : ∀ n : ℕ, aleph' n = n + | 0 => aleph'_zero + | n + 1 => show aleph' (succ n) = n.succ by rw [aleph'_succ, aleph'_nat n, nat_succ] + +theorem aleph'_le_of_limit {o : Ordinal} (l : o.IsLimit) {c} : + aleph' o ≤ c ↔ ∀ o' < o, aleph' o' ≤ c := + ⟨fun h o' h' => (aleph'_le.2 <| h'.le).trans h, fun h => by + rw [← aleph'.apply_symm_apply c, aleph'_le, limit_le l] + intro x h' + rw [← aleph'_le, aleph'.apply_symm_apply] + exact h _ h'⟩ + +theorem aleph'_limit {o : Ordinal} (ho : o.IsLimit) : aleph' o = ⨆ a : Iio o, aleph' a := by + refine le_antisymm ?_ (ciSup_le' fun i => aleph'_le.2 (le_of_lt i.2)) + rw [aleph'_le_of_limit ho] + exact fun a ha => le_ciSup (bddAbove_of_small _) (⟨a, ha⟩ : Iio o) + +@[simp] +theorem aleph'_omega0 : aleph' ω = ℵ₀ := + eq_of_forall_ge_iff fun c => by + simp only [aleph'_le_of_limit omega0_isLimit, lt_omega0, exists_imp, aleph0_le] + exact forall_swap.trans (forall_congr' fun n => by simp only [forall_eq, aleph'_nat]) + +@[deprecated (since := "2024-09-30")] +alias aleph'_omega := aleph'_omega0 + +set_option linter.deprecated false in +/-- `aleph'` and `aleph_idx` form an equivalence between `Ordinal` and `Cardinal` -/ +@[deprecated aleph' (since := "2024-08-28")] +def aleph'Equiv : Ordinal ≃ Cardinal := + ⟨aleph', alephIdx, alephIdx_aleph', aleph'_alephIdx⟩ + +/-- The `aleph` function gives the infinite cardinals listed by their ordinal index. `aleph 0 = ℵ₀`, +`aleph 1 = succ ℵ₀` is the first uncountable cardinal, and so on. + +For a version including finite cardinals, see `Cardinal.aleph'`. -/ +def aleph : Ordinal ↪o Cardinal := + (OrderEmbedding.addLeft ω).trans aleph'.toOrderEmbedding + +theorem aleph_eq_aleph' (o : Ordinal) : aleph o = aleph' (ω + o) := + rfl + +theorem aleph_lt {o₁ o₂ : Ordinal} : aleph o₁ < aleph o₂ ↔ o₁ < o₂ := + aleph.lt_iff_lt + +theorem aleph_le {o₁ o₂ : Ordinal} : aleph o₁ ≤ aleph o₂ ↔ o₁ ≤ o₂ := + aleph.le_iff_le + +theorem aleph_max (o₁ o₂ : Ordinal) : aleph (max o₁ o₂) = max (aleph o₁) (aleph o₂) := + aleph.monotone.map_max + +@[deprecated aleph_max (since := "2024-08-28")] +theorem max_aleph_eq (o₁ o₂ : Ordinal) : max (aleph o₁) (aleph o₂) = aleph (max o₁ o₂) := + (aleph_max o₁ o₂).symm + +@[simp] +theorem aleph_succ (o : Ordinal) : aleph (succ o) = succ (aleph o) := by + rw [aleph_eq_aleph', add_succ, aleph'_succ, aleph_eq_aleph'] + +@[simp] +theorem aleph_zero : aleph 0 = ℵ₀ := by rw [aleph_eq_aleph', add_zero, aleph'_omega0] + +theorem aleph_limit {o : Ordinal} (ho : o.IsLimit) : aleph o = ⨆ a : Iio o, aleph a := by + apply le_antisymm _ (ciSup_le' _) + · rw [aleph_eq_aleph', aleph'_limit (ho.add _)] + refine ciSup_mono' (bddAbove_of_small _) ?_ + rintro ⟨i, hi⟩ + cases' lt_or_le i ω with h h + · rcases lt_omega0.1 h with ⟨n, rfl⟩ + use ⟨0, ho.pos⟩ + simpa using (nat_lt_aleph0 n).le + · exact ⟨⟨_, (sub_lt_of_le h).2 hi⟩, aleph'_le.2 (le_add_sub _ _)⟩ + · exact fun i => aleph_le.2 (le_of_lt i.2) + +theorem aleph0_le_aleph' {o : Ordinal} : ℵ₀ ≤ aleph' o ↔ ω ≤ o := by rw [← aleph'_omega0, aleph'_le] + +theorem aleph0_le_aleph (o : Ordinal) : ℵ₀ ≤ aleph o := by + rw [aleph_eq_aleph', aleph0_le_aleph'] + apply Ordinal.le_add_right + +theorem aleph'_pos {o : Ordinal} (ho : 0 < o) : 0 < aleph' o := by rwa [← aleph'_zero, aleph'_lt] + +theorem aleph_pos (o : Ordinal) : 0 < aleph o := + aleph0_pos.trans_le (aleph0_le_aleph o) + +@[simp] +theorem aleph_toNat (o : Ordinal) : toNat (aleph o) = 0 := + toNat_apply_of_aleph0_le <| aleph0_le_aleph o + +@[simp] +theorem aleph_toPartENat (o : Ordinal) : toPartENat (aleph o) = ⊤ := + toPartENat_apply_of_aleph0_le <| aleph0_le_aleph o + +instance nonempty_toType_aleph (o : Ordinal) : Nonempty (aleph o).ord.toType := by + rw [toType_nonempty_iff_ne_zero, ← ord_zero] + exact fun h => (ord_injective h).not_gt (aleph_pos o) + +theorem ord_aleph_isLimit (o : Ordinal) : (aleph o).ord.IsLimit := + ord_isLimit <| aleph0_le_aleph _ + +instance (o : Ordinal) : NoMaxOrder (aleph o).ord.toType := + toType_noMax_of_succ_lt (ord_aleph_isLimit o).2 + +theorem exists_aleph {c : Cardinal} : ℵ₀ ≤ c ↔ ∃ o, c = aleph o := + ⟨fun h => + ⟨aleph'.symm c - ω, by + rw [aleph_eq_aleph', Ordinal.add_sub_cancel_of_le, aleph'.apply_symm_apply] + rwa [← aleph0_le_aleph', aleph'.apply_symm_apply]⟩, + fun ⟨o, e⟩ => e.symm ▸ aleph0_le_aleph _⟩ + +theorem aleph'_isNormal : IsNormal (ord ∘ aleph') := + ⟨fun o => ord_lt_ord.2 <| aleph'_lt.2 <| lt_succ o, fun o l a => by + simp [ord_le, aleph'_le_of_limit l]⟩ + +theorem aleph_isNormal : IsNormal (ord ∘ aleph) := + aleph'_isNormal.trans <| add_isNormal ω + +theorem succ_aleph0 : succ ℵ₀ = aleph 1 := by rw [← aleph_zero, ← aleph_succ, Ordinal.succ_zero] + +theorem aleph0_lt_aleph_one : ℵ₀ < aleph 1 := by + rw [← succ_aleph0] + apply lt_succ + +theorem countable_iff_lt_aleph_one {α : Type*} (s : Set α) : s.Countable ↔ #s < aleph 1 := by + rw [← succ_aleph0, lt_succ_iff, le_aleph0_iff_set_countable] + +section deprecated + +set_option linter.deprecated false + +-- TODO: these lemmas should be stated in terms of the `ω` function and of an `IsInitial` predicate, +-- neither of which currently exist. +-- +-- They should also use `¬ BddAbove` instead of `Unbounded (· < ·)`. + +/-- Ordinals that are cardinals are unbounded. -/ +@[deprecated (since := "2024-09-24")] +theorem ord_card_unbounded : Unbounded (· < ·) { b : Ordinal | b.card.ord = b } := + unbounded_lt_iff.2 fun a => + ⟨_, + ⟨by + dsimp + rw [card_ord], (lt_ord_succ_card a).le⟩⟩ + +@[deprecated (since := "2024-09-24")] +theorem eq_aleph'_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) : ∃ a, (aleph' a).ord = o := + ⟨aleph'.symm o.card, by simpa using ho⟩ + +/-- Infinite ordinals that are cardinals are unbounded. -/ +@[deprecated (since := "2024-09-24")] +theorem ord_card_unbounded' : Unbounded (· < ·) { b : Ordinal | b.card.ord = b ∧ ω ≤ b } := + (unbounded_lt_inter_le ω).2 ord_card_unbounded + +@[deprecated (since := "2024-09-24")] +theorem eq_aleph_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) (ho' : ω ≤ o) : + ∃ a, (aleph a).ord = o := by + cases' eq_aleph'_of_eq_card_ord ho with a ha + use a - ω + rwa [aleph_eq_aleph', Ordinal.add_sub_cancel_of_le] + rwa [← aleph0_le_aleph', ← ord_le_ord, ha, ord_aleph0] + +end deprecated + +/-! ### Beth cardinals -/ + +/-- Beth numbers are defined so that `beth 0 = ℵ₀`, `beth (succ o) = 2 ^ (beth o)`, and when `o` is +a limit ordinal, `beth o` is the supremum of `beth o'` for `o' < o`. + +Assuming the generalized continuum hypothesis, which is undecidable in ZFC, `beth o = aleph o` for +every `o`. -/ +def beth (o : Ordinal.{u}) : Cardinal.{u} := + limitRecOn o aleph0 (fun _ x => (2 : Cardinal) ^ x) fun a _ IH => ⨆ b : Iio a, IH b.1 b.2 + +@[simp] +theorem beth_zero : beth 0 = aleph0 := + limitRecOn_zero _ _ _ + +@[simp] +theorem beth_succ (o : Ordinal) : beth (succ o) = 2 ^ beth o := + limitRecOn_succ _ _ _ _ + +theorem beth_limit {o : Ordinal} : o.IsLimit → beth o = ⨆ a : Iio o, beth a := + limitRecOn_limit _ _ _ _ + +theorem beth_strictMono : StrictMono beth := by + intro a b + induction' b using Ordinal.induction with b IH generalizing a + intro h + rcases zero_or_succ_or_limit b with (rfl | ⟨c, rfl⟩ | hb) + · exact (Ordinal.not_lt_zero a h).elim + · rw [lt_succ_iff] at h + rw [beth_succ] + apply lt_of_le_of_lt _ (cantor _) + rcases eq_or_lt_of_le h with (rfl | h) + · rfl + exact (IH c (lt_succ c) h).le + · apply (cantor _).trans_le + rw [beth_limit hb, ← beth_succ] + exact le_ciSup (bddAbove_of_small _) (⟨_, hb.succ_lt h⟩ : Iio b) + +theorem beth_mono : Monotone beth := + beth_strictMono.monotone + +@[simp] +theorem beth_lt {o₁ o₂ : Ordinal} : beth o₁ < beth o₂ ↔ o₁ < o₂ := + beth_strictMono.lt_iff_lt + +@[simp] +theorem beth_le {o₁ o₂ : Ordinal} : beth o₁ ≤ beth o₂ ↔ o₁ ≤ o₂ := + beth_strictMono.le_iff_le + +theorem aleph_le_beth (o : Ordinal) : aleph o ≤ beth o := by + induction o using limitRecOn with + | H₁ => simp + | H₂ o h => + rw [aleph_succ, beth_succ, succ_le_iff] + exact (cantor _).trans_le (power_le_power_left two_ne_zero h) + | H₃ o ho IH => + rw [aleph_limit ho, beth_limit ho] + exact ciSup_mono (bddAbove_of_small _) fun x => IH x.1 x.2 + +theorem aleph0_le_beth (o : Ordinal) : ℵ₀ ≤ beth o := + (aleph0_le_aleph o).trans <| aleph_le_beth o + +theorem beth_pos (o : Ordinal) : 0 < beth o := + aleph0_pos.trans_le <| aleph0_le_beth o + +theorem beth_ne_zero (o : Ordinal) : beth o ≠ 0 := + (beth_pos o).ne' + +theorem beth_normal : IsNormal.{u} fun o => (beth o).ord := + (isNormal_iff_strictMono_limit _).2 + ⟨ord_strictMono.comp beth_strictMono, fun o ho a ha => by + rw [beth_limit ho, ord_le] + exact ciSup_le' fun b => ord_le.1 (ha _ b.2)⟩ + +end Cardinal + +/-! ### Omega ordinals -/ + +namespace Ordinal + +/-- +`ω_ o` is a notation for the *initial ordinal* of cardinality +`aleph o`. Thus, for example `ω_ 0 = ω`. +-/ +scoped notation "ω_" o => ord <| aleph o + +/-- +`ω₁` is the first uncountable ordinal. +-/ +scoped notation "ω₁" => ord <| aleph 1 + +lemma omega_lt_omega1 : ω < ω₁ := ord_aleph0.symm.trans_lt (ord_lt_ord.mpr (aleph0_lt_aleph_one)) + +end Ordinal diff --git a/Mathlib/SetTheory/Cardinal/Ordinal.lean b/Mathlib/SetTheory/Cardinal/Arithmetic.lean similarity index 57% rename from Mathlib/SetTheory/Cardinal/Ordinal.lean rename to Mathlib/SetTheory/Cardinal/Arithmetic.lean index f605981cb3c6b..4bb8721a053d7 100644 --- a/Mathlib/SetTheory/Cardinal/Ordinal.lean +++ b/Mathlib/SetTheory/Cardinal/Arithmetic.lean @@ -3,36 +3,22 @@ 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, Floris van Doorn -/ -import Mathlib.Order.Bounded -import Mathlib.SetTheory.Cardinal.PartENat +import Mathlib.SetTheory.Cardinal.Aleph import Mathlib.SetTheory.Ordinal.Principal import Mathlib.Tactic.Linarith /-! -# Cardinals and ordinals +# Cardinal arithmetic -Relationships between cardinals and ordinals, properties of cardinals that are proved -using ordinals. - -## Main definitions - -* The function `Cardinal.aleph'` gives the cardinals listed by their ordinal index. - `aleph' n = n`, `aleph' ω = ℵ₀`, `aleph' (ω + 1) = succ ℵ₀`, etc. - It is an order isomorphism between ordinals and cardinals. -* The function `Cardinal.aleph` gives the infinite cardinals listed by their - ordinal index. `aleph 0 = ℵ₀`, `aleph 1 = succ ℵ₀` is the first - uncountable cardinal, and so on. The notation `ω_` combines the latter with `Cardinal.ord`, - giving an enumeration of (infinite) initial ordinals. - Thus `ω_ 0 = ω` and `ω₁ = ω_ 1` is the first uncountable ordinal. -* The function `Cardinal.beth` enumerates the Beth cardinals. `beth 0 = ℵ₀`, - `beth (succ o) = 2 ^ beth o`, and for a limit ordinal `o`, `beth o` is the supremum of `beth a` - for `a < o`. +Arithmetic operations on cardinals are defined in `SetTheory/Cardinal/Basic.lean`. However, proving +the important theorem `c * c = c` for infinite cardinals and its corollaries requires the use of +ordinal numbers. This is done within this file. ## Main statements * `Cardinal.mul_eq_max` and `Cardinal.add_eq_max` state that the product (resp. sum) of two infinite cardinals is just their maximum. Several variations around this fact are also given. -* `Cardinal.mk_list_eq_mk` : when `α` is infinite, `α` and `List α` have the same cardinality. +* `Cardinal.mk_list_eq_mk`: when `α` is infinite, `α` and `List α` have the same cardinality. ## Tags @@ -50,400 +36,8 @@ universe u v w namespace Cardinal -section UsingOrdinals - -theorem ord_isLimit {c} (co : ℵ₀ ≤ c) : (ord c).IsLimit := by - refine ⟨fun h => aleph0_ne_zero ?_, fun a => lt_imp_lt_of_le_imp_le fun h => ?_⟩ - · rw [← Ordinal.le_zero, ord_le] at h - simpa only [card_zero, nonpos_iff_eq_zero] using co.trans h - · rw [ord_le] at h ⊢ - rwa [← @add_one_of_aleph0_le (card a), ← card_succ] - rw [← ord_le, ← le_succ_of_isLimit, ord_le] - · exact co.trans h - · rw [ord_aleph0] - exact omega_isLimit - -theorem noMaxOrder {c} (h : ℵ₀ ≤ c) : NoMaxOrder c.ord.toType := - toType_noMax_of_succ_lt (ord_isLimit h).2 - -/-! ### Aleph cardinals -/ - -section aleph - -/-- The `aleph'` function gives the cardinals listed by their ordinal index. `aleph' n = n`, -`aleph' ω = ℵ₀`, `aleph' (ω + 1) = succ ℵ₀`, etc. - -For the more common aleph function skipping over finite cardinals, see `Cardinal.aleph`. -/ -def aleph' : Ordinal.{u} ≃o Cardinal.{u} := by - let f := RelEmbedding.collapse Cardinal.ord.orderEmbedding.ltEmbedding.{u} - refine (OrderIso.ofRelIsoLT <| RelIso.ofSurjective f ?_).symm - apply f.eq_or_principal.resolve_right - rintro ⟨o, e⟩ - have : ∀ c, f c < o := fun c => (e _).2 ⟨_, rfl⟩ - refine Ordinal.inductionOn o ?_ this - intro α r _ h - let s := ⨆ a, invFun f (Ordinal.typein r a) - apply (lt_succ s).not_le - have I : Injective f := f.toEmbedding.injective - simpa only [typein_enum, leftInverse_invFun I (succ s)] using - le_ciSup - (Cardinal.bddAbove_range.{u, u} fun a : α => invFun f (Ordinal.typein r a)) - (Ordinal.enum r ⟨_, h (succ s)⟩) - -/-- The `aleph'` index function, which gives the ordinal index of a cardinal. - (The `aleph'` part is because unlike `aleph` this counts also the - finite stages. So `alephIdx n = n`, `alephIdx ω = ω`, - `alephIdx ℵ₁ = ω + 1` and so on.) - In this definition, we register additionally that this function is an initial segment, - i.e., it is order preserving and its range is an initial segment of the ordinals. - For the basic function version, see `alephIdx`. - For an upgraded version stating that the range is everything, see `AlephIdx.rel_iso`. -/ -@[deprecated aleph' (since := "2024-08-28")] -def alephIdx.initialSeg : @InitialSeg Cardinal Ordinal (· < ·) (· < ·) := - @RelEmbedding.collapse Cardinal Ordinal (· < ·) (· < ·) _ Cardinal.ord.orderEmbedding.ltEmbedding - -/-- The `aleph'` index function, which gives the ordinal index of a cardinal. - (The `aleph'` part is because unlike `aleph` this counts also the - finite stages. So `alephIdx n = n`, `alephIdx ℵ₀ = ω`, - `alephIdx ℵ₁ = ω + 1` and so on.) - In this version, we register additionally that this function is an order isomorphism - between cardinals and ordinals. - For the basic function version, see `alephIdx`. -/ -@[deprecated aleph' (since := "2024-08-28")] -def alephIdx.relIso : @RelIso Cardinal.{u} Ordinal.{u} (· < ·) (· < ·) := - aleph'.symm.toRelIsoLT - -/-- The `aleph'` index function, which gives the ordinal index of a cardinal. - (The `aleph'` part is because unlike `aleph` this counts also the - finite stages. So `alephIdx n = n`, `alephIdx ω = ω`, - `alephIdx ℵ₁ = ω + 1` and so on.) - For an upgraded version stating that the range is everything, see `AlephIdx.rel_iso`. -/ -@[deprecated aleph' (since := "2024-08-28")] -def alephIdx : Cardinal → Ordinal := - aleph'.symm - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx.initialSeg_coe : (alephIdx.initialSeg : Cardinal → Ordinal) = alephIdx := - rfl - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx_lt {a b} : alephIdx a < alephIdx b ↔ a < b := - alephIdx.initialSeg.toRelEmbedding.map_rel_iff - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx_le {a b} : alephIdx a ≤ alephIdx b ↔ a ≤ b := by - rw [← not_lt, ← not_lt, alephIdx_lt] - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx.init {a b} : b < alephIdx a → ∃ c, alephIdx c = b := - alephIdx.initialSeg.init - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx.relIso_coe : (alephIdx.relIso : Cardinal → Ordinal) = alephIdx := - rfl - -@[simp] -theorem type_cardinal : @type Cardinal (· < ·) _ = Ordinal.univ.{u, u + 1} := by - rw [Ordinal.univ_id] - exact Quotient.sound ⟨aleph'.symm.toRelIsoLT⟩ - -@[simp] -theorem mk_cardinal : #Cardinal = univ.{u, u + 1} := by - simpa only [card_type, card_univ] using congr_arg card type_cardinal - -/-- The `aleph'` function gives the cardinals listed by their ordinal - index, and is the inverse of `aleph_idx`. - `aleph' n = n`, `aleph' ω = ω`, `aleph' (ω + 1) = succ ℵ₀`, etc. - In this version, we register additionally that this function is an order isomorphism - between ordinals and cardinals. - For the basic function version, see `aleph'`. -/ -@[deprecated aleph' (since := "2024-08-28")] -def Aleph'.relIso := - aleph' - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem aleph'.relIso_coe : (Aleph'.relIso : Ordinal → Cardinal) = aleph' := - rfl - -theorem aleph'_lt {o₁ o₂ : Ordinal} : aleph' o₁ < aleph' o₂ ↔ o₁ < o₂ := - aleph'.lt_iff_lt - -theorem aleph'_le {o₁ o₂ : Ordinal} : aleph' o₁ ≤ aleph' o₂ ↔ o₁ ≤ o₂ := - aleph'.le_iff_le - -theorem aleph'_max (o₁ o₂ : Ordinal) : aleph' (max o₁ o₂) = max (aleph' o₁) (aleph' o₂) := - aleph'.monotone.map_max - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem aleph'_alephIdx (c : Cardinal) : aleph' c.alephIdx = c := - Cardinal.alephIdx.relIso.toEquiv.symm_apply_apply c - -set_option linter.deprecated false in -@[deprecated (since := "2024-08-28")] -theorem alephIdx_aleph' (o : Ordinal) : (aleph' o).alephIdx = o := - Cardinal.alephIdx.relIso.toEquiv.apply_symm_apply o - -@[simp] -theorem aleph'_zero : aleph' 0 = 0 := - aleph'.map_bot - -@[simp] -theorem aleph'_succ (o : Ordinal) : aleph' (succ o) = succ (aleph' o) := - aleph'.map_succ o - -@[simp] -theorem aleph'_nat : ∀ n : ℕ, aleph' n = n - | 0 => aleph'_zero - | n + 1 => show aleph' (succ n) = n.succ by rw [aleph'_succ, aleph'_nat n, nat_succ] - -theorem aleph'_le_of_limit {o : Ordinal} (l : o.IsLimit) {c} : - aleph' o ≤ c ↔ ∀ o' < o, aleph' o' ≤ c := - ⟨fun h o' h' => (aleph'_le.2 <| h'.le).trans h, fun h => by - rw [← aleph'.apply_symm_apply c, aleph'_le, limit_le l] - intro x h' - rw [← aleph'_le, aleph'.apply_symm_apply] - exact h _ h'⟩ - -theorem aleph'_limit {o : Ordinal} (ho : o.IsLimit) : aleph' o = ⨆ a : Iio o, aleph' a := by - refine le_antisymm ?_ (ciSup_le' fun i => aleph'_le.2 (le_of_lt i.2)) - rw [aleph'_le_of_limit ho] - exact fun a ha => le_ciSup (bddAbove_of_small _) (⟨a, ha⟩ : Iio o) - -@[simp] -theorem aleph'_omega : aleph' ω = ℵ₀ := - eq_of_forall_ge_iff fun c => by - simp only [aleph'_le_of_limit omega_isLimit, lt_omega, exists_imp, aleph0_le] - exact forall_swap.trans (forall_congr' fun n => by simp only [forall_eq, aleph'_nat]) - -set_option linter.deprecated false in -/-- `aleph'` and `aleph_idx` form an equivalence between `Ordinal` and `Cardinal` -/ -@[deprecated aleph' (since := "2024-08-28")] -def aleph'Equiv : Ordinal ≃ Cardinal := - ⟨aleph', alephIdx, alephIdx_aleph', aleph'_alephIdx⟩ - -/-- The `aleph` function gives the infinite cardinals listed by their ordinal index. `aleph 0 = ℵ₀`, -`aleph 1 = succ ℵ₀` is the first uncountable cardinal, and so on. - -For a version including finite cardinals, see `Cardinal.aleph'`. -/ -def aleph : Ordinal ↪o Cardinal := - (OrderEmbedding.addLeft ω).trans aleph'.toOrderEmbedding - -theorem aleph_eq_aleph' (o : Ordinal) : aleph o = aleph' (ω + o) := - rfl - -theorem aleph_lt {o₁ o₂ : Ordinal} : aleph o₁ < aleph o₂ ↔ o₁ < o₂ := - aleph.lt_iff_lt - -theorem aleph_le {o₁ o₂ : Ordinal} : aleph o₁ ≤ aleph o₂ ↔ o₁ ≤ o₂ := - aleph.le_iff_le - -theorem aleph_max (o₁ o₂ : Ordinal) : aleph (max o₁ o₂) = max (aleph o₁) (aleph o₂) := - aleph.monotone.map_max - -@[deprecated aleph_max (since := "2024-08-28")] -theorem max_aleph_eq (o₁ o₂ : Ordinal) : max (aleph o₁) (aleph o₂) = aleph (max o₁ o₂) := - (aleph_max o₁ o₂).symm - -@[simp] -theorem aleph_succ (o : Ordinal) : aleph (succ o) = succ (aleph o) := by - rw [aleph_eq_aleph', add_succ, aleph'_succ, aleph_eq_aleph'] - -@[simp] -theorem aleph_zero : aleph 0 = ℵ₀ := by rw [aleph_eq_aleph', add_zero, aleph'_omega] - -theorem aleph_limit {o : Ordinal} (ho : o.IsLimit) : aleph o = ⨆ a : Iio o, aleph a := by - apply le_antisymm _ (ciSup_le' _) - · rw [aleph_eq_aleph', aleph'_limit (ho.add _)] - refine ciSup_mono' (bddAbove_of_small _) ?_ - rintro ⟨i, hi⟩ - cases' lt_or_le i ω with h h - · rcases lt_omega.1 h with ⟨n, rfl⟩ - use ⟨0, ho.pos⟩ - simpa using (nat_lt_aleph0 n).le - · exact ⟨⟨_, (sub_lt_of_le h).2 hi⟩, aleph'_le.2 (le_add_sub _ _)⟩ - · exact fun i => aleph_le.2 (le_of_lt i.2) - -theorem aleph0_le_aleph' {o : Ordinal} : ℵ₀ ≤ aleph' o ↔ ω ≤ o := by rw [← aleph'_omega, aleph'_le] - -theorem aleph0_le_aleph (o : Ordinal) : ℵ₀ ≤ aleph o := by - rw [aleph_eq_aleph', aleph0_le_aleph'] - apply Ordinal.le_add_right - -theorem aleph'_pos {o : Ordinal} (ho : 0 < o) : 0 < aleph' o := by rwa [← aleph'_zero, aleph'_lt] - -theorem aleph_pos (o : Ordinal) : 0 < aleph o := - aleph0_pos.trans_le (aleph0_le_aleph o) - -@[simp] -theorem aleph_toNat (o : Ordinal) : toNat (aleph o) = 0 := - toNat_apply_of_aleph0_le <| aleph0_le_aleph o - -@[simp] -theorem aleph_toPartENat (o : Ordinal) : toPartENat (aleph o) = ⊤ := - toPartENat_apply_of_aleph0_le <| aleph0_le_aleph o - -instance nonempty_toType_aleph (o : Ordinal) : Nonempty (aleph o).ord.toType := by - rw [toType_nonempty_iff_ne_zero, ← ord_zero] - exact fun h => (ord_injective h).not_gt (aleph_pos o) - -theorem ord_aleph_isLimit (o : Ordinal) : (aleph o).ord.IsLimit := - ord_isLimit <| aleph0_le_aleph _ - -instance (o : Ordinal) : NoMaxOrder (aleph o).ord.toType := - toType_noMax_of_succ_lt (ord_aleph_isLimit o).2 - -theorem exists_aleph {c : Cardinal} : ℵ₀ ≤ c ↔ ∃ o, c = aleph o := - ⟨fun h => - ⟨aleph'.symm c - ω, by - rw [aleph_eq_aleph', Ordinal.add_sub_cancel_of_le, aleph'.apply_symm_apply] - rwa [← aleph0_le_aleph', aleph'.apply_symm_apply]⟩, - fun ⟨o, e⟩ => e.symm ▸ aleph0_le_aleph _⟩ - -theorem aleph'_isNormal : IsNormal (ord ∘ aleph') := - ⟨fun o => ord_lt_ord.2 <| aleph'_lt.2 <| lt_succ o, fun o l a => by - simp [ord_le, aleph'_le_of_limit l]⟩ - -theorem aleph_isNormal : IsNormal (ord ∘ aleph) := - aleph'_isNormal.trans <| add_isNormal ω - -theorem succ_aleph0 : succ ℵ₀ = aleph 1 := by rw [← aleph_zero, ← aleph_succ, Ordinal.succ_zero] - -theorem aleph0_lt_aleph_one : ℵ₀ < aleph 1 := by - rw [← succ_aleph0] - apply lt_succ - -theorem countable_iff_lt_aleph_one {α : Type*} (s : Set α) : s.Countable ↔ #s < aleph 1 := by - rw [← succ_aleph0, lt_succ_iff, le_aleph0_iff_set_countable] - -/-- Ordinals that are cardinals are unbounded. -/ -theorem ord_card_unbounded : Unbounded (· < ·) { b : Ordinal | b.card.ord = b } := - unbounded_lt_iff.2 fun a => - ⟨_, - ⟨by - dsimp - rw [card_ord], (lt_ord_succ_card a).le⟩⟩ - -theorem eq_aleph'_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) : ∃ a, (aleph' a).ord = o := - ⟨aleph'.symm o.card, by simpa using ho⟩ - -/-- `ord ∘ aleph'` enumerates the ordinals that are cardinals. -/ -theorem ord_aleph'_eq_enum_card : ord ∘ aleph' = enumOrd { b : Ordinal | b.card.ord = b } := by - rw [← eq_enumOrd _ ord_card_unbounded, range_eq_iff] - exact - ⟨aleph'_isNormal.strictMono, - ⟨fun a => by - dsimp - rw [card_ord], fun b hb => eq_aleph'_of_eq_card_ord hb⟩⟩ - -/-- Infinite ordinals that are cardinals are unbounded. -/ -theorem ord_card_unbounded' : Unbounded (· < ·) { b : Ordinal | b.card.ord = b ∧ ω ≤ b } := - (unbounded_lt_inter_le ω).2 ord_card_unbounded - -theorem eq_aleph_of_eq_card_ord {o : Ordinal} (ho : o.card.ord = o) (ho' : ω ≤ o) : - ∃ a, (aleph a).ord = o := by - cases' eq_aleph'_of_eq_card_ord ho with a ha - use a - ω - rwa [aleph_eq_aleph', Ordinal.add_sub_cancel_of_le] - rwa [← aleph0_le_aleph', ← ord_le_ord, ha, ord_aleph0] - -/-- `ord ∘ aleph` enumerates the infinite ordinals that are cardinals. -/ -theorem ord_aleph_eq_enum_card : - ord ∘ aleph = enumOrd { b : Ordinal | b.card.ord = b ∧ ω ≤ b } := by - rw [← eq_enumOrd _ ord_card_unbounded'] - use aleph_isNormal.strictMono - rw [range_eq_iff] - refine ⟨fun a => ⟨?_, ?_⟩, fun b hb => eq_aleph_of_eq_card_ord hb.1 hb.2⟩ - · rw [Function.comp_apply, card_ord] - · rw [← ord_aleph0, Function.comp_apply, ord_le_ord] - exact aleph0_le_aleph _ - -end aleph - -/-! ### Beth cardinals -/ -section beth - -/-- Beth numbers are defined so that `beth 0 = ℵ₀`, `beth (succ o) = 2 ^ (beth o)`, and when `o` is -a limit ordinal, `beth o` is the supremum of `beth o'` for `o' < o`. - -Assuming the generalized continuum hypothesis, which is undecidable in ZFC, `beth o = aleph o` for -every `o`. -/ -def beth (o : Ordinal.{u}) : Cardinal.{u} := - limitRecOn o aleph0 (fun _ x => (2 : Cardinal) ^ x) fun a _ IH => ⨆ b : Iio a, IH b.1 b.2 - -@[simp] -theorem beth_zero : beth 0 = aleph0 := - limitRecOn_zero _ _ _ - -@[simp] -theorem beth_succ (o : Ordinal) : beth (succ o) = 2 ^ beth o := - limitRecOn_succ _ _ _ _ - -theorem beth_limit {o : Ordinal} : o.IsLimit → beth o = ⨆ a : Iio o, beth a := - limitRecOn_limit _ _ _ _ - -theorem beth_strictMono : StrictMono beth := by - intro a b - induction' b using Ordinal.induction with b IH generalizing a - intro h - rcases zero_or_succ_or_limit b with (rfl | ⟨c, rfl⟩ | hb) - · exact (Ordinal.not_lt_zero a h).elim - · rw [lt_succ_iff] at h - rw [beth_succ] - apply lt_of_le_of_lt _ (cantor _) - rcases eq_or_lt_of_le h with (rfl | h) - · rfl - exact (IH c (lt_succ c) h).le - · apply (cantor _).trans_le - rw [beth_limit hb, ← beth_succ] - exact le_ciSup (bddAbove_of_small _) (⟨_, hb.succ_lt h⟩ : Iio b) - -theorem beth_mono : Monotone beth := - beth_strictMono.monotone - -@[simp] -theorem beth_lt {o₁ o₂ : Ordinal} : beth o₁ < beth o₂ ↔ o₁ < o₂ := - beth_strictMono.lt_iff_lt - -@[simp] -theorem beth_le {o₁ o₂ : Ordinal} : beth o₁ ≤ beth o₂ ↔ o₁ ≤ o₂ := - beth_strictMono.le_iff_le - -theorem aleph_le_beth (o : Ordinal) : aleph o ≤ beth o := by - induction o using limitRecOn with - | H₁ => simp - | H₂ o h => - rw [aleph_succ, beth_succ, succ_le_iff] - exact (cantor _).trans_le (power_le_power_left two_ne_zero h) - | H₃ o ho IH => - rw [aleph_limit ho, beth_limit ho] - exact ciSup_mono (bddAbove_of_small _) fun x => IH x.1 x.2 - -theorem aleph0_le_beth (o : Ordinal) : ℵ₀ ≤ beth o := - (aleph0_le_aleph o).trans <| aleph_le_beth o - -theorem beth_pos (o : Ordinal) : 0 < beth o := - aleph0_pos.trans_le <| aleph0_le_beth o - -theorem beth_ne_zero (o : Ordinal) : beth o ≠ 0 := - (beth_pos o).ne' - -theorem beth_normal : IsNormal.{u} fun o => (beth o).ord := - (isNormal_iff_strictMono_limit _).2 - ⟨ord_strictMono.comp beth_strictMono, fun o ho a ha => by - rw [beth_limit ho, ord_le] - exact ciSup_le' fun b => ord_le.1 (ha _ b.2)⟩ - -end beth - /-! ### Properties of `mul` -/ -section mulOrdinals +section mul /-- If `α` is an infinite type, then `α × α` and `α` have the same cardinality. -/ theorem mul_eq_self {c : Cardinal} (h : ℵ₀ ≤ c) : c * c = c := by @@ -492,13 +86,6 @@ theorem mul_eq_self {c : Cardinal} (h : ℵ₀ ≤ c) : c * c = c := by rw [mk'_def, e] apply typein_lt_type -end mulOrdinals - -end UsingOrdinals - -/-! Properties of `mul`, not requiring ordinals -/ -section mul - /-- If `α` and `β` are infinite types, then the cardinality of `α × β` is the maximum of the cardinalities of `α` and `β`. -/ theorem mul_eq_max {a b : Cardinal} (ha : ℵ₀ ≤ a) (hb : ℵ₀ ≤ b) : a * b = max a b := @@ -769,6 +356,7 @@ protected theorem eq_of_add_eq_add_right {a b c : Cardinal} (h : a + b = c + b) end add +/-! ### Properties of `ciSup` -/ section ciSup variable {ι : Type u} {ι' : Type w} (f : ι → Cardinal.{v}) @@ -829,6 +417,9 @@ protected theorem ciSup_mul_ciSup (g : ι' → Cardinal.{v}) : end ciSup +/-! ### Properties of `aleph` -/ +section aleph + @[simp] theorem aleph_add_aleph (o₁ o₂ : Ordinal) : aleph o₁ + aleph o₂ = aleph (max o₁ o₂) := by rw [Cardinal.add_eq_max (aleph0_le_aleph o₁), aleph_max] @@ -873,8 +464,10 @@ theorem add_one_le_add_one_iff {α β : Cardinal} : α + 1 ≤ β + 1 ↔ α ≤ @[deprecated (since := "2024-02-12")] alias add_one_le_add_one_iff_of_lt_aleph_0 := add_one_le_add_one_iff -/-! ### Properties about power -/ -section pow +end aleph + +/-! ### Properties about `power` -/ +section power theorem pow_le {κ μ : Cardinal.{u}} (H1 : ℵ₀ ≤ κ) (H2 : μ < ℵ₀) : κ ^ μ ≤ κ := let ⟨n, H3⟩ := lt_aleph0.1 H2 @@ -949,7 +542,7 @@ theorem powerlt_aleph0_le (c : Cardinal) : c ^< ℵ₀ ≤ max c ℵ₀ := by rw [powerlt_le] exact fun c' hc' => (power_lt_aleph0 h hc').le.trans (le_max_right _ _) -end pow +end power /-! ### Computing cardinality of various types -/ section computing @@ -1193,6 +786,7 @@ theorem mk_compl_eq_mk_compl_finite_same {α : Type u} [Finite α] {s t : Set α end compl /-! ### Extending an injection to an equiv -/ +section extend theorem extend_function {α β : Type*} {s : Set α} (f : s ↪ β) (h : Nonempty ((sᶜ : Set α) ≃ ((range f)ᶜ : Set β))) : ∃ g : α ≃ β, ∀ x : s, g x = f x := by @@ -1222,234 +816,17 @@ theorem extend_function_of_lt {α β : Type*} {s : Set α} (f : s ↪ β) (hs : rwa [mk_compl_of_infinite s hs, mk_compl_of_infinite] rwa [← lift_lt, mk_range_eq_of_injective f.injective, ← h, lift_lt] - --- Porting note: we no longer express literals as `bit0` and `bit1` in Lean 4, so we can't use this --- section Bit - --- /-! --- This section proves inequalities for `bit0` and `bit1`, enabling `simp` to solve inequalities --- for numeral cardinals. The complexity of the resulting algorithm is not good, as in some cases --- `simp` reduces an inequality to a disjunction of two situations, depending on whether a cardinal --- is finite or infinite. Since the evaluation of the branches is not lazy, this is bad. It is good --- enough for practical situations, though. - --- For specific numbers, these inequalities could also be deduced from the corresponding --- inequalities of natural numbers using `norm_cast`: --- ``` --- example : (37 : cardinal) < 42 := --- by { norm_cast, norm_num } --- ``` --- -/ - - --- theorem bit0_ne_zero (a : Cardinal) : ¬bit0 a = 0 ↔ ¬a = 0 := by simp [bit0] - --- @[simp] --- theorem bit1_ne_zero (a : Cardinal) : ¬bit1 a = 0 := by simp [bit1] - --- @[simp] --- theorem zero_lt_bit0 (a : Cardinal) : 0 < bit0 a ↔ 0 < a := by --- rw [← not_iff_not] --- simp [bit0] - --- @[simp] --- theorem zero_lt_bit1 (a : Cardinal) : 0 < bit1 a := --- zero_lt_one.trans_le (self_le_add_left _ _) - --- @[simp] --- theorem one_le_bit0 (a : Cardinal) : 1 ≤ bit0 a ↔ 0 < a := --- ⟨fun h => (zero_lt_bit0 a).mp (zero_lt_one.trans_le h), fun h => --- (one_le_iff_pos.mpr h).trans (self_le_add_left a a)⟩ - --- @[simp] --- theorem one_le_bit1 (a : Cardinal) : 1 ≤ bit1 a := --- self_le_add_left _ _ - --- theorem bit0_eq_self {c : Cardinal} (h : ℵ₀ ≤ c) : bit0 c = c := --- add_eq_self h - --- @[simp] --- theorem bit0_lt_aleph0 {c : Cardinal} : bit0 c < ℵ₀ ↔ c < ℵ₀ := --- by simp [bit0, add_lt_aleph_0_iff] - --- @[simp] --- theorem aleph0_le_bit0 {c : Cardinal} : ℵ₀ ≤ bit0 c ↔ ℵ₀ ≤ c := by --- rw [← not_iff_not] --- simp - --- @[simp] --- theorem bit1_eq_self_iff {c : Cardinal} : bit1 c = c ↔ ℵ₀ ≤ c := by --- by_cases h : ℵ₀ ≤ c --- · simp only [bit1, bit0_eq_self h, h, eq_self_iff_true, add_one_of_aleph_0_le] --- · refine' iff_of_false (ne_of_gt _) h --- rcases lt_aleph_0.1 (not_le.1 h) with ⟨n, rfl⟩ --- norm_cast --- dsimp [bit1, bit0] --- linarith - --- @[simp] --- theorem bit1_lt_aleph0 {c : Cardinal} : bit1 c < ℵ₀ ↔ c < ℵ₀ := by --- simp [bit1, bit0, add_lt_aleph_0_iff, one_lt_aleph_0] - --- @[simp] --- theorem aleph0_le_bit1 {c : Cardinal} : ℵ₀ ≤ bit1 c ↔ ℵ₀ ≤ c := by --- rw [← not_iff_not] --- simp - --- @[simp] --- theorem bit0_le_bit0 {a b : Cardinal} : bit0 a ≤ bit0 b ↔ a ≤ b := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · rw [bit0_eq_self ha, bit0_eq_self hb] --- · rw [bit0_eq_self ha] --- refine' iff_of_false (fun h => _) (hb.trans_le ha).not_le --- have A : bit0 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans_le h) --- · rw [bit0_eq_self hb] --- exact iff_of_true ((bit0_lt_aleph_0.2 ha).le.trans hb) (ha.le.trans hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- exact bit0_le_bit0 - --- @[simp] --- theorem bit0_le_bit1 {a b : Cardinal} : bit0 a ≤ bit1 b ↔ a ≤ b := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · rw [bit0_eq_self ha, bit1_eq_self_iff.2 hb] --- · rw [bit0_eq_self ha] --- refine' iff_of_false (fun h => _) (hb.trans_le ha).not_le --- have A : bit1 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans_le h) --- · rw [bit1_eq_self_iff.2 hb] --- exact iff_of_true ((bit0_lt_aleph_0.2 ha).le.trans hb) (ha.le.trans hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- exact Nat.bit0_le_bit1_iff - --- @[simp] --- theorem bit1_le_bit1 {a b : Cardinal} : bit1 a ≤ bit1 b ↔ a ≤ b := --- ⟨fun h => bit0_le_bit1.1 ((self_le_add_right (bit0 a) 1).trans h), fun h => --- (add_le_add_right (add_le_add_left h a) 1).trans (add_le_add_right (add_le_add_right h b) 1)⟩ - --- @[simp] --- theorem bit1_le_bit0 {a b : Cardinal} : bit1 a ≤ bit0 b ↔ a < b ∨ a ≤ b ∧ ℵ₀ ≤ a := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · simp only [bit1_eq_self_iff.mpr ha, bit0_eq_self hb, ha, and_true_iff] --- refine' ⟨fun h => Or.inr h, fun h => _⟩ --- cases h --- · exact le_of_lt h --- · exact h --- · rw [bit1_eq_self_iff.2 ha] --- refine' iff_of_false (fun h => _) fun h => _ --- · have A : bit0 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans_le h) --- · exact not_le_of_lt (hb.trans_le ha) (h.elim le_of_lt And.left) --- · rw [bit0_eq_self hb] --- exact iff_of_true ((bit1_lt_aleph_0.2 ha).le.trans hb) (Or.inl <| ha.trans_le hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- simp [not_le.mpr ha] - --- @[simp] --- theorem bit0_lt_bit0 {a b : Cardinal} : bit0 a < bit0 b ↔ a < b := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · rw [bit0_eq_self ha, bit0_eq_self hb] --- · rw [bit0_eq_self ha] --- refine' iff_of_false (fun h => _) (hb.le.trans ha).not_lt --- have A : bit0 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans h) --- · rw [bit0_eq_self hb] --- exact iff_of_true ((bit0_lt_aleph_0.2 ha).trans_le hb) (ha.trans_le hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- exact bit0_lt_bit0 - --- @[simp] --- theorem bit1_lt_bit0 {a b : Cardinal} : bit1 a < bit0 b ↔ a < b := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · rw [bit1_eq_self_iff.2 ha, bit0_eq_self hb] --- · rw [bit1_eq_self_iff.2 ha] --- refine' iff_of_false (fun h => _) (hb.le.trans ha).not_lt --- have A : bit0 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans h) --- · rw [bit0_eq_self hb] --- exact iff_of_true ((bit1_lt_aleph_0.2 ha).trans_le hb) (ha.trans_le hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- exact Nat.bit1_lt_bit0_iff - --- @[simp] --- theorem bit1_lt_bit1 {a b : Cardinal} : bit1 a < bit1 b ↔ a < b := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · rw [bit1_eq_self_iff.2 ha, bit1_eq_self_iff.2 hb] --- · rw [bit1_eq_self_iff.2 ha] --- refine' iff_of_false (fun h => _) (hb.le.trans ha).not_lt --- have A : bit1 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans h) --- · rw [bit1_eq_self_iff.2 hb] --- exact iff_of_true ((bit1_lt_aleph_0.2 ha).trans_le hb) (ha.trans_le hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- exact bit1_lt_bit1 - --- @[simp] --- theorem bit0_lt_bit1 {a b : Cardinal} : bit0 a < bit1 b ↔ a < b ∨ a ≤ b ∧ a < ℵ₀ := by --- rcases le_or_lt ℵ₀ a with ha | ha <;> rcases le_or_lt ℵ₀ b with hb | hb --- · simp [bit0_eq_self ha, bit1_eq_self_iff.2 hb, not_lt.mpr ha] --- · rw [bit0_eq_self ha] --- refine' iff_of_false (fun h => _) fun h => _ --- · have A : bit1 b < ℵ₀ := by simpa using hb --- exact lt_irrefl _ ((A.trans_le ha).trans h) --- · exact (hb.trans_le ha).not_le (h.elim le_of_lt And.left) --- · rw [bit1_eq_self_iff.2 hb] --- exact iff_of_true ((bit0_lt_aleph_0.2 ha).trans_le hb) (Or.inl <| ha.trans_le hb) --- · rcases lt_aleph_0.1 ha with ⟨m, rfl⟩ --- rcases lt_aleph_0.1 hb with ⟨n, rfl⟩ --- norm_cast --- simp only [ha, and_true_iff, Nat.bit0_lt_bit1_iff, or_iff_right_of_imp le_of_lt] - --- theorem one_lt_two : (1 : Cardinal) < 2 := by --- -- This strategy works generally to prove inequalities between numerals in `cardinality`. --- norm_cast --- norm_num - --- @[simp] --- theorem one_lt_bit0 {a : Cardinal} : 1 < bit0 a ↔ 0 < a := by simp [← bit1_zero] - --- @[simp] --- theorem one_lt_bit1 (a : Cardinal) : 1 < bit1 a ↔ 0 < a := by simp [← bit1_zero] - --- end Bit +end extend end Cardinal -section Initial - -namespace Ordinal - -/-- -`ω_ o` is a notation for the *initial ordinal* of cardinality -`aleph o`. Thus, for example `ω_ 0 = ω`. --/ -scoped notation "ω_" o => ord <| aleph o - -/-- -`ω₁` is the first uncountable ordinal. --/ -scoped notation "ω₁" => ord <| aleph 1 - -lemma omega_lt_omega1 : ω < ω₁ := ord_aleph0.symm.trans_lt (ord_lt_ord.mpr (aleph0_lt_aleph_one)) - -section OrdinalIndices /-! ### Cardinal operations with ordinal indices Results on cardinality of ordinal-indexed families of sets. -/ + +namespace Ordinal namespace Cardinal open scoped Cardinal @@ -1467,9 +844,4 @@ lemma mk_iUnion_Ordinal_le_of_le {β : Type*} {o : Ordinal} {c : Cardinal} exact mul_le_mul' ho <| ciSup_le' <| (hA _ <| typein_lt_self ·) end Cardinal - -end OrdinalIndices - end Ordinal - -end Initial diff --git a/Mathlib/SetTheory/Cardinal/Basic.lean b/Mathlib/SetTheory/Cardinal/Basic.lean index 2a607f4838215..e6a0f29565545 100644 --- a/Mathlib/SetTheory/Cardinal/Basic.lean +++ b/Mathlib/SetTheory/Cardinal/Basic.lean @@ -6,6 +6,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Floris van Doorn import Mathlib.Data.Fintype.BigOperators import Mathlib.Data.Set.Countable import Mathlib.Logic.Small.Set +import Mathlib.Order.InitialSeg import Mathlib.Order.SuccPred.CompleteLinearOrder import Mathlib.SetTheory.Cardinal.SchroederBernstein import Mathlib.Algebra.Order.Ring.Nat @@ -79,7 +80,7 @@ Cantor's theorem, König's theorem, Konig's theorem assert_not_exists Field open Mathlib (Vector) -open Function Set Order +open Function Order Set noncomputable section @@ -305,12 +306,6 @@ we provide this statement separately so you don't have to solve the specializati theorem lift_mk_eq' {α : Type u} {β : Type v} : lift.{v} #α = lift.{u} #β ↔ Nonempty (α ≃ β) := lift_mk_eq.{u, v, 0} -@[simp] -theorem lift_le {a b : Cardinal.{v}} : lift.{u, v} a ≤ lift.{u, v} b ↔ a ≤ b := - inductionOn₂ a b fun α β => by - rw [← lift_umax] - exact lift_mk_le.{u} - -- Porting note: simpNF is not happy with universe levels. @[simp, nolint simpNF] theorem lift_mk_shrink (α : Type u) [Small.{v} α] : @@ -327,32 +322,48 @@ theorem lift_mk_shrink'' (α : Type max u v) [Small.{v} α] : Cardinal.lift.{u} #(Shrink.{v} α) = #α := by rw [← lift_umax', lift_mk_shrink.{max u v, v, 0} α, ← lift_umax, lift_id] +/-- `Cardinal.lift` as an `InitialSeg`. -/ +@[simps!] +def liftInitialSeg : Cardinal.{u} ≤i Cardinal.{max u v} := by + refine ⟨(OrderEmbedding.ofMapLEIff lift ?_).ltEmbedding, ?_⟩ <;> intro a b + · refine inductionOn₂ a b fun _ _ ↦ ?_ + rw [← lift_umax, lift_mk_le.{v, u, u}, le_def] + · refine inductionOn₂ a b fun α β h ↦ ?_ + obtain ⟨e⟩ := h.le + replace e := e.congr (Equiv.refl β) Equiv.ulift + refine ⟨#(range e), mk_congr (Equiv.ulift.trans <| Equiv.symm ?_)⟩ + apply (e.codRestrict _ mem_range_self).equivOfSurjective + rintro ⟨a, ⟨b, rfl⟩⟩ + exact ⟨b, rfl⟩ + +theorem mem_range_of_le_lift {a : Cardinal.{u}} {b : Cardinal.{max u v}} : + b ≤ lift.{v, u} a → b ∈ Set.range lift.{v, u} := + liftInitialSeg.mem_range_of_le + +@[deprecated mem_range_of_le_lift (since := "2024-10-07")] theorem lift_down {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b ≤ lift.{v,u} a → ∃ a', lift.{v,u} a' = b := - inductionOn₂ a b fun α β => by - rw [← lift_id #β, ← lift_umax, ← lift_umax.{u, v}, lift_mk_le.{v}] - exact fun ⟨f⟩ => - ⟨#(Set.range f), - Eq.symm <| lift_mk_eq.{_, _, v}.2 - ⟨Function.Embedding.equivOfSurjective (Embedding.codRestrict _ f Set.mem_range_self) - fun ⟨a, ⟨b, e⟩⟩ => ⟨b, Subtype.eq e⟩⟩⟩ - --- Porting note: changed `simps` to `simps!` because the linter told to do so. + b ≤ lift.{v, u} a → ∃ a', lift.{v, u} a' = b := + mem_range_of_le_lift + /-- `Cardinal.lift` as an `OrderEmbedding`. -/ -@[simps! (config := .asFn)] +@[deprecated Cardinal.liftInitialSeg (since := "2024-10-07")] def liftOrderEmbedding : Cardinal.{v} ↪o Cardinal.{max v u} := - OrderEmbedding.ofMapLEIff lift.{u, v} fun _ _ => lift_le + liftInitialSeg.toOrderEmbedding theorem lift_injective : Injective lift.{u, v} := - liftOrderEmbedding.injective + liftInitialSeg.injective @[simp] theorem lift_inj {a b : Cardinal.{u}} : lift.{v, u} a = lift.{v, u} b ↔ a = b := lift_injective.eq_iff +@[simp] +theorem lift_le {a b : Cardinal.{v}} : lift.{u} a ≤ lift.{u} b ↔ a ≤ b := + liftInitialSeg.le_iff_le + @[simp] theorem lift_lt {a b : Cardinal.{u}} : lift.{v, u} a < lift.{v, u} b ↔ a < b := - liftOrderEmbedding.lt_iff_lt + liftInitialSeg.lt_iff_lt theorem lift_strictMono : StrictMono lift := fun _ _ => lift_lt.2 @@ -374,18 +385,12 @@ theorem lift_umax_eq {a : Cardinal.{u}} {b : Cardinal.{v}} : rw [← lift_lift.{v, w, u}, ← lift_lift.{u, w, v}, lift_inj] theorem le_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b ≤ lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' ≤ a := - ⟨fun h => - let ⟨a', e⟩ := lift_down h - ⟨a', e, lift_le.1 <| e.symm ▸ h⟩, - fun ⟨_, e, h⟩ => e ▸ lift_le.2 h⟩ + b ≤ lift.{v, u} a ↔ ∃ a' ≤ a, lift.{v, u} a' = b := + liftInitialSeg.le_apply_iff theorem lt_lift_iff {a : Cardinal.{u}} {b : Cardinal.{max u v}} : - b < lift.{v, u} a ↔ ∃ a', lift.{v, u} a' = b ∧ a' < a := - ⟨fun h => - let ⟨a', e⟩ := lift_down h.le - ⟨a', e, lift_lt.1 <| e.symm ▸ h⟩, - fun ⟨_, e, h⟩ => e ▸ lift_lt.2 h⟩ + b < lift.{v, u} a ↔ ∃ a' < a, lift.{v, u} a' = b := + liftInitialSeg.lt_apply_iff /-! ### Basic cardinals -/ @@ -427,8 +432,8 @@ instance : One Cardinal.{u} := instance : Nontrivial Cardinal.{u} := ⟨⟨1, 0, mk_ne_zero _⟩⟩ -theorem mk_eq_one (α : Type u) [Unique α] : #α = 1 := - (Equiv.equivOfUnique α (ULift (Fin 1))).cardinal_eq +theorem mk_eq_one (α : Type u) [Subsingleton α] [Nonempty α] : #α = 1 := + let ⟨_⟩ := nonempty_unique α; (Equiv.equivOfUnique α (ULift (Fin 1))).cardinal_eq theorem le_one_iff_subsingleton {α : Type u} : #α ≤ 1 ↔ Subsingleton α := ⟨fun ⟨f⟩ => ⟨fun _ _ => f.injective (Subsingleton.elim _ _)⟩, fun ⟨h⟩ => @@ -784,7 +789,7 @@ theorem add_one_le_succ (c : Cardinal.{u}) : c + 1 ≤ succ c := by theorem lift_succ (a) : lift.{v, u} (succ a) = succ (lift.{v, u} a) := le_antisymm (le_of_not_gt fun h => by - rcases lt_lift_iff.1 h with ⟨b, e, h⟩ + rcases lt_lift_iff.1 h with ⟨b, h, e⟩ rw [lt_succ_iff, ← lift_le, e] at h exact h.not_lt (lt_succ _)) (succ_le_of_lt <| lift_lt.2 <| lt_succ a) @@ -847,6 +852,34 @@ theorem iSup_le_sum {ι} (f : ι → Cardinal) : iSup f ≤ sum f := theorem mk_sigma {ι} (f : ι → Type*) : #(Σ i, f i) = sum fun i => #(f i) := mk_congr <| Equiv.sigmaCongrRight fun _ => outMkEquiv.symm +theorem mk_sigma_congr_lift {ι : Type v} {ι' : Type v'} {f : ι → Type w} {g : ι' → Type w'} + (e : ι ≃ ι') (h : ∀ i, lift.{w'} #(f i) = lift.{w} #(g (e i))) : + lift.{max v' w'} #(Σ i, f i) = lift.{max v w} #(Σ i, g i) := + Cardinal.lift_mk_eq'.2 ⟨.sigmaCongr e fun i ↦ Classical.choice <| Cardinal.lift_mk_eq'.1 (h i)⟩ + +theorem mk_sigma_congr {ι ι' : Type u} {f : ι → Type v} {g : ι' → Type v} (e : ι ≃ ι') + (h : ∀ i, #(f i) = #(g (e i))) : #(Σ i, f i) = #(Σ i, g i) := + mk_congr <| Equiv.sigmaCongr e fun i ↦ Classical.choice <| Cardinal.eq.mp (h i) + +/-- Similar to `mk_sigma_congr` with indexing types in different universes. This is not a strict +generalization. -/ +theorem mk_sigma_congr' {ι : Type u} {ι' : Type v} {f : ι → Type max w (max u v)} + {g : ι' → Type max w (max u v)} (e : ι ≃ ι') + (h : ∀ i, #(f i) = #(g (e i))) : #(Σ i, f i) = #(Σ i, g i) := + mk_congr <| Equiv.sigmaCongr e fun i ↦ Classical.choice <| Cardinal.eq.mp (h i) + +theorem mk_sigma_congrRight {ι : Type u} {f g : ι → Type v} (h : ∀ i, #(f i) = #(g i)) : + #(Σ i, f i) = #(Σ i, g i) := + mk_sigma_congr (Equiv.refl ι) h + +theorem mk_psigma_congrRight {ι : Type u} {f g : ι → Type v} (h : ∀ i, #(f i) = #(g i)) : + #(Σ' i, f i) = #(Σ' i, g i) := + mk_congr <| .psigmaCongrRight fun i => Classical.choice <| Cardinal.eq.mp (h i) + +theorem mk_psigma_congrRight_prop {ι : Prop} {f g : ι → Type v} (h : ∀ i, #(f i) = #(g i)) : + #(Σ' i, f i) = #(Σ' i, g i) := + mk_congr <| .psigmaCongrRight fun i => Classical.choice <| Cardinal.eq.mp (h i) + theorem mk_sigma_arrow {ι} (α : Type*) (f : ι → Type*) : #(Sigma f → α) = #(Π i, f i → α) := mk_congr <| Equiv.piCurry fun _ _ ↦ α @@ -1006,7 +1039,7 @@ theorem lift_sSup {s : Set Cardinal} (hs : BddAbove s) : apply ((le_csSup_iff' (bddAbove_image.{_,u} _ hs)).2 fun c hc => _).antisymm (csSup_le' _) · intro c hc by_contra h - obtain ⟨d, rfl⟩ := Cardinal.lift_down (not_le.1 h).le + obtain ⟨d, rfl⟩ := Cardinal.mem_range_of_le_lift (not_le.1 h).le simp_rw [lift_le] at h hc rw [csSup_le_iff' hs] at h exact h fun a ha => lift_le.1 <| hc (mem_image_of_mem _ ha) @@ -1093,6 +1126,34 @@ def prod {ι : Type u} (f : ι → Cardinal) : Cardinal := theorem mk_pi {ι : Type u} (α : ι → Type v) : #(Π i, α i) = prod fun i => #(α i) := mk_congr <| Equiv.piCongrRight fun _ => outMkEquiv.symm +theorem mk_pi_congr_lift {ι : Type v} {ι' : Type v'} {f : ι → Type w} {g : ι' → Type w'} + (e : ι ≃ ι') (h : ∀ i, lift.{w'} #(f i) = lift.{w} #(g (e i))) : + lift.{max v' w'} #(Π i, f i) = lift.{max v w} #(Π i, g i) := + Cardinal.lift_mk_eq'.2 ⟨.piCongr e fun i ↦ Classical.choice <| Cardinal.lift_mk_eq'.1 (h i)⟩ + +theorem mk_pi_congr {ι ι' : Type u} {f : ι → Type v} {g : ι' → Type v} (e : ι ≃ ι') + (h : ∀ i, #(f i) = #(g (e i))) : #(Π i, f i) = #(Π i, g i) := + mk_congr <| Equiv.piCongr e fun i ↦ Classical.choice <| Cardinal.eq.mp (h i) + +theorem mk_pi_congr_prop {ι ι' : Prop} {f : ι → Type v} {g : ι' → Type v} (e : ι ↔ ι') + (h : ∀ i, #(f i) = #(g (e.mp i))) : #(Π i, f i) = #(Π i, g i) := + mk_congr <| Equiv.piCongr (.ofIff e) fun i ↦ Classical.choice <| Cardinal.eq.mp (h i) + +/-- Similar to `mk_pi_congr` with indexing types in different universes. This is not a strict +generalization. -/ +theorem mk_pi_congr' {ι : Type u} {ι' : Type v} {f : ι → Type max w (max u v)} + {g : ι' → Type max w (max u v)} (e : ι ≃ ι') + (h : ∀ i, #(f i) = #(g (e i))) : #(Π i, f i) = #(Π i, g i) := + mk_congr <| Equiv.piCongr e fun i ↦ Classical.choice <| Cardinal.eq.mp (h i) + +theorem mk_pi_congrRight {ι : Type u} {f g : ι → Type v} (h : ∀ i, #(f i) = #(g i)) : + #(Π i, f i) = #(Π i, g i) := + mk_pi_congr (Equiv.refl ι) h + +theorem mk_pi_congrRight_prop {ι : Prop} {f g : ι → Type v} (h : ∀ i, #(f i) = #(g i)) : + #(Π i, f i) = #(Π i, g i) := + mk_pi_congr_prop Iff.rfl h + @[simp] theorem prod_const (ι : Type u) (a : Cardinal.{v}) : (prod fun _ : ι => a) = lift.{u} a ^ lift.{v} #ι := @@ -1370,6 +1431,9 @@ lemma two_le_iff_one_lt {c : Cardinal} : 2 ≤ c ↔ 1 < c := by @[simp] theorem succ_zero : succ (0 : Cardinal) = 1 := by norm_cast +-- This works generally to prove inequalities between numeric cardinals. +theorem one_lt_two : (1 : Cardinal) < 2 := by norm_cast + theorem exists_finset_le_card (α : Type*) (n : ℕ) (h : n ≤ #α) : ∃ s : Finset α, n ≤ s.card := by obtain hα|hα := finite_or_infinite α @@ -1414,7 +1478,7 @@ theorem one_le_aleph0 : 1 ≤ ℵ₀ := theorem lt_aleph0 {c : Cardinal} : c < ℵ₀ ↔ ∃ n : ℕ, c = n := ⟨fun h => by - rcases lt_lift_iff.1 h with ⟨c, rfl, h'⟩ + rcases lt_lift_iff.1 h with ⟨c, h', rfl⟩ rcases le_mk_iff_exists_set.1 h'.1 with ⟨S, rfl⟩ suffices S.Finite by lift S to Finset ℕ using this diff --git a/Mathlib/SetTheory/Cardinal/Cofinality.lean b/Mathlib/SetTheory/Cardinal/Cofinality.lean index 035f8671aa50d..55b3d56e3120c 100644 --- a/Mathlib/SetTheory/Cardinal/Cofinality.lean +++ b/Mathlib/SetTheory/Cardinal/Cofinality.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: Mario Carneiro, Floris van Doorn, Violeta Hernández Palacios -/ -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.SetTheory.Ordinal.FixedPoint /-! @@ -680,11 +680,14 @@ theorem aleph_cof {o : Ordinal} (ho : o.IsLimit) : (aleph o).ord.cof = o.cof := aleph_isNormal.cof_eq ho @[simp] -theorem cof_omega : cof ω = ℵ₀ := - (aleph0_le_cof.2 omega_isLimit).antisymm' <| by - rw [← card_omega] +theorem cof_omega0 : cof ω = ℵ₀ := + (aleph0_le_cof.2 omega0_isLimit).antisymm' <| by + rw [← card_omega0] apply cof_le_card +@[deprecated (since := "2024-09-30")] +alias cof_omega := cof_omega0 + theorem cof_eq' (r : α → α → Prop) [IsWellOrder α r] (h : IsLimit (type r)) : ∃ S : Set α, (∀ a, ∃ b ∈ S, r a b) ∧ #S = cof (type r) := let ⟨S, H, e⟩ := cof_eq r @@ -709,7 +712,7 @@ theorem cof_univ : cof univ.{u, v} = Cardinal.univ.{u, v} := rcases @cof_eq Ordinal.{u} (· < ·) _ with ⟨S, H, Se⟩ rw [univ, ← lift_cof, ← Cardinal.lift_lift.{u+1, v, u}, Cardinal.lift_lt, ← Se] refine lt_of_not_ge fun h => ?_ - cases' Cardinal.lift_down h with a e + cases' Cardinal.mem_range_of_le_lift h with a e refine Quotient.inductionOn a (fun α e => ?_) e cases' Quotient.exact e with f have f := Equiv.ulift.symm.trans f diff --git a/Mathlib/SetTheory/Cardinal/Continuum.lean b/Mathlib/SetTheory/Cardinal/Continuum.lean index 9aeb9a15becb8..fa8694e0661e5 100644 --- a/Mathlib/SetTheory/Cardinal/Continuum.lean +++ b/Mathlib/SetTheory/Cardinal/Continuum.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.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic /-! # Cardinality of continuum diff --git a/Mathlib/SetTheory/Cardinal/CountableCover.lean b/Mathlib/SetTheory/Cardinal/CountableCover.lean index 65caa5dd364f5..16eb4b46b329c 100644 --- a/Mathlib/SetTheory/Cardinal/CountableCover.lean +++ b/Mathlib/SetTheory/Cardinal/CountableCover.lean @@ -3,7 +3,7 @@ Copyright (c) 2023 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.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.Order.Filter.Basic /-! diff --git a/Mathlib/SetTheory/Cardinal/Divisibility.lean b/Mathlib/SetTheory/Cardinal/Divisibility.lean index 4dac7f8531de2..6a176f3246b65 100644 --- a/Mathlib/SetTheory/Cardinal/Divisibility.lean +++ b/Mathlib/SetTheory/Cardinal/Divisibility.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Eric Rodriguez -/ import Mathlib.Algebra.IsPrimePow -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.Tactic.WLOG /-! diff --git a/Mathlib/SetTheory/Cardinal/Finite.lean b/Mathlib/SetTheory/Cardinal/Finite.lean index 1cd7eb9c7c18a..54b12ce1da78f 100644 --- a/Mathlib/SetTheory/Cardinal/Finite.lean +++ b/Mathlib/SetTheory/Cardinal/Finite.lean @@ -95,15 +95,19 @@ protected theorem bijective_iff_injective_and_card [Finite β] (f : α → β) : rw [← and_congr_right_iff, ← Bijective, card_eq_fintype_card, card_eq_fintype_card, Fintype.bijective_iff_injective_and_card] +#adaptation_note +/-- +After nightly-2024-09-06 we can remove the `_root_` prefixes below. +-/ protected theorem bijective_iff_surjective_and_card [Finite α] (f : α → β) : Bijective f ↔ Surjective f ∧ Nat.card α = Nat.card β := by classical - rw [and_comm, Bijective, and_congr_left_iff] + rw [_root_.and_comm, Bijective, and_congr_left_iff] intro h have := Fintype.ofFinite α have := Fintype.ofSurjective f h revert h - rw [← and_congr_left_iff, ← Bijective, ← and_comm, + rw [← and_congr_left_iff, ← Bijective, ← _root_.and_comm, card_eq_fintype_card, card_eq_fintype_card, Fintype.bijective_iff_surjective_and_card] theorem _root_.Function.Injective.bijective_of_nat_card_le [Finite β] {f : α → β} @@ -173,13 +177,13 @@ theorem card_of_subsingleton (a : α) [Subsingleton α] : Nat.card α = 1 := by letI := Fintype.ofSubsingleton a rw [card_eq_fintype_card, Fintype.card_ofSubsingleton a] --- @[simp] -- Porting note (#10618): simp can prove this -theorem card_unique [Unique α] : Nat.card α = 1 := - card_of_subsingleton default - theorem card_eq_one_iff_unique : Nat.card α = 1 ↔ Subsingleton α ∧ Nonempty α := Cardinal.toNat_eq_one_iff_unique +@[simp] +theorem card_unique [Nonempty α] [Subsingleton α] : Nat.card α = 1 := by + simp [card_eq_one_iff_unique, *] + theorem card_eq_one_iff_exists : Nat.card α = 1 ↔ ∃ x : α, ∀ y : α, y = x := by rw [card_eq_one_iff_unique] exact ⟨fun ⟨s, ⟨a⟩⟩ ↦ ⟨a, fun x ↦ s.elim x a⟩, fun ⟨x, h⟩ ↦ ⟨subsingleton_of_forall_eq x h, ⟨x⟩⟩⟩ diff --git a/Mathlib/SetTheory/Cardinal/Finsupp.lean b/Mathlib/SetTheory/Cardinal/Finsupp.lean index d62685c418254..b8d207a955820 100644 --- a/Mathlib/SetTheory/Cardinal/Finsupp.lean +++ b/Mathlib/SetTheory/Cardinal/Finsupp.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Violeta Hernández Palacios. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios, Junyan Xu -/ -import Mathlib.SetTheory.Cardinal.Ordinal +import Mathlib.SetTheory.Cardinal.Arithmetic import Mathlib.Data.Finsupp.Basic import Mathlib.Data.Finsupp.Multiset diff --git a/Mathlib/SetTheory/Game/Basic.lean b/Mathlib/SetTheory/Game/Basic.lean index f6b0a8b89caf6..8c72765907e52 100644 --- a/Mathlib/SetTheory/Game/Basic.lean +++ b/Mathlib/SetTheory/Game/Basic.lean @@ -238,7 +238,7 @@ theorem quot_natCast : ∀ n : ℕ, ⟦(n : PGame)⟧ = (n : Game) theorem quot_eq_of_mk'_quot_eq {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) (R : x.RightMoves ≃ y.RightMoves) (hl : ∀ i, (⟦x.moveLeft i⟧ : Game) = ⟦y.moveLeft (L i)⟧) (hr : ∀ j, (⟦x.moveRight j⟧ : Game) = ⟦y.moveRight (R j)⟧) : (⟦x⟧ : Game) = ⟦y⟧ := - game_eq (equiv_of_mk_equiv L R (fun _ => equiv_iff_game_eq.2 (hl _)) + game_eq (.of_equiv L R (fun _ => equiv_iff_game_eq.2 (hl _)) (fun _ => equiv_iff_game_eq.2 (hr _))) /-! Multiplicative operations can be defined at the level of pre-games, @@ -605,7 +605,7 @@ def mulOneRelabelling : ∀ x : PGame.{u}, x * 1 ≡r x (try rintro (⟨i, ⟨⟩⟩ | ⟨i, ⟨⟩⟩)) <;> { dsimp apply (Relabelling.subCongr (Relabelling.refl _) (mulZeroRelabelling _)).trans - rw [sub_zero] + rw [sub_zero_eq_add_zero] exact (addZeroRelabelling _).trans <| (((mulOneRelabelling _).addCongr (mulZeroRelabelling _)).trans <| addZeroRelabelling _) } diff --git a/Mathlib/SetTheory/Game/Birthday.lean b/Mathlib/SetTheory/Game/Birthday.lean index 016fd8366eb3a..c211b6f8b75e4 100644 --- a/Mathlib/SetTheory/Game/Birthday.lean +++ b/Mathlib/SetTheory/Game/Birthday.lean @@ -126,7 +126,7 @@ theorem le_birthday : ∀ x : PGame, x ≤ x.birthday.toPGame Or.inl ⟨toLeftMovesToPGame ⟨_, birthday_moveLeft_lt i⟩, by simp [le_birthday (xL i)]⟩, isEmptyElim⟩ -variable (a b x : PGame.{u}) +variable (x : PGame.{u}) theorem neg_birthday_le : -x.birthday.toPGame ≤ x := by simpa only [birthday_neg, ← neg_le_iff] using le_birthday (-x) diff --git a/Mathlib/SetTheory/Game/Nim.lean b/Mathlib/SetTheory/Game/Nim.lean index dea7c7401922c..f563fafa77d4b 100644 --- a/Mathlib/SetTheory/Game/Nim.lean +++ b/Mathlib/SetTheory/Game/Nim.lean @@ -218,6 +218,7 @@ theorem grundyValue_eq_sInf_moveLeft (G : PGame) : grundyValue G = sInf (Set.range (grundyValue ∘ G.moveLeft))ᶜ := by rw [grundyValue]; rfl +set_option linter.deprecated false in @[deprecated grundyValue_eq_sInf_moveLeft (since := "2024-09-16")] theorem grundyValue_eq_mex_left (G : PGame) : grundyValue G = Ordinal.mex fun i => grundyValue (G.moveLeft i) := @@ -302,6 +303,7 @@ theorem grundyValue_eq_sInf_moveRight (G : PGame) [G.Impartial] : ext i exact @grundyValue_neg _ (@Impartial.moveRight_impartial ⟨l, r, L, R⟩ _ _) +set_option linter.deprecated false in @[deprecated grundyValue_eq_sInf_moveRight (since := "2024-09-16")] theorem grundyValue_eq_mex_right (G : PGame) [G.Impartial] : grundyValue G = Ordinal.mex.{u, u} fun i => grundyValue (G.moveRight i) := @@ -343,7 +345,7 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m all_goals intro j have hj := toLeftMovesNim_symm_lt j - obtain ⟨k, hk⟩ := lt_omega.1 (hj.trans (nat_lt_omega _)) + obtain ⟨k, hk⟩ := lt_omega0.1 (hj.trans (nat_lt_omega0 _)) rw [hk, Nat.cast_lt] at hj have := hj.ne have := hj -- The termination checker doesn't work without this. @@ -354,7 +356,7 @@ theorem grundyValue_nim_add_nim (n m : ℕ) : grundyValue (nim.{u} n + nim.{u} m -- For any `k < n ^^^ m`, either `nim (k ^^^ m) + nim m` or `nim n + nim (k ^^^ n)` is a left -- option with Grundy value `k`. · intro k hk - obtain ⟨k, rfl⟩ := Ordinal.lt_omega.1 (hk.trans (Ordinal.nat_lt_omega _)) + obtain ⟨k, rfl⟩ := Ordinal.lt_omega0.1 (hk.trans (Ordinal.nat_lt_omega0 _)) rw [Set.mem_Iio, Nat.cast_lt] at hk obtain hk | hk := Nat.lt_xor_cases hk <;> rw [← natCast_lt] at hk · use toLeftMovesAdd (Sum.inl (toLeftMovesNim ⟨_, hk⟩)) diff --git a/Mathlib/SetTheory/Game/PGame.lean b/Mathlib/SetTheory/Game/PGame.lean index 94f9ebf8cd866..55a01998f3b98 100644 --- a/Mathlib/SetTheory/Game/PGame.lean +++ b/Mathlib/SetTheory/Game/PGame.lean @@ -822,13 +822,15 @@ theorem equiv_congr_right {x₁ x₂ : PGame} : (x₁ ≈ x₂) ↔ ∀ y₁, (x ⟨fun h _ => ⟨fun h' => Equiv.trans (Equiv.symm h) h', fun h' => Equiv.trans h h'⟩, fun h => (h x₂).2 <| equiv_rfl⟩ -theorem equiv_of_mk_equiv {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) +theorem Equiv.of_equiv {x y : PGame} (L : x.LeftMoves ≃ y.LeftMoves) (R : x.RightMoves ≃ y.RightMoves) (hl : ∀ i, x.moveLeft i ≈ y.moveLeft (L i)) (hr : ∀ j, x.moveRight j ≈ y.moveRight (R j)) : x ≈ y := by constructor <;> rw [le_def] · exact ⟨fun i => Or.inl ⟨_, (hl i).1⟩, fun j => Or.inr ⟨_, by simpa using (hr (R.symm j)).1⟩⟩ · exact ⟨fun i => Or.inl ⟨_, by simpa using (hl (L.symm i)).2⟩, fun j => Or.inr ⟨_, (hr j).2⟩⟩ +@[deprecated (since := "2024-09-26")] alias equiv_of_mk_equiv := Equiv.of_equiv + /-- The fuzzy, confused, or incomparable relation on pre-games. If `x ‖ 0`, then the first player can always win `x`. -/ @@ -1432,9 +1434,11 @@ instance : Sub PGame := ⟨fun x y => x + -y⟩ @[simp] -theorem sub_zero (x : PGame) : x - 0 = x + 0 := +theorem sub_zero_eq_add_zero (x : PGame) : x - 0 = x + 0 := show x + -0 = x + 0 by rw [neg_zero] +@[deprecated (since := "2024-09-26")] alias sub_zero := sub_zero_eq_add_zero + /-- If `w` has the same moves as `x` and `y` has the same moves as `z`, then `w - y` has the same moves as `x - z`. -/ def Relabelling.subCongr {w x y z : PGame} (h₁ : w ≡r x) (h₂ : y ≡r z) : w - y ≡r x - z := diff --git a/Mathlib/SetTheory/Game/Short.lean b/Mathlib/SetTheory/Game/Short.lean index 1d55f6247f452..03c8ecbda2c5b 100644 --- a/Mathlib/SetTheory/Game/Short.lean +++ b/Mathlib/SetTheory/Game/Short.lean @@ -136,7 +136,7 @@ def moveRightShort' {xl xr} (xL xR) [S : Short (mk xl xr xL xR)] (j : xr) : Shor attribute [local instance] moveRightShort' -theorem short_birthday (x : PGame.{u}) : [Short x] → x.birthday < Ordinal.omega := by +theorem short_birthday (x : PGame.{u}) : [Short x] → x.birthday < Ordinal.omega0 := by -- Porting note: Again `induction` is used instead of `pgame_wf_tac` induction x with | mk xl xr xL xR ihl ihr => diff --git a/Mathlib/SetTheory/Ordinal/Arithmetic.lean b/Mathlib/SetTheory/Ordinal/Arithmetic.lean index 3ad8ed13ca9bc..b974b8b6d0361 100644 --- a/Mathlib/SetTheory/Ordinal/Arithmetic.lean +++ b/Mathlib/SetTheory/Ordinal/Arithmetic.lean @@ -41,7 +41,6 @@ Some properties of the operations are also used to discuss general tools on ordi * `IsNormal`: a function `f : Ordinal → Ordinal` satisfies `IsNormal` if it is strictly increasing and order-continuous, i.e., the image `f o` of a limit ordinal `o` is the sup of `f a` for `a < o`. -* `enumOrd`: enumerates an unbounded set of ordinals by the ordinals themselves. * `sup`, `lsub`: the supremum / least strict upper bound of an indexed family of ordinals in `Type u`, as an ordinal in `Type u`. * `bsup`, `blsub`: the supremum / least strict upper bound of a set of ordinals indexed by ordinals @@ -62,8 +61,7 @@ universe u v w namespace Ordinal -variable {α : Type*} {β : Type*} {γ : Type*} {r : α → α → Prop} {s : β → β → Prop} - {t : γ → γ → Prop} +variable {α β γ : Type*} {r : α → α → Prop} {s : β → β → Prop} {t : γ → γ → Prop} /-! ### Further properties of addition on ordinals -/ @@ -79,38 +77,21 @@ theorem lift_succ (a : Ordinal.{v}) : lift.{u} (succ a) = succ (lift.{u} a) := b rw [← add_one_eq_succ, lift_add, lift_one] rfl -instance add_contravariantClass_le : ContravariantClass Ordinal.{u} Ordinal.{u} (· + ·) (· ≤ ·) := - ⟨fun a b c => - inductionOn a fun α r hr => - inductionOn b fun β₁ s₁ hs₁ => - inductionOn c fun β₂ s₂ hs₂ ⟨f⟩ => - ⟨have fl : ∀ a, f (Sum.inl a) = Sum.inl a := fun a => by - simpa only [InitialSeg.trans_apply, InitialSeg.leAdd_apply] using - @InitialSeg.eq _ _ _ _ _ - ((InitialSeg.leAdd r s₁).trans f) (InitialSeg.leAdd r s₂) a - have : ∀ b, { b' // f (Sum.inr b) = Sum.inr b' } := by - intro b; cases e : f (Sum.inr b) - · rw [← fl] at e - have := f.inj' e - contradiction - · exact ⟨_, rfl⟩ - let g (b) := (this b).1 - have fr : ∀ b, f (Sum.inr b) = Sum.inr (g b) := fun b => (this b).2 - ⟨⟨⟨g, fun x y h => by - injection f.inj' (by rw [fr, fr, h] : f (Sum.inr x) = f (Sum.inr y))⟩, - @fun a b => by - -- Porting note: - -- `relEmbedding.coe_fn_to_embedding` & `initial_seg.coe_fn_to_rel_embedding` - -- → `InitialSeg.coe_coe_fn` - simpa only [Sum.lex_inr_inr, fr, InitialSeg.coe_coe_fn, Embedding.coeFn_mk] using - @RelEmbedding.map_rel_iff _ _ _ _ f.toRelEmbedding (Sum.inr a) (Sum.inr b)⟩, - fun a b H => by - rcases f.mem_range_of_rel (by rw [fr] <;> exact Sum.lex_inr_inr.2 H) with - ⟨a' | a', h⟩ - · rw [fl] at h - cases h - · rw [fr] at h - exact ⟨a', Sum.inr.inj h⟩⟩⟩⟩ +instance add_contravariantClass_le : + ContravariantClass Ordinal.{u} Ordinal.{u} (· + ·) (· ≤ ·) where + elim c a b := by + refine inductionOn₃ a b c fun α r _ β s _ γ t _ ⟨f⟩ ↦ ?_ + have H₁ a : f (Sum.inl a) = Sum.inl a := by + simpa using ((InitialSeg.leAdd t r).trans f).eq (InitialSeg.leAdd t s) a + have H₂ a : ∃ b, f (Sum.inr a) = Sum.inr b := by + generalize hx : f (Sum.inr a) = x + obtain x | x := x + · rw [← H₁, f.inj] at hx + contradiction + · exact ⟨x, rfl⟩ + choose g hg using H₂ + refine (RelEmbedding.ofMonotone g fun _ _ h ↦ ?_).ordinal_type_le + rwa [← @Sum.lex_inr_inr _ t _ s, ← hg, ← hg, f.map_rel_iff, Sum.lex_inr_inr] theorem add_left_cancel (a) {b c : Ordinal} : a + b = a + c ↔ b = c := by simp only [le_antisymm_iff, add_le_add_iff_left] @@ -119,14 +100,14 @@ private theorem add_lt_add_iff_left' (a) {b c : Ordinal} : a + b < a + c ↔ b < rw [← not_le, ← not_le, add_le_add_iff_left] instance add_covariantClass_lt : CovariantClass Ordinal.{u} Ordinal.{u} (· + ·) (· < ·) := - ⟨fun a _b _c => (add_lt_add_iff_left' a).2⟩ + ⟨fun a _b _c ↦ (add_lt_add_iff_left' a).2⟩ instance add_contravariantClass_lt : ContravariantClass Ordinal.{u} Ordinal.{u} (· + ·) (· < ·) := - ⟨fun a _b _c => (add_lt_add_iff_left' a).1⟩ + ⟨fun a _b _c ↦ (add_lt_add_iff_left' a).1⟩ instance add_swap_contravariantClass_lt : ContravariantClass Ordinal.{u} Ordinal.{u} (swap (· + ·)) (· < ·) := - ⟨fun _a _b _c => lt_imp_lt_of_le_imp_le fun h => add_le_add_right h _⟩ + ⟨fun _a _b _c ↦ lt_imp_lt_of_le_imp_le fun h => add_le_add_right h _⟩ theorem add_le_add_iff_right {a b : Ordinal} : ∀ n : ℕ, a + n ≤ b + n ↔ a ≤ b | 0 => by simp @@ -137,10 +118,9 @@ theorem add_right_cancel {a b : Ordinal} (n : ℕ) : a + n = b + n ↔ a = b := simp only [le_antisymm_iff, add_le_add_iff_right] theorem add_eq_zero_iff {a b : Ordinal} : a + b = 0 ↔ a = 0 ∧ b = 0 := - inductionOn a fun α r _ => - inductionOn b fun β s _ => by - simp_rw [← type_sum_lex, type_eq_zero_iff_isEmpty] - exact isEmpty_sum + inductionOn₂ a b fun α r _ β s _ => by + simp_rw [← type_sum_lex, type_eq_zero_iff_isEmpty] + exact isEmpty_sum theorem left_eq_zero_of_add_eq_zero {a b : Ordinal} (h : a + b = 0) : a = 0 := (add_eq_zero_iff.1 h).1 @@ -305,6 +285,34 @@ theorem limitRecOn_limit {C} (o H₁ H₂ H₃ h) : @limitRecOn C o H₁ H₂ H₃ = H₃ o h fun x _h => @limitRecOn C x H₁ H₂ H₃ := by simp_rw [limitRecOn, SuccOrder.prelimitRecOn_of_isSuccPrelimit _ _ h.isSuccPrelimit, dif_neg h.1] +/-- Bounded recursion on ordinals. Similar to `limitRecOn`, with the assumption `o < l` + added to all cases. The final term's domain is the ordinals below `l`. -/ +@[elab_as_elim] +def boundedLimitRecOn {l : Ordinal} (lLim : l.IsLimit) {C : Iio l → Sort*} (o : Iio l) + (H₁ : C ⟨0, lLim.pos⟩) (H₂ : (o : Iio l) → C o → C ⟨succ o, lLim.succ_lt o.2⟩) + (H₃ : (o : Iio l) → IsLimit o → (Π o' < o, C o') → C o) : C o := + limitRecOn (C := fun p ↦ (h : p < l) → C ⟨p, h⟩) o.1 (fun _ ↦ H₁) + (fun o ih h ↦ H₂ ⟨o, _⟩ <| ih <| (lt_succ o).trans h) + (fun _o ho ih _ ↦ H₃ _ ho fun _o' h ↦ ih _ h _) o.2 + +@[simp] +theorem boundedLimitRec_zero {l} (lLim : l.IsLimit) {C} (H₁ H₂ H₃) : + @boundedLimitRecOn l lLim C ⟨0, lLim.pos⟩ H₁ H₂ H₃ = H₁ := by + rw [boundedLimitRecOn, limitRecOn_zero] + +@[simp] +theorem boundedLimitRec_succ {l} (lLim : l.IsLimit) {C} (o H₁ H₂ H₃) : + @boundedLimitRecOn l lLim C ⟨succ o.1, lLim.succ_lt o.2⟩ H₁ H₂ H₃ = H₂ o + (@boundedLimitRecOn l lLim C o H₁ H₂ H₃) := by + rw [boundedLimitRecOn, limitRecOn_succ] + rfl + +theorem boundedLimitRec_limit {l} (lLim : l.IsLimit) {C} (o H₁ H₂ H₃ oLim) : + @boundedLimitRecOn l lLim C o H₁ H₂ H₃ = H₃ o oLim (fun x _ ↦ + @boundedLimitRecOn l lLim C x H₁ H₂ H₃) := by + rw [boundedLimitRecOn, limitRecOn_limit] + rfl + instance orderTopToTypeSucc (o : Ordinal) : OrderTop (succ o).toType := @OrderTop.mk _ _ (Top.mk _) le_enum_succ @@ -334,16 +342,28 @@ theorem bounded_singleton {r : α → α → Prop} [IsWellOrder α r] (hr : (typ rw [@enum_lt_enum _ r, Subtype.mk_lt_mk] apply lt_succ --- Porting note: `· < ·` requires a type ascription for an `IsWellOrder` instance. -theorem type_subrel_lt (o : Ordinal.{u}) : - type (@Subrel Ordinal (· < ·) { o' : Ordinal | o' < o }) = Ordinal.lift.{u + 1} o := by +@[simp] +theorem typein_ordinal (o : Ordinal.{u}) : + @typein Ordinal (· < ·) _ o = Ordinal.lift.{u + 1} o := by refine Quotient.inductionOn o ?_ rintro ⟨α, r, wo⟩; apply Quotient.sound constructor; refine ((RelIso.preimage Equiv.ulift r).trans (enum r).symm).symm +-- Porting note: `· < ·` requires a type ascription for an `IsWellOrder` instance. +@[deprecated typein_ordinal (since := "2024-09-19")] +theorem type_subrel_lt (o : Ordinal.{u}) : + type (@Subrel Ordinal (· < ·) { o' : Ordinal | o' < o }) = Ordinal.lift.{u + 1} o := + typein_ordinal o + +theorem mk_Iio_ordinal (o : Ordinal.{u}) : + #(Iio o) = Cardinal.lift.{u + 1} o.card := by + rw [lift_card, ← typein_ordinal] + rfl + +@[deprecated mk_Iio_ordinal (since := "2024-09-19")] theorem mk_initialSeg (o : Ordinal.{u}) : - #{ o' : Ordinal | o' < o } = Cardinal.lift.{u + 1} o.card := by - rw [lift_card, ← type_subrel_lt, card_type] + #{ o' : Ordinal | o' < o } = Cardinal.lift.{u + 1} o.card := mk_Iio_ordinal o + /-! ### Normal ordinal functions -/ @@ -540,9 +560,9 @@ theorem sub_isLimit {a b} (l : IsLimit a) (h : b < a) : IsLimit (a - b) := rw [lt_sub, add_succ]; exact l.2 _ (lt_sub.1 h)⟩ -- @[simp] -- Porting note (#10618): simp can prove this -theorem one_add_omega : 1 + ω = ω := by +theorem one_add_omega0 : 1 + ω = ω := by refine le_antisymm ?_ (le_add_left _ _) - rw [omega, ← lift_one.{0}, ← lift_add, lift_le, ← type_unit, ← type_sum_lex] + rw [omega0, ← lift_one.{0}, ← lift_add, lift_le, ← type_unit, ← type_sum_lex] refine ⟨RelEmbedding.collapse (RelEmbedding.ofMonotone ?_ ?_)⟩ · apply Sum.rec · exact fun _ => 0 @@ -551,9 +571,15 @@ theorem one_add_omega : 1 + ω = ω := by cases a <;> cases b <;> intro H <;> cases' H with _ _ H _ _ H <;> [exact H.elim; exact Nat.succ_pos _; exact Nat.succ_lt_succ H] +@[deprecated (since := "2024-09-30")] +alias one_add_omega := one_add_omega0 + @[simp] -theorem one_add_of_omega_le {o} (h : ω ≤ o) : 1 + o = o := by - rw [← Ordinal.add_sub_cancel_of_le h, ← add_assoc, one_add_omega] +theorem one_add_of_omega0_le {o} (h : ω ≤ o) : 1 + o = o := by + rw [← Ordinal.add_sub_cancel_of_le h, ← add_assoc, one_add_omega0] + +@[deprecated (since := "2024-09-30")] +alias one_add_of_omega_le := one_add_of_omega0_le /-! ### Multiplication of ordinals -/ @@ -1340,6 +1366,22 @@ theorem iSup_ord {ι} {f : ι → Cardinal} (hf : BddAbove (range f)) : conv_lhs => change range (ord ∘ f) rw [range_comp] +theorem sInf_compl_lt_lift_ord_succ {ι : Type u} (f : ι → Ordinal.{max u v}) : + sInf (range f)ᶜ < lift.{v} (succ #ι).ord := by + by_contra! h + have : Iio (lift.{v} (succ #ι).ord) ⊆ range f := by + intro o ho + have := not_mem_of_lt_csInf' (ho.trans_le h) + rwa [not_mem_compl_iff] at this + have := mk_le_mk_of_subset this + rw [mk_Iio_ordinal, ← lift_card, Cardinal.lift_lift, card_ord, Cardinal.lift_succ, + succ_le_iff, ← Cardinal.lift_id'.{u, max (u + 1) (v + 1)} #_] at this + exact this.not_le mk_range_le_lift + +theorem sInf_compl_lt_ord_succ {ι : Type u} (f : ι → Ordinal.{u}) : + sInf (range f)ᶜ < (succ #ι).ord := + lift_id (succ #ι).ord ▸ sInf_compl_lt_lift_ord_succ f + -- TODO: remove `bsup` in favor of `iSup` in a future refactor. section bsup @@ -1885,30 +1927,38 @@ set_option linter.deprecated false /-- The minimum excluded ordinal in a family of ordinals. -/ +@[deprecated "use sInf sᶜ instead" (since := "2024-09-20")] def mex {ι : Type u} (f : ι → Ordinal.{max u v}) : Ordinal := sInf (Set.range f)ᶜ +@[deprecated (since := "2024-09-20")] theorem mex_not_mem_range {ι : Type u} (f : ι → Ordinal.{max u v}) : mex.{_, v} f ∉ Set.range f := csInf_mem (nonempty_compl_range.{_, v} f) +@[deprecated (since := "2024-09-20")] theorem le_mex_of_forall {ι : Type u} {f : ι → Ordinal.{max u v}} {a : Ordinal} (H : ∀ b < a, ∃ i, f i = b) : a ≤ mex.{_, v} f := by by_contra! h exact mex_not_mem_range f (H _ h) +@[deprecated (since := "2024-09-20")] theorem ne_mex {ι : Type u} (f : ι → Ordinal.{max u v}) : ∀ i, f i ≠ mex.{_, v} f := by simpa using mex_not_mem_range.{_, v} f +@[deprecated (since := "2024-09-20")] theorem mex_le_of_ne {ι} {f : ι → Ordinal} {a} (ha : ∀ i, f i ≠ a) : mex f ≤ a := csInf_le' (by simp [ha]) +@[deprecated (since := "2024-09-20")] theorem exists_of_lt_mex {ι} {f : ι → Ordinal} {a} (ha : a < mex f) : ∃ i, f i = a := by by_contra! ha' exact ha.not_le (mex_le_of_ne ha') +@[deprecated (since := "2024-09-20")] theorem mex_le_lsub {ι : Type u} (f : ι → Ordinal.{max u v}) : mex.{_, v} f ≤ lsub.{_, v} f := csInf_le' (lsub_not_mem_range f) +@[deprecated (since := "2024-09-20")] theorem mex_monotone {α β : Type u} {f : α → Ordinal.{max u v}} {g : β → Ordinal.{max u v}} (h : Set.range f ⊆ Set.range g) : mex.{_, v} f ≤ mex.{_, v} g := by refine mex_le_of_ne fun i hi => ?_ @@ -1916,6 +1966,7 @@ theorem mex_monotone {α β : Type u} {f : α → Ordinal.{max u v}} {g : β → rw [← hj] at hi exact ne_mex g j hi +@[deprecated sInf_compl_lt_ord_succ (since := "2024-09-20")] theorem mex_lt_ord_succ_mk {ι : Type u} (f : ι → Ordinal.{u}) : mex.{_, u} f < (succ #ι).ord := by by_contra! h @@ -1936,18 +1987,22 @@ theorem mex_lt_ord_succ_mk {ι : Type u} (f : ι → Ordinal.{u}) : `familyOfBFamily`. This is to `mex` as `bsup` is to `sup`. -/ +@[deprecated "use sInf sᶜ instead" (since := "2024-09-20")] def bmex (o : Ordinal) (f : ∀ a < o, Ordinal) : Ordinal := mex (familyOfBFamily o f) +@[deprecated (since := "2024-09-20")] theorem bmex_not_mem_brange {o : Ordinal} (f : ∀ a < o, Ordinal) : bmex o f ∉ brange o f := by rw [← range_familyOfBFamily] apply mex_not_mem_range +@[deprecated (since := "2024-09-20")] theorem le_bmex_of_forall {o : Ordinal} (f : ∀ a < o, Ordinal) {a : Ordinal} (H : ∀ b < a, ∃ i hi, f i hi = b) : a ≤ bmex o f := by by_contra! h exact bmex_not_mem_brange f (H _ h) +@[deprecated (since := "2024-09-20")] theorem ne_bmex {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) {i} (hi) : f i hi ≠ bmex.{_, v} o f := by convert (config := {transparency := .default}) @@ -1955,24 +2010,29 @@ theorem ne_bmex {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) {i} (hi) : -- Porting note: `familyOfBFamily_enum` → `typein_enum` rw [typein_enum] +@[deprecated (since := "2024-09-20")] theorem bmex_le_of_ne {o : Ordinal} {f : ∀ a < o, Ordinal} {a} (ha : ∀ i hi, f i hi ≠ a) : bmex o f ≤ a := mex_le_of_ne fun _i => ha _ _ +@[deprecated (since := "2024-09-20")] theorem exists_of_lt_bmex {o : Ordinal} {f : ∀ a < o, Ordinal} {a} (ha : a < bmex o f) : ∃ i hi, f i hi = a := by cases' exists_of_lt_mex ha with i hi exact ⟨_, typein_lt_self i, hi⟩ +@[deprecated (since := "2024-09-20")] theorem bmex_le_blsub {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{max u v}) : bmex.{_, v} o f ≤ blsub.{_, v} o f := mex_le_lsub _ +@[deprecated (since := "2024-09-20")] theorem bmex_monotone {o o' : Ordinal.{u}} {f : ∀ a < o, Ordinal.{max u v}} {g : ∀ a < o', Ordinal.{max u v}} (h : brange o f ⊆ brange o' g) : bmex.{_, v} o f ≤ bmex.{_, v} o' g := mex_monotone (by rwa [range_familyOfBFamily, range_familyOfBFamily]) +@[deprecated sInf_compl_lt_ord_succ (since := "2024-09-20")] theorem bmex_lt_ord_succ_card {o : Ordinal.{u}} (f : ∀ a < o, Ordinal.{u}) : bmex.{_, u} o f < (succ o.card).ord := by rw [← mk_toType] @@ -2010,134 +2070,11 @@ theorem Ordinal.not_bddAbove_compl_of_small (s : Set Ordinal.{u}) [hs : Small.{u rw [union_compl_self, small_univ_iff] at this exact not_small_ordinal this -/-! ### Enumerating unbounded sets of ordinals with ordinals -/ +/-! ### Casting naturals into ordinals, compatibility with operations -/ namespace Ordinal -section - -/-- Enumerator function for an unbounded set of ordinals. -/ -def enumOrd (S : Set Ordinal.{u}) : Ordinal → Ordinal := - lt_wf.fix fun o f => sInf (S ∩ Set.Ici (blsub.{u, u} o f)) - -variable {S : Set Ordinal.{u}} - -/-- The equation that characterizes `enumOrd` definitionally. This isn't the nicest expression to - work with, so consider using `enumOrd_def` instead. -/ -theorem enumOrd_def' (o) : - enumOrd S o = sInf (S ∩ Set.Ici (blsub.{u, u} o fun a _ => enumOrd S a)) := - lt_wf.fix_eq _ _ - -/-- The set in `enumOrd_def'` is nonempty. -/ -theorem enumOrd_def'_nonempty (hS : Unbounded (· < ·) S) (a) : (S ∩ Set.Ici a).Nonempty := - let ⟨b, hb, hb'⟩ := hS a - ⟨b, hb, le_of_not_gt hb'⟩ - -private theorem enumOrd_mem_aux (hS : Unbounded (· < ·) S) (o) : - enumOrd S o ∈ S ∩ Set.Ici (blsub.{u, u} o fun c _ => enumOrd S c) := by - rw [enumOrd_def'] - exact csInf_mem (enumOrd_def'_nonempty hS _) - -theorem enumOrd_mem (hS : Unbounded (· < ·) S) (o) : enumOrd S o ∈ S := - (enumOrd_mem_aux hS o).left - -theorem blsub_le_enumOrd (hS : Unbounded (· < ·) S) (o) : - (blsub.{u, u} o fun c _ => enumOrd S c) ≤ enumOrd S o := - (enumOrd_mem_aux hS o).right - -theorem enumOrd_strictMono (hS : Unbounded (· < ·) S) : StrictMono (enumOrd S) := fun _ _ h => - (lt_blsub.{u, u} _ _ h).trans_le (blsub_le_enumOrd hS _) - -/-- A more workable definition for `enumOrd`. -/ -theorem enumOrd_def (o) : enumOrd S o = sInf (S ∩ { b | ∀ c, c < o → enumOrd S c < b }) := by - rw [enumOrd_def'] - congr; ext - exact ⟨fun h a hao => (lt_blsub.{u, u} _ _ hao).trans_le h, blsub_le⟩ - -/-- The set in `enumOrd_def` is nonempty. -/ -theorem enumOrd_def_nonempty (hS : Unbounded (· < ·) S) {o} : - { x | x ∈ S ∧ ∀ c, c < o → enumOrd S c < x }.Nonempty := - ⟨_, enumOrd_mem hS o, fun _ b => enumOrd_strictMono hS b⟩ - -@[simp] -theorem enumOrd_range {f : Ordinal → Ordinal} (hf : StrictMono f) : enumOrd (range f) = f := - funext fun o => by - apply Ordinal.induction o - intro a H - rw [enumOrd_def a] - have Hfa : f a ∈ range f ∩ { b | ∀ c, c < a → enumOrd (range f) c < b } := - ⟨mem_range_self a, fun b hb => by - rw [H b hb] - exact hf hb⟩ - refine (csInf_le' Hfa).antisymm ((le_csInf_iff'' ⟨_, Hfa⟩).2 ?_) - rintro _ ⟨⟨c, rfl⟩, hc : ∀ b < a, enumOrd (range f) b < f c⟩ - rw [hf.le_iff_le] - contrapose! hc - exact ⟨c, hc, (H c hc).ge⟩ - -@[simp] -theorem enumOrd_univ : enumOrd Set.univ = id := by - rw [← range_id] - exact enumOrd_range strictMono_id - -@[simp] -theorem enumOrd_zero : enumOrd S 0 = sInf S := by - rw [enumOrd_def] - simp [Ordinal.not_lt_zero] - -theorem enumOrd_succ_le {a b} (hS : Unbounded (· < ·) S) (ha : a ∈ S) (hb : enumOrd S b < a) : - enumOrd S (succ b) ≤ a := by - rw [enumOrd_def] - exact - csInf_le' ⟨ha, fun c hc => ((enumOrd_strictMono hS).monotone (le_of_lt_succ hc)).trans_lt hb⟩ - -theorem enumOrd_le_of_subset {S T : Set Ordinal} (hS : Unbounded (· < ·) S) (hST : S ⊆ T) (a) : - enumOrd T a ≤ enumOrd S a := by - apply Ordinal.induction a - intro b H - rw [enumOrd_def] - exact csInf_le' ⟨hST (enumOrd_mem hS b), fun c h => (H c h).trans_lt (enumOrd_strictMono hS h)⟩ - -theorem enumOrd_surjective (hS : Unbounded (· < ·) S) : ∀ s ∈ S, ∃ a, enumOrd S a = s := fun s hs => - ⟨sSup { a | enumOrd S a ≤ s }, by - apply le_antisymm - · rw [enumOrd_def] - refine csInf_le' ⟨hs, fun a ha => ?_⟩ - have : enumOrd S 0 ≤ s := by - rw [enumOrd_zero] - exact csInf_le' hs - -- Porting note: `flip` is required to infer a metavariable. - rcases flip exists_lt_of_lt_csSup ha ⟨0, this⟩ with ⟨b, hb, hab⟩ - exact (enumOrd_strictMono hS hab).trans_le hb - · by_contra! h - exact (le_csSup ⟨s, fun a => ((enumOrd_strictMono hS).id_le a).trans⟩ - (enumOrd_succ_le hS hs h)).not_lt (lt_succ _)⟩ - -/-- An order isomorphism between an unbounded set of ordinals and the ordinals. -/ -def enumOrdOrderIso (hS : Unbounded (· < ·) S) : Ordinal ≃o S := - StrictMono.orderIsoOfSurjective (fun o => ⟨_, enumOrd_mem hS o⟩) (enumOrd_strictMono hS) fun s => - let ⟨a, ha⟩ := enumOrd_surjective hS s s.prop - ⟨a, Subtype.eq ha⟩ - -theorem range_enumOrd (hS : Unbounded (· < ·) S) : range (enumOrd S) = S := by - rw [range_eq_iff] - exact ⟨enumOrd_mem hS, enumOrd_surjective hS⟩ - -/-- A characterization of `enumOrd`: it is the unique strict monotonic function with range `S`. -/ -theorem eq_enumOrd (f : Ordinal → Ordinal) (hS : Unbounded (· < ·) S) : - StrictMono f ∧ range f = S ↔ f = enumOrd S := by - constructor - · rintro ⟨h₁, h₂⟩ - rwa [← h₁.range_inj (enumOrd_strictMono hS), range_enumOrd hS] - · rintro rfl - exact ⟨enumOrd_strictMono hS, range_enumOrd hS⟩ - -end - -/-! ### Casting naturals into ordinals, compatibility with operations -/ - - @[simp] theorem one_add_natCast (m : ℕ) : 1 + (m : Ordinal) = succ m := by rw [← Nat.cast_one, ← Nat.cast_add, add_comm] @@ -2251,7 +2188,7 @@ theorem lift_ofNat (n : ℕ) [n.AtLeastTwo] : end Ordinal -/-! ### Properties of `omega` -/ +/-! ### Properties of ω -/ namespace Cardinal @@ -2268,7 +2205,7 @@ theorem ord_aleph0 : ord.{u} ℵ₀ = ω := @[simp] theorem add_one_of_aleph0_le {c} (h : ℵ₀ ≤ c) : c + 1 = c := by - rw [add_comm, ← card_ord c, ← card_one, ← card_add, one_add_of_omega_le] + rw [add_comm, ← card_ord c, ← card_one, ← card_add, one_add_of_omega0_le] rwa [← ord_aleph0, ord_le_ord] end Cardinal @@ -2280,34 +2217,56 @@ theorem lt_add_of_limit {a b c : Ordinal.{u}} (h : IsLimit c) : -- Porting note: `bex_def` is required. rw [← IsNormal.bsup_eq.{u, u} (add_isNormal b) h, lt_bsup, bex_def] -theorem lt_omega {o : Ordinal} : o < ω ↔ ∃ n : ℕ, o = n := by +theorem lt_omega0 {o : Ordinal} : o < ω ↔ ∃ n : ℕ, o = n := by simp_rw [← Cardinal.ord_aleph0, Cardinal.lt_ord, lt_aleph0, card_eq_nat] -theorem nat_lt_omega (n : ℕ) : ↑n < ω := - lt_omega.2 ⟨_, rfl⟩ +@[deprecated (since := "2024-09-30")] +alias lt_omega := lt_omega0 + +theorem nat_lt_omega0 (n : ℕ) : ↑n < ω := + lt_omega0.2 ⟨_, rfl⟩ + +@[deprecated (since := "2024-09-30")] +alias nat_lt_omega := nat_lt_omega0 +theorem omega0_pos : 0 < ω := + nat_lt_omega0 0 + +@[deprecated (since := "2024-09-30")] theorem omega_pos : 0 < ω := - nat_lt_omega 0 + nat_lt_omega0 0 + +theorem omega0_ne_zero : ω ≠ 0 := + omega0_pos.ne' + +@[deprecated (since := "2024-09-30")] +alias omega_ne_zero := omega0_ne_zero + +theorem one_lt_omega0 : 1 < ω := by simpa only [Nat.cast_one] using nat_lt_omega0 1 -theorem omega_ne_zero : ω ≠ 0 := - omega_pos.ne' +@[deprecated (since := "2024-09-30")] +alias one_lt_omega := one_lt_omega0 -theorem one_lt_omega : 1 < ω := by simpa only [Nat.cast_one] using nat_lt_omega 1 +theorem omega0_isLimit : IsLimit ω := + ⟨omega0_ne_zero, fun o h => by + let ⟨n, e⟩ := lt_omega0.1 h + rw [e]; exact nat_lt_omega0 (n + 1)⟩ -theorem omega_isLimit : IsLimit ω := - ⟨omega_ne_zero, fun o h => by - let ⟨n, e⟩ := lt_omega.1 h - rw [e]; exact nat_lt_omega (n + 1)⟩ +@[deprecated (since := "2024-09-30")] +alias omega_isLimit := omega0_isLimit -theorem omega_le {o : Ordinal} : ω ≤ o ↔ ∀ n : ℕ, ↑n ≤ o := - ⟨fun h n => (nat_lt_omega _).le.trans h, fun H => +theorem omega0_le {o : Ordinal} : ω ≤ o ↔ ∀ n : ℕ, ↑n ≤ o := + ⟨fun h n => (nat_lt_omega0 _).le.trans h, fun H => le_of_forall_lt fun a h => by - let ⟨n, e⟩ := lt_omega.1 h + let ⟨n, e⟩ := lt_omega0.1 h rw [e, ← succ_le_iff]; exact H (n + 1)⟩ +@[deprecated (since := "2024-09-30")] +alias omega_le := omega0_le + @[simp] theorem iSup_natCast : iSup Nat.cast = ω := - (Ordinal.iSup_le fun n => (nat_lt_omega n).le).antisymm <| omega_le.2 <| Ordinal.le_iSup _ + (Ordinal.iSup_le fun n => (nat_lt_omega0 n).le).antisymm <| omega0_le.2 <| Ordinal.le_iSup _ set_option linter.deprecated false in @[deprecated iSup_natCast (since := "2024-04-17")] @@ -2321,24 +2280,30 @@ theorem nat_lt_limit {o} (h : IsLimit o) : ∀ n : ℕ, ↑n < o | 0 => lt_of_le_of_ne (Ordinal.zero_le o) h.1.symm | n + 1 => h.2 _ (nat_lt_limit h n) -theorem omega_le_of_isLimit {o} (h : IsLimit o) : ω ≤ o := - omega_le.2 fun n => le_of_lt <| nat_lt_limit h n +theorem omega0_le_of_isLimit {o} (h : IsLimit o) : ω ≤ o := + omega0_le.2 fun n => le_of_lt <| nat_lt_limit h n + +@[deprecated (since := "2024-09-30")] +alias omega_le_of_isLimit := omega0_le_of_isLimit -theorem isLimit_iff_omega_dvd {a : Ordinal} : IsLimit a ↔ a ≠ 0 ∧ ω ∣ a := by +theorem isLimit_iff_omega0_dvd {a : Ordinal} : IsLimit a ↔ a ≠ 0 ∧ ω ∣ a := by refine ⟨fun l => ⟨l.1, ⟨a / ω, le_antisymm ?_ (mul_div_le _ _)⟩⟩, fun h => ?_⟩ · refine (limit_le l).2 fun x hx => le_of_lt ?_ - rw [← div_lt omega_ne_zero, ← succ_le_iff, le_div omega_ne_zero, mul_succ, - add_le_of_limit omega_isLimit] + rw [← div_lt omega0_ne_zero, ← succ_le_iff, le_div omega0_ne_zero, mul_succ, + add_le_of_limit omega0_isLimit] intro b hb - rcases lt_omega.1 hb with ⟨n, rfl⟩ + rcases lt_omega0.1 hb with ⟨n, rfl⟩ exact (add_le_add_right (mul_div_le _ _) _).trans (lt_sub.1 <| nat_lt_limit (sub_isLimit l hx) _).le · rcases h with ⟨a0, b, rfl⟩ - refine mul_isLimit_left omega_isLimit (Ordinal.pos_iff_ne_zero.2 <| mt ?_ a0) + refine mul_isLimit_left omega0_isLimit (Ordinal.pos_iff_ne_zero.2 <| mt ?_ a0) intro e simp only [e, mul_zero] +@[deprecated (since := "2024-09-30")] +alias isLimit_iff_omega_dvd := isLimit_iff_omega0_dvd + theorem add_mul_limit_aux {a b c : Ordinal} (ba : b + a = a) (l : IsLimit c) (IH : ∀ c' < c, (a + b) * succ c' = a * succ c' + b) : (a + b) * c = a * c := le_antisymm @@ -2377,24 +2342,27 @@ theorem add_le_of_forall_add_lt {a b c : Ordinal} (hb : 0 < b) (h : ∀ d < b, a by_contra! hb exact (h _ hb).ne H -theorem IsNormal.apply_omega {f : Ordinal.{u} → Ordinal.{v}} (hf : IsNormal f) : +theorem IsNormal.apply_omega0 {f : Ordinal.{u} → Ordinal.{v}} (hf : IsNormal f) : ⨆ n : ℕ, f n = f ω := by rw [← iSup_natCast, hf.map_iSup] +@[deprecated (since := "2024-09-30")] +alias IsNormal.apply_omega := IsNormal.apply_omega0 + @[simp] theorem iSup_add_nat (o : Ordinal) : ⨆ n : ℕ, o + n = o + ω := - (add_isNormal o).apply_omega + (add_isNormal o).apply_omega0 set_option linter.deprecated false in @[deprecated iSup_add_nat (since := "2024-08-27")] theorem sup_add_nat (o : Ordinal) : (sup fun n : ℕ => o + n) = o + ω := - (add_isNormal o).apply_omega + (add_isNormal o).apply_omega0 @[simp] theorem iSup_mul_nat (o : Ordinal) : ⨆ n : ℕ, o * n = o * ω := by rcases eq_zero_or_pos o with (rfl | ho) · rw [zero_mul] exact iSup_eq_zero_iff.2 fun n => zero_mul (n : Ordinal) - · exact (mul_isNormal ho).apply_omega + · exact (mul_isNormal ho).apply_omega0 set_option linter.deprecated false in @[deprecated iSup_add_nat (since := "2024-08-27")] @@ -2402,10 +2370,30 @@ theorem sup_mul_nat (o : Ordinal) : (sup fun n : ℕ => o * n) = o * ω := by rcases eq_zero_or_pos o with (rfl | ho) · rw [zero_mul] exact sup_eq_zero_iff.2 fun n => zero_mul (n : Ordinal) - · exact (mul_isNormal ho).apply_omega + · exact (mul_isNormal ho).apply_omega0 end Ordinal +namespace Cardinal + +open Ordinal + +theorem ord_isLimit {c} (co : ℵ₀ ≤ c) : (ord c).IsLimit := by + refine ⟨fun h => aleph0_ne_zero ?_, fun a => lt_imp_lt_of_le_imp_le fun h => ?_⟩ + · rw [← Ordinal.le_zero, ord_le] at h + simpa only [card_zero, nonpos_iff_eq_zero] using co.trans h + · rw [ord_le] at h ⊢ + rwa [← @add_one_of_aleph0_le (card a), ← card_succ] + rw [← ord_le, ← le_succ_of_isLimit, ord_le] + · exact co.trans h + · rw [ord_aleph0] + exact Ordinal.omega0_isLimit + +theorem noMaxOrder {c} (h : ℵ₀ ≤ c) : NoMaxOrder c.ord.toType := + toType_noMax_of_succ_lt (ord_isLimit h).2 + +end Cardinal + variable {α : Type u} {r : α → α → Prop} {a b : α} namespace Acc @@ -2456,4 +2444,4 @@ theorem rank_strictAnti [Preorder α] [WellFoundedGT α] : end WellFounded -set_option linter.style.longFile 2500 +set_option linter.style.longFile 2700 diff --git a/Mathlib/SetTheory/Ordinal/Basic.lean b/Mathlib/SetTheory/Ordinal/Basic.lean index d9a0cb4a39c91..633dfc776c196 100644 --- a/Mathlib/SetTheory/Ordinal/Basic.lean +++ b/Mathlib/SetTheory/Ordinal/Basic.lean @@ -5,7 +5,6 @@ Authors: Mario Carneiro, Floris van Doorn -/ import Mathlib.Algebra.Order.SuccPred import Mathlib.Data.Sum.Order -import Mathlib.Order.InitialSeg import Mathlib.SetTheory.Cardinal.Basic import Mathlib.Tactic.PPWithUniv @@ -31,9 +30,10 @@ initial segment (or, equivalently, in any way). This total order is well founded `Ordinal.liftInitialSeg`. For a version registering that it is a principal segment embedding if `u < v`, see `Ordinal.liftPrincipalSeg`. -* `Ordinal.omega` or `ω` is the order type of `ℕ`. This definition is universe polymorphic: - `Ordinal.omega.{u} : Ordinal.{u}` (contrast with `ℕ : Type`, which lives in a specific - universe). In some cases the universe level has to be given explicitly. +* `Ordinal.omega0` or `ω` is the order type of `ℕ`. It is called this to match `Cardinal.aleph0` + and so that the omega function can be named `Ordinal.omega`. This definition is universe + polymorphic: `Ordinal.omega0.{u} : Ordinal.{u}` (contrast with `ℕ : Type`, which lives in + a specific universe). In some cases the universe level has to be given explicitly. * `o₁ + o₂` is the order on the disjoint union of `o₁` and `o₂` obtained by declaring that every element of `o₁` is smaller than every element of `o₂`. @@ -190,15 +190,14 @@ theorem type_pEmpty : type (@EmptyRelation PEmpty) = 0 := theorem type_empty : type (@EmptyRelation Empty) = 0 := type_eq_zero_of_empty _ -theorem type_eq_one_of_unique (r) [IsWellOrder α r] [Unique α] : type r = 1 := - (RelIso.relIsoOfUniqueOfIrrefl r _).ordinal_type_eq +theorem type_eq_one_of_unique (r) [IsWellOrder α r] [Nonempty α] [Subsingleton α] : type r = 1 := by + cases nonempty_unique α + exact (RelIso.relIsoOfUniqueOfIrrefl r _).ordinal_type_eq @[simp] theorem type_eq_one_iff_unique [IsWellOrder α r] : type r = 1 ↔ Nonempty (Unique α) := - ⟨fun h => - let ⟨s⟩ := type_eq.1 h - ⟨s.toEquiv.unique⟩, - fun ⟨h⟩ => @type_eq_one_of_unique α r _ h⟩ + ⟨fun h ↦ let ⟨s⟩ := type_eq.1 h; ⟨s.toEquiv.unique⟩, + fun ⟨_⟩ ↦ type_eq_one_of_unique r⟩ theorem type_pUnit : type (@EmptyRelation PUnit) = 1 := rfl @@ -247,6 +246,18 @@ theorem inductionOn {C : Ordinal → Prop} (o : Ordinal) (H : ∀ (α r) [IsWellOrder α r], C (type r)) : C o := Quot.inductionOn o fun ⟨α, r, wo⟩ => @H α r wo +@[elab_as_elim] +theorem inductionOn₂ {C : Ordinal → Ordinal → Prop} (o₁ o₂ : Ordinal) + (H : ∀ (α r) [IsWellOrder α r] (β s) [IsWellOrder β s], C (type r) (type s)) : C o₁ o₂ := + Quotient.inductionOn₂ o₁ o₂ fun ⟨α, r, wo₁⟩ ⟨β, s, wo₂⟩ => @H α r wo₁ β s wo₂ + +@[elab_as_elim] +theorem inductionOn₃ {C : Ordinal → Ordinal → Ordinal → Prop} (o₁ o₂ o₃ : Ordinal) + (H : ∀ (α r) [IsWellOrder α r] (β s) [IsWellOrder β s] (γ t) [IsWellOrder γ t], + C (type r) (type s) (type t)) : C o₁ o₂ o₃ := + Quotient.inductionOn₃ o₁ o₂ o₃ fun ⟨α, r, wo₁⟩ ⟨β, s, wo₂⟩ ⟨γ, t, wo₃⟩ => + @H α r wo₁ β s wo₂ γ t wo₃ + /-! ### The order on ordinals -/ /-- @@ -348,22 +359,18 @@ instance NeZero.one : NeZero (1 : Ordinal) := /-- Given two ordinals `α ≤ β`, then `initialSegToType α β` is the initial segment embedding of `α.toType` into `β.toType`. -/ -def initialSegToType {α β : Ordinal} (h : α ≤ β) : - @InitialSeg α.toType β.toType (· < ·) (· < ·) := by - change α.out.r ≼i β.out.r - rw [← Quotient.out_eq α, ← Quotient.out_eq β] at h; revert h - cases Quotient.out α; cases Quotient.out β; exact Classical.choice +def initialSegToType {α β : Ordinal} (h : α ≤ β) : α.toType ≤i β.toType := by + apply Classical.choice (type_le_iff.mp _) + rwa [type_lt, type_lt] @[deprecated initialSegToType (since := "2024-08-26")] noncomputable alias initialSegOut := initialSegToType /-- Given two ordinals `α < β`, then `principalSegToType α β` is the principal segment embedding of `α.toType` into `β.toType`. -/ -def principalSegToType {α β : Ordinal} (h : α < β) : - @PrincipalSeg α.toType β.toType (· < ·) (· < ·) := by - change α.out.r ≺i β.out.r - rw [← Quotient.out_eq α, ← Quotient.out_eq β] at h; revert h - cases Quotient.out α; cases Quotient.out β; exact Classical.choice +def principalSegToType {α β : Ordinal} (h : α < β) : α.toType by - rcases f.down.1 h with ⟨b, rfl⟩; exact ⟨b, rfl⟩⟩ + rcases f.mem_range_of_rel_top h with ⟨b, rfl⟩; exact ⟨b, rfl⟩⟩ @[simp] theorem typein_apply {α β} {r : α → α → Prop} {s : β → β → Prop} [IsWellOrder α r] [IsWellOrder β s] @@ -425,7 +432,7 @@ principal segment. -/ def typein.principalSeg {α : Type u} (r : α → α → Prop) [IsWellOrder α r] : @PrincipalSeg α Ordinal.{u} r (· < ·) := ⟨⟨⟨typein r, typein_injective r⟩, typein_lt_typein r⟩, type r, - fun _ ↦ ⟨typein_surj r, fun ⟨a, h⟩ ↦ h ▸ typein_lt_type r a⟩⟩ + fun _ ↦ ⟨fun ⟨a, h⟩ ↦ h ▸ typein_lt_type r a, typein_surj r⟩⟩ @[simp] theorem typein.principalSeg_coe (r : α → α → Prop) [IsWellOrder α r] : @@ -652,7 +659,7 @@ theorem lift_card (a) : Cardinal.lift.{u,v} (card a)= card (lift.{u,v} a) := theorem lift_down' {a : Cardinal.{u}} {b : Ordinal.{max u v}} (h : card.{max u v} b ≤ Cardinal.lift.{v,u} a) : ∃ a', lift.{v,u} a' = b := - let ⟨c, e⟩ := Cardinal.lift_down h + let ⟨c, e⟩ := Cardinal.mem_range_of_le_lift h Cardinal.inductionOn c (fun α => inductionOn b fun β s _ e' => by @@ -684,9 +691,9 @@ theorem lt_lift_iff {a : Ordinal.{u}} {b : Ordinal.{max u v}} : ⟨a', e, lift_lt.1 <| e.symm ▸ h⟩, fun ⟨_, e, h⟩ => e ▸ lift_lt.2 h⟩ -/-- Initial segment version of the lift operation on ordinals, embedding `ordinal.{u}` in - `ordinal.{v}` as an initial segment when `u ≤ v`. -/ -def liftInitialSeg : @InitialSeg Ordinal.{u} Ordinal.{max u v} (· < ·) (· < ·) := +/-- Initial segment version of the lift operation on ordinals, embedding `Ordinal.{u}` in +`Ordinal.{v}` as an initial segment when `u ≤ v`. -/ +def liftInitialSeg : Ordinal.{u} ≤i Ordinal.{max u v} := ⟨⟨⟨lift.{v}, fun _ _ => lift_inj.1⟩, lift_lt⟩, fun _ _ h => lift_down (le_of_lt h)⟩ @[deprecated liftInitialSeg (since := "2024-09-21")] @@ -701,29 +708,38 @@ set_option linter.deprecated false in theorem lift.initialSeg_coe : (lift.initialSeg.{u, v} : Ordinal → Ordinal) = lift.{v, u} := rfl -/-! ### The first infinite ordinal `omega` -/ +/-! ### The first infinite ordinal ω -/ /-- `ω` is the first infinite ordinal, defined as the order type of `ℕ`. -/ -def omega : Ordinal.{u} := +def omega0 : Ordinal.{u} := lift <| @type ℕ (· < ·) _ +@[deprecated Ordinal.omega0 (since := "2024-09-26")] +alias omega := omega0 + @[inherit_doc] -scoped notation "ω" => Ordinal.omega +scoped notation "ω" => Ordinal.omega0 -/-- Note that the presence of this lemma makes `simp [omega]` form a loop. -/ +/-- Note that the presence of this lemma makes `simp [omega0]` form a loop. -/ @[simp] theorem type_nat_lt : @type ℕ (· < ·) _ = ω := (lift_id _).symm @[simp] -theorem card_omega : card ω = ℵ₀ := +theorem card_omega0 : card ω = ℵ₀ := rfl +@[deprecated (since := "2024-09-30")] +alias card_omega := card_omega0 + @[simp] -theorem lift_omega : lift ω = ω := +theorem lift_omega0 : lift ω = ω := lift_lift _ +@[deprecated (since := "2024-09-30")] +alias lift_omega := lift_omega0 + /-! ### Definition and first properties of addition on ordinals @@ -735,11 +751,10 @@ the addition, together with properties of the other operations, are proved in /-- `o₁ + o₂` is the order on the disjoint union of `o₁` and `o₂` obtained by declaring that - every element of `o₁` is smaller than every element of `o₂`. -/ +every element of `o₁` is smaller than every element of `o₂`. -/ instance add : Add Ordinal.{u} := - ⟨fun o₁ o₂ => - Quotient.liftOn₂ o₁ o₂ (fun ⟨_, r, _⟩ ⟨_, s, _⟩ => type (Sum.Lex r s)) - fun _ _ _ _ ⟨f⟩ ⟨g⟩ => Quot.sound ⟨RelIso.sumLexCongr f g⟩⟩ + ⟨fun o₁ o₂ => Quotient.liftOn₂ o₁ o₂ (fun ⟨_, r, _⟩ ⟨_, s, _⟩ => type (Sum.Lex r s)) + fun _ _ _ _ ⟨f⟩ ⟨g⟩ => (RelIso.sumLexCongr f g).ordinal_type_eq⟩ instance addMonoidWithOne : AddMonoidWithOne Ordinal.{u} where add := (· + ·) @@ -780,45 +795,18 @@ theorem card_ofNat (n : ℕ) [n.AtLeastTwo] : card.{u} (no_index (OfNat.ofNat n)) = OfNat.ofNat n := card_nat n --- Porting note: Rewritten proof of elim, previous version was difficult to debug instance add_covariantClass_le : CovariantClass Ordinal.{u} Ordinal.{u} (· + ·) (· ≤ ·) where - elim := fun c a b h => by - revert h c - refine inductionOn a (fun α₁ r₁ _ ↦ ?_) - refine inductionOn b (fun α₂ r₂ _ ↦ ?_) - rintro c ⟨⟨⟨f, fo⟩, fi⟩⟩ - refine inductionOn c (fun β s _ ↦ ?_) - refine ⟨⟨⟨(Embedding.refl.{u+1} _).sumMap f, ?_⟩, ?_⟩⟩ - · intros a b - match a, b with - | Sum.inl a, Sum.inl b => exact Sum.lex_inl_inl.trans Sum.lex_inl_inl.symm - | Sum.inl a, Sum.inr b => apply iff_of_true <;> apply Sum.Lex.sep - | Sum.inr a, Sum.inl b => apply iff_of_false <;> exact Sum.lex_inr_inl - | Sum.inr a, Sum.inr b => exact Sum.lex_inr_inr.trans <| fo.trans Sum.lex_inr_inr.symm - · intros a b H - match a, b, H with - | _, Sum.inl b, _ => exact ⟨Sum.inl b, rfl⟩ - | Sum.inl a, Sum.inr b, H => exact (Sum.lex_inr_inl H).elim - | Sum.inr a, Sum.inr b, H => - let ⟨w, h⟩ := fi _ _ (Sum.lex_inr_inr.1 H) - exact ⟨Sum.inr w, congr_arg Sum.inr h⟩ - --- Porting note: Rewritten proof of elim, previous version was difficult to debug + elim c a b := by + refine inductionOn₃ a b c fun α r _ β s _ γ t _ ⟨f⟩ ↦ + (RelEmbedding.ofMonotone (Sum.recOn · Sum.inl (Sum.inr ∘ f)) ?_).ordinal_type_le + simp [f.map_rel_iff] + instance add_swap_covariantClass_le : CovariantClass Ordinal.{u} Ordinal.{u} (swap (· + ·)) (· ≤ ·) where - elim := fun c a b h => by - revert h c - refine inductionOn a (fun α₁ r₁ _ ↦ ?_) - refine inductionOn b (fun α₂ r₂ _ ↦ ?_) - rintro c ⟨⟨⟨f, fo⟩, fi⟩⟩ - refine inductionOn c (fun β s _ ↦ ?_) - exact @RelEmbedding.ordinal_type_le _ _ (Sum.Lex r₁ s) (Sum.Lex r₂ s) _ _ - ⟨f.sumMap (Embedding.refl _), by - intro a b - constructor <;> intro H - · cases' a with a a <;> cases' b with b b <;> cases H <;> constructor <;> - [rwa [← fo]; assumption] - · cases H <;> constructor <;> [rwa [fo]; assumption]⟩ + elim c a b := by + refine inductionOn₃ a b c fun α r _ β s _ γ t _ ⟨f⟩ ↦ + (RelEmbedding.ofMonotone (Sum.recOn · (Sum.inl ∘ f) Sum.inr) ?_).ordinal_type_le + simp [f.map_rel_iff] theorem le_add_right (a b : Ordinal) : a ≤ a + b := by simpa only [add_zero] using add_le_add_left (Ordinal.zero_le b) a @@ -842,32 +830,12 @@ theorem sInf_empty : sInf (∅ : Set Ordinal) = 0 := /-! ### Successor order properties -/ -private theorem succ_le_iff' {a b : Ordinal} : a + 1 ≤ b ↔ a < b := - ⟨lt_of_lt_of_le - (inductionOn a fun α r _ => - ⟨⟨⟨⟨fun x => Sum.inl x, fun _ _ => Sum.inl.inj⟩, Sum.lex_inl_inl⟩, - Sum.inr PUnit.unit, fun b => - Sum.recOn b (fun x => ⟨fun _ => ⟨x, rfl⟩, fun _ => Sum.Lex.sep _ _⟩) fun x => - Sum.lex_inr_inr.trans ⟨False.elim, fun ⟨x, H⟩ => Sum.inl_ne_inr H⟩⟩⟩), - inductionOn a fun α r hr => - inductionOn b fun β s hs ⟨⟨f, t, hf⟩⟩ => by - haveI := hs - refine ⟨⟨RelEmbedding.ofMonotone (Sum.rec f fun _ => t) (fun a b ↦ ?_), fun a b ↦ ?_⟩⟩ - · rcases a with (a | _) <;> rcases b with (b | _) - · simpa only [Sum.lex_inl_inl] using f.map_rel_iff.2 - · intro - rw [hf] - exact ⟨_, rfl⟩ - · exact False.elim ∘ Sum.lex_inr_inl - · exact False.elim ∘ Sum.lex_inr_inr.1 - · rcases a with (a | _) - · intro h - have := @PrincipalSeg.mem_range_of_rel _ _ _ _ _ ⟨f, t, hf⟩ _ _ h - cases' this with w h - exact ⟨Sum.inl w, h⟩ - · intro h - cases' (hf b).1 h with w h - exact ⟨Sum.inl w, h⟩⟩ +private theorem succ_le_iff' {a b : Ordinal} : a + 1 ≤ b ↔ a < b := by + refine inductionOn₂ a b fun α r _ β s _ ↦ ⟨?_, ?_⟩ <;> rintro ⟨f⟩ + · refine ⟨((InitialSeg.leAdd _ _).trans f).toPrincipalSeg fun h ↦ ?_⟩ + simpa using h (f (Sum.inr PUnit.unit)) + · apply (RelEmbedding.ofMonotone (Sum.recOn · f fun _ ↦ f.top) ?_).ordinal_type_le + simpa [f.map_rel_iff] using f.lt_top instance noMaxOrder : NoMaxOrder Ordinal := ⟨fun _ => ⟨_, succ_le_iff'.1 le_rfl⟩⟩ @@ -992,7 +960,7 @@ theorem enum_inj {r : α → α → Prop} [IsWellOrder α r] {o₁ o₂ : {o // rw [EmbeddingLike.apply_eq_iff_eq, Subtype.mk.injEq] /-- The order isomorphism between ordinals less than `o` and `o.toType`. -/ -@[simps!] +@[simps! (config := .lemmasOnly)] noncomputable def enumIsoToType (o : Ordinal) : Set.Iio o ≃o o.toType where toFun x := enum (α := o.toType) (· < ·) ⟨x.1, by @@ -1053,12 +1021,17 @@ theorem lift_univ : lift.{w} univ.{u, v} = univ.{u, max v w} := theorem univ_umax : univ.{u, max (u + 1) v} = univ.{u, v} := congr_fun lift_umax _ -/-- Principal segment version of the lift operation on ordinals, embedding `ordinal.{u}` in - `ordinal.{v}` as a principal segment when `u < v`. -/ -def liftPrincipalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < ·) (· < ·) := +/-- Principal segment version of the lift operation on ordinals, embedding `Ordinal.{u}` in +`Ordinal.{v}` as a principal segment when `u < v`. -/ +def liftPrincipalSeg : Ordinal.{u} inductionOn b ?_; intro β s _ rw [univ, ← lift_umax]; constructor <;> intro h + · cases' h with a e + rw [← e] + refine inductionOn a ?_ + intro α r _ + exact lift_type_lt.{u, u + 1, max (u + 1) v}.2 ⟨typein.principalSeg r⟩ · rw [← lift_id (type s)] at h ⊢ cases' lift_type_lt.{_,_,v}.1 h with f cases' f with f a hf @@ -1067,23 +1040,17 @@ def liftPrincipalSeg : @PrincipalSeg Ordinal.{u} Ordinal.{max (u + 1) v} (· < -- Porting note: apply inductionOn does not work, refine does refine inductionOn a ?_ intro α r _ hf - refine - lift_type_eq.{u, max (u + 1) v, max (u + 1) v}.2 - ⟨(RelIso.ofSurjective (RelEmbedding.ofMonotone ?_ ?_) ?_).symm⟩ - · exact fun b => enum r ⟨f b, (hf _).2 ⟨_, rfl⟩⟩ + refine lift_type_eq.{u, max (u + 1) v, max (u + 1) v}.2 + ⟨(RelIso.ofSurjective (RelEmbedding.ofMonotone ?_ ?_) ?_).symm⟩ + · exact fun b => enum r ⟨f b, (hf _).1 ⟨_, rfl⟩⟩ · refine fun a b h => (typein_lt_typein r).1 ?_ rw [typein_enum, typein_enum] exact f.map_rel_iff.2 h · intro a' - cases' (hf _).1 (typein_lt_type _ a') with b e + cases' (hf _).2 (typein_lt_type _ a') with b e exists b simp only [RelEmbedding.ofMonotone_coe] - simp [e] - · cases' h with a e - rw [← e] - refine inductionOn a ?_ - intro α r _ - exact lift_type_lt.{u, u + 1, max (u + 1) v}.2 ⟨typein.principalSeg r⟩⟩ + simp [e]⟩ @[deprecated liftPrincipalSeg (since := "2024-09-21")] alias lift.principalSeg := liftPrincipalSeg @@ -1185,6 +1152,9 @@ theorem card_ord (c) : (ord c).card = c := -- Porting note: cardinal.mk_def is now Cardinal.mk'_def, not sure why simp only [mk'_def, e, card_type] +theorem card_surjective : Function.Surjective card := + fun c ↦ ⟨_, card_ord c⟩ + /-- Galois coinsertion between `Cardinal.ord` and `Ordinal.card`. -/ def gciOrdCard : GaloisCoinsertion ord card := gc_ord_card.toGaloisCoinsertion fun c => c.card_ord.le @@ -1332,7 +1302,7 @@ theorem lift_lt_univ' (c : Cardinal) : lift.{max (u + 1) v, u} c < univ.{u, v} : @[simp] theorem ord_univ : ord univ.{u, v} = Ordinal.univ.{u, v} := by refine le_antisymm (ord_card_le _) <| le_of_forall_lt fun o h => lt_ord.2 ?_ - have := liftPrincipalSeg.{u, v}.down.1 (by simpa only [liftPrincipalSeg_coe] using h) + have := liftPrincipalSeg.mem_range_of_rel_top (by simpa only [liftPrincipalSeg_coe] using h) rcases this with ⟨o, h'⟩ rw [← h', liftPrincipalSeg_coe, ← lift_card] apply lift_lt_univ' @@ -1341,14 +1311,14 @@ theorem lt_univ {c} : c < univ.{u, u + 1} ↔ ∃ c', c = lift.{u + 1, u} c' := ⟨fun h => by have := ord_lt_ord.2 h rw [ord_univ] at this - cases' liftPrincipalSeg.{u, u + 1}.down.1 (by simpa only [liftPrincipalSeg_top] ) with o e + cases' liftPrincipalSeg.mem_range_of_rel_top (by simpa only [liftPrincipalSeg_top]) with o e have := card_ord c rw [← e, liftPrincipalSeg_coe, ← lift_card] at this exact ⟨_, this.symm⟩, fun ⟨c', e⟩ => e.symm ▸ lift_lt_univ _⟩ theorem lt_univ' {c} : c < univ.{u, v} ↔ ∃ c', c = lift.{max (u + 1) v, u} c' := ⟨fun h => by - let ⟨a, e, h'⟩ := lt_lift_iff.1 h + let ⟨a, h', e⟩ := lt_lift_iff.1 h rw [← univ_id] at h' rcases lt_univ.{u}.1 h' with ⟨c', rfl⟩ exact ⟨c', by simp only [e.symm, lift_lift]⟩, fun ⟨c', e⟩ => e.symm ▸ lift_lt_univ' _⟩ diff --git a/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean index 1013da5c56c46..563ef369b373b 100644 --- a/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean +++ b/Mathlib/SetTheory/Ordinal/CantorNormalForm.lean @@ -139,6 +139,6 @@ theorem CNF_sorted (b o : Ordinal) : ((CNF b o).map Prod.fst).Sorted (· > ·) : refine ⟨fun a H ↦ ?_, IH⟩ rw [mem_map] at H rcases H with ⟨⟨a, a'⟩, H, rfl⟩ - exact (CNF_fst_le_log H).trans_lt (log_mod_opow_log_lt_log_self hb ho hbo) + exact (CNF_fst_le_log H).trans_lt (log_mod_opow_log_lt_log_self hb hbo) end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Enum.lean b/Mathlib/SetTheory/Ordinal/Enum.lean new file mode 100644 index 0000000000000..c5a4c3b7442d6 --- /dev/null +++ b/Mathlib/SetTheory/Ordinal/Enum.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2022 Violeta Hernández Palacios. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Violeta Hernández Palacios +-/ +import Mathlib.SetTheory.Ordinal.Arithmetic + +/-! +# Enumerating sets of ordinals by ordinals + +The ordinals have the peculiar property that every subset bounded above is a small type, while +themselves not being small. As a consequence of this, every unbounded subset of `Ordinal` is order +isomorphic to `Ordinal`. + +We define this correspondence as `enumOrd`, and use it to then define an order isomorphism +`enumOrdOrderIso`. + +This can be thought of as an ordinal analog of `Nat.nth`. +-/ + +universe u + +open Order Set + +namespace Ordinal + +variable {o a b : Ordinal.{u}} + +/-- Enumerator function for an unbounded set of ordinals. -/ +noncomputable def enumOrd (s : Set Ordinal.{u}) (o : Ordinal.{u}) : Ordinal.{u} := + sInf (s ∩ { b | ∀ c, c < o → enumOrd s c < b }) +termination_by o + +variable {s : Set Ordinal.{u}} + +@[deprecated (since := "2024-09-20")] +theorem enumOrd_def (o : Ordinal.{u}) : + enumOrd s o = sInf (s ∩ { b | ∀ c, c < o → enumOrd s c < b }) := by + rw [enumOrd] + +theorem enumOrd_le_of_forall_lt (ha : a ∈ s) (H : ∀ b < o, enumOrd s b < a) : enumOrd s o ≤ a := by + rw [enumOrd] + exact csInf_le' ⟨ha, H⟩ + +/-- The set in the definition of `enumOrd` is nonempty. -/ +private theorem enumOrd_nonempty (hs : ¬ BddAbove s) (o : Ordinal) : + (s ∩ { b | ∀ c, c < o → enumOrd s c < b }).Nonempty := by + rw [not_bddAbove_iff] at hs + obtain ⟨a, ha⟩ := bddAbove_of_small (enumOrd s '' Iio o) + obtain ⟨b, hb, hba⟩ := hs a + exact ⟨b, hb, fun c hc ↦ (ha (mem_image_of_mem _ hc)).trans_lt hba⟩ + +private theorem enumOrd_mem_aux (hs : ¬ BddAbove s) (o : Ordinal) : + enumOrd s o ∈ s ∩ { b | ∀ c, c < o → enumOrd s c < b } := by + rw [enumOrd] + exact csInf_mem (enumOrd_nonempty hs o) + +theorem enumOrd_mem (hs : ¬ BddAbove s) (o : Ordinal) : enumOrd s o ∈ s := + (enumOrd_mem_aux hs o).1 + +theorem enumOrd_strictMono (hs : ¬ BddAbove s) : StrictMono (enumOrd s) := + fun a b ↦ (enumOrd_mem_aux hs b).2 a + +theorem enumOrd_succ_le (hs : ¬ BddAbove s) (ha : a ∈ s) (hb : enumOrd s b < a) : + enumOrd s (succ b) ≤ a := by + apply enumOrd_le_of_forall_lt ha + intro c hc + rw [lt_succ_iff] at hc + exact ((enumOrd_strictMono hs).monotone hc).trans_lt hb + +theorem range_enumOrd (hs : ¬ BddAbove s) : range (enumOrd s) = s := by + ext a + let t := { b | a ≤ enumOrd s b } + constructor + · rintro ⟨b, rfl⟩ + exact enumOrd_mem hs b + · intro ha + refine ⟨sInf t, (enumOrd_le_of_forall_lt ha ?_).antisymm ?_⟩ + · intro b hb + by_contra! hb' + exact hb.not_le (csInf_le' hb') + · exact csInf_mem (s := t) ⟨a, (enumOrd_strictMono hs).id_le a⟩ + +theorem enumOrd_surjective (hs : ¬ BddAbove s) {b : Ordinal} (hb : b ∈ s) : + ∃ a, enumOrd s a = b := by + rwa [← range_enumOrd hs] at hb + +theorem enumOrd_le_of_subset {t : Set Ordinal} (hs : ¬ BddAbove s) (hst : s ⊆ t) : + enumOrd t ≤ enumOrd s := by + intro a + rw [enumOrd, enumOrd] + apply csInf_le_csInf' (enumOrd_nonempty hs a) (inter_subset_inter hst _) + intro b hb c hc + exact (enumOrd_le_of_subset hs hst c).trans_lt <| hb c hc +termination_by a => a + +/-- A characterization of `enumOrd`: it is the unique strict monotonic function with range `s`. -/ +theorem eq_enumOrd (f : Ordinal → Ordinal) (hs : ¬ BddAbove s) : + enumOrd s = f ↔ StrictMono f ∧ range f = s := by + constructor + · rintro rfl + exact ⟨enumOrd_strictMono hs, range_enumOrd hs⟩ + · rintro ⟨h₁, h₂⟩ + rwa [← (enumOrd_strictMono hs).range_inj h₁, range_enumOrd hs, eq_comm] + +theorem enumOrd_range {f : Ordinal → Ordinal} (hf : StrictMono f) : enumOrd (range f) = f := + (eq_enumOrd _ hf.not_bddAbove_range_of_wellFoundedLT).2 ⟨hf, rfl⟩ + +@[simp] +theorem enumOrd_univ : enumOrd Set.univ = id := by + rw [← range_id] + exact enumOrd_range strictMono_id + +@[simp] +theorem enumOrd_zero : enumOrd s 0 = sInf s := by + rw [enumOrd] + simp [Ordinal.not_lt_zero] + +/-- An order isomorphism between an unbounded set of ordinals and the ordinals. -/ +noncomputable def enumOrdOrderIso (s : Set Ordinal) (hs : ¬ BddAbove s) : Ordinal ≃o s := + StrictMono.orderIsoOfSurjective (fun o => ⟨_, enumOrd_mem hs o⟩) (enumOrd_strictMono hs) fun s => + let ⟨a, ha⟩ := enumOrd_surjective hs s.prop + ⟨a, Subtype.eq ha⟩ + +end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Exponential.lean b/Mathlib/SetTheory/Ordinal/Exponential.lean index d231c359e943d..9b7cfa5938077 100644 --- a/Mathlib/SetTheory/Ordinal/Exponential.lean +++ b/Mathlib/SetTheory/Ordinal/Exponential.lean @@ -86,6 +86,14 @@ theorem opow_pos {a : Ordinal} (b : Ordinal) (a0 : 0 < a) : 0 < a ^ b := by theorem opow_ne_zero {a : Ordinal} (b : Ordinal) (a0 : a ≠ 0) : a ^ b ≠ 0 := Ordinal.pos_iff_ne_zero.1 <| opow_pos b <| Ordinal.pos_iff_ne_zero.2 a0 +@[simp] +theorem opow_eq_zero {a b : Ordinal} : a ^ b = 0 ↔ a = 0 ∧ b ≠ 0 := by + obtain rfl | ha := eq_or_ne a 0 + · obtain rfl | hb := eq_or_ne b 0 + · simp + · simp [hb] + · simp [opow_ne_zero b ha, ha] + @[simp, norm_cast] theorem opow_natCast (a : Ordinal) (n : ℕ) : a ^ (n : Ordinal) = a ^ n := by induction n with @@ -218,41 +226,56 @@ theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by simp (config := { contextual := true }) only [IH] exact (opow_le_of_limit (opow_ne_zero _ a0) l).symm +theorem opow_mul_add_pos {b v : Ordinal} (hb : b ≠ 0) (u : Ordinal) (hv : v ≠ 0) (w : Ordinal) : + 0 < b ^ u * v + w := + (opow_pos u <| Ordinal.pos_iff_ne_zero.2 hb).trans_le <| + (le_mul_left _ <| Ordinal.pos_iff_ne_zero.2 hv).trans <| le_add_right _ _ + +theorem opow_mul_add_lt_opow_mul_succ {b u w : Ordinal} (v : Ordinal) (hw : w < b ^ u) : + b ^ u * v + w < b ^ u * succ v := by + rwa [mul_succ, add_lt_add_iff_left] + +theorem opow_mul_add_lt_opow_succ {b u v w : Ordinal} (hvb : v < b) (hw : w < b ^ u) : + b ^ u * v + w < b ^ succ u := by + convert (opow_mul_add_lt_opow_mul_succ v hw).trans_le + (mul_le_mul_left' (succ_le_of_lt hvb) _) using 1 + exact opow_succ b u + /-! ### Ordinal logarithm -/ /-- The ordinal logarithm is the solution `u` to the equation `x = b ^ u * v + w` where `v < b` and - `w < b ^ u`. -/ +`w < b ^ u`. -/ @[pp_nodot] def log (b : Ordinal) (x : Ordinal) : Ordinal := - if _h : 1 < b then pred (sInf { o | x < b ^ o }) else 0 + if 1 < b then pred (sInf { o | x < b ^ o }) else 0 /-- The set in the definition of `log` is nonempty. -/ -theorem log_nonempty {b x : Ordinal} (h : 1 < b) : { o : Ordinal | x < b ^ o }.Nonempty := +private theorem log_nonempty {b x : Ordinal} (h : 1 < b) : { o : Ordinal | x < b ^ o }.Nonempty := ⟨_, succ_le_iff.1 (right_le_opow _ h)⟩ -theorem log_def {b : Ordinal} (h : 1 < b) (x : Ordinal) : - log b x = pred (sInf { o | x < b ^ o }) := by simp only [log, dif_pos h] +theorem log_def {b : Ordinal} (h : 1 < b) (x : Ordinal) : log b x = pred (sInf { o | x < b ^ o }) := + if_pos h -theorem log_of_not_one_lt_left {b : Ordinal} (h : ¬1 < b) (x : Ordinal) : log b x = 0 := by - simp only [log, dif_neg h] +theorem log_of_left_le_one {b : Ordinal} (h : b ≤ 1) (x : Ordinal) : log b x = 0 := + if_neg h.not_lt -theorem log_of_left_le_one {b : Ordinal} (h : b ≤ 1) : ∀ x, log b x = 0 := - log_of_not_one_lt_left h.not_lt +@[deprecated log_of_left_le_one (since := "2024-10-10")] +theorem log_of_not_one_lt_left {b : Ordinal} (h : ¬1 < b) (x : Ordinal) : log b x = 0 := by + simp only [log, if_neg h] @[simp] theorem log_zero_left : ∀ b, log 0 b = 0 := log_of_left_le_one zero_le_one @[simp] -theorem log_zero_right (b : Ordinal) : log b 0 = 0 := - if b1 : 1 < b then by - rw [log_def b1, ← Ordinal.le_zero, pred_le] +theorem log_zero_right (b : Ordinal) : log b 0 = 0 := by + obtain hb | hb := lt_or_le 1 b + · rw [log_def hb, ← Ordinal.le_zero, pred_le, succ_zero] apply csInf_le' - dsimp - rw [succ_zero, opow_one] - exact zero_lt_one.trans b1 - else by simp only [log_of_not_one_lt_left b1] + rw [mem_setOf, opow_one] + exact bot_lt_of_lt hb + · rw [log_of_left_le_one hb] @[simp] theorem log_one_left : ∀ b, log 1 b = 0 := @@ -261,7 +284,7 @@ theorem log_one_left : ∀ b, log 1 b = 0 := theorem succ_log_def {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) : succ (log b x) = sInf { o : Ordinal | x < b ^ o } := by let t := sInf { o : Ordinal | x < b ^ o } - have : x < (b^t) := csInf_mem (log_nonempty hb) + have : x < b ^ t := csInf_mem (log_nonempty hb) rcases zero_or_succ_or_limit t with (h | h | h) · refine ((one_le_iff_ne_zero.2 hx).not_lt ?_).elim simpa only [h, opow_zero] using this @@ -286,17 +309,67 @@ theorem opow_log_le_self (b : Ordinal) {x : Ordinal} (hx : x ≠ 0) : b ^ log b rwa [← succ_log_def hb hx] at this · rwa [one_opow, one_le_iff_ne_zero] -/-- `opow b` and `log b` (almost) form a Galois connection. -/ -theorem opow_le_iff_le_log {b x c : Ordinal} (hb : 1 < b) (hx : x ≠ 0) : b ^ c ≤ x ↔ c ≤ log b x := - ⟨fun h => - le_of_not_lt fun hn => - (lt_opow_succ_log_self hb x).not_le <| - ((opow_le_opow_iff_right hb).2 (succ_le_of_lt hn)).trans h, - fun h => ((opow_le_opow_iff_right hb).2 h).trans (opow_log_le_self b hx)⟩ - +/-- `opow b` and `log b` (almost) form a Galois connection. + +See `opow_le_iff_le_log'` for a variant assuming `c ≠ 0` rather than `x ≠ 0`. See also +`le_log_of_opow_le` and `opow_le_of_le_log`, which are both separate implications under weaker +assumptions. -/ +theorem opow_le_iff_le_log {b x c : Ordinal} (hb : 1 < b) (hx : x ≠ 0) : + b ^ c ≤ x ↔ c ≤ log b x := by + constructor <;> + intro h + · apply le_of_not_lt + intro hn + apply (lt_opow_succ_log_self hb x).not_le <| + ((opow_le_opow_iff_right hb).2 <| succ_le_of_lt hn).trans h + · exact ((opow_le_opow_iff_right hb).2 h).trans <| opow_log_le_self b hx + +/-- `opow b` and `log b` (almost) form a Galois connection. + +See `opow_le_iff_le_log` for a variant assuming `x ≠ 0` rather than `c ≠ 0`. See also +`le_log_of_opow_le` and `opow_le_of_le_log`, which are both separate implications under weaker +assumptions. -/ +theorem opow_le_iff_le_log' {b x c : Ordinal} (hb : 1 < b) (hc : c ≠ 0) : + b ^ c ≤ x ↔ c ≤ log b x := by + obtain rfl | hx := eq_or_ne x 0 + · rw [log_zero_right, Ordinal.le_zero, Ordinal.le_zero, opow_eq_zero] + simp [hc, (zero_lt_one.trans hb).ne'] + · exact opow_le_iff_le_log hb hx + +theorem le_log_of_opow_le {b x c : Ordinal} (hb : 1 < b) (h : b ^ c ≤ x) : c ≤ log b x := by + obtain rfl | hx := eq_or_ne x 0 + · rw [Ordinal.le_zero, opow_eq_zero] at h + exact (zero_lt_one.asymm <| h.1 ▸ hb).elim + · exact (opow_le_iff_le_log hb hx).1 h + +theorem opow_le_of_le_log {b x c : Ordinal} (hc : c ≠ 0) (h : c ≤ log b x) : b ^ c ≤ x := by + obtain hb | hb := le_or_lt b 1 + · rw [log_of_left_le_one hb] at h + exact (h.not_lt (Ordinal.pos_iff_ne_zero.2 hc)).elim + · rwa [opow_le_iff_le_log' hb hc] + +/-- `opow b` and `log b` (almost) form a Galois connection. + +See `lt_opow_iff_log_lt'` for a variant assuming `c ≠ 0` rather than `x ≠ 0`. See also +`lt_opow_of_log_lt` and `lt_log_of_lt_opow`, which are both separate implications under weaker +assumptions. -/ theorem lt_opow_iff_log_lt {b x c : Ordinal} (hb : 1 < b) (hx : x ≠ 0) : x < b ^ c ↔ log b x < c := lt_iff_lt_of_le_iff_le (opow_le_iff_le_log hb hx) +/-- `opow b` and `log b` (almost) form a Galois connection. + +See `lt_opow_iff_log_lt` for a variant assuming `x ≠ 0` rather than `c ≠ 0`. See also +`lt_opow_of_log_lt` and `lt_log_of_lt_opow`, which are both separate implications under weaker +assumptions. -/ +theorem lt_opow_iff_log_lt' {b x c : Ordinal} (hb : 1 < b) (hc : c ≠ 0) : x < b ^ c ↔ log b x < c := + lt_iff_lt_of_le_iff_le (opow_le_iff_le_log' hb hc) + +theorem lt_opow_of_log_lt {b x c : Ordinal} (hb : 1 < b) : log b x < c → x < b ^ c := + lt_imp_lt_of_le_imp_le <| le_log_of_opow_le hb + +theorem lt_log_of_lt_opow {b x c : Ordinal} (hc : c ≠ 0) : x < b ^ c → log b x < c := + lt_imp_lt_of_le_imp_le <| opow_le_of_le_log hc + theorem log_pos {b o : Ordinal} (hb : 1 < b) (ho : o ≠ 0) (hbo : b ≤ o) : 0 < log b o := by rwa [← succ_le_iff, succ_zero, ← opow_le_iff_le_log hb ho, opow_one] @@ -310,69 +383,75 @@ theorem log_eq_zero {b o : Ordinal} (hbo : o < b) : log b o = 0 := by · rwa [← Ordinal.le_zero, ← lt_succ_iff, succ_zero, ← lt_opow_iff_log_lt hb ho, opow_one] @[mono] -theorem log_mono_right (b : Ordinal) {x y : Ordinal} (xy : x ≤ y) : log b x ≤ log b y := - if hx : x = 0 then by simp only [hx, log_zero_right, Ordinal.zero_le] - else - if hb : 1 < b then - (opow_le_iff_le_log hb (lt_of_lt_of_le (Ordinal.pos_iff_ne_zero.2 hx) xy).ne').1 <| +theorem log_mono_right (b : Ordinal) {x y : Ordinal} (xy : x ≤ y) : log b x ≤ log b y := by + obtain rfl | hx := eq_or_ne x 0 + · simp_rw [log_zero_right, Ordinal.zero_le] + · obtain hb | hb := lt_or_le 1 b + · exact (opow_le_iff_le_log hb (hx.bot_lt.trans_le xy).ne').1 <| (opow_log_le_self _ hx).trans xy - else by simp only [log_of_not_one_lt_left hb, Ordinal.zero_le] + · rw [log_of_left_le_one hb, log_of_left_le_one hb] -theorem log_le_self (b x : Ordinal) : log b x ≤ x := - if hx : x = 0 then by simp only [hx, log_zero_right, Ordinal.zero_le] - else - if hb : 1 < b then (right_le_opow _ hb).trans (opow_log_le_self b hx) - else by simp only [log_of_not_one_lt_left hb, Ordinal.zero_le] +theorem log_le_self (b x : Ordinal) : log b x ≤ x := by + obtain rfl | hx := eq_or_ne x 0 + · rw [log_zero_right] + · obtain hb | hb := lt_or_le 1 b + · exact (right_le_opow _ hb).trans (opow_log_le_self b hx) + · simp_rw [log_of_left_le_one hb, Ordinal.zero_le] @[simp] -theorem log_one_right (b : Ordinal) : log b 1 = 0 := - if hb : 1 < b then log_eq_zero hb else log_of_not_one_lt_left hb 1 +theorem log_one_right (b : Ordinal) : log b 1 = 0 := by + obtain hb | hb := lt_or_le 1 b + · exact log_eq_zero hb + · exact log_of_left_le_one hb 1 theorem mod_opow_log_lt_self (b : Ordinal) {o : Ordinal} (ho : o ≠ 0) : o % (b ^ log b o) < o := by rcases eq_or_ne b 0 with (rfl | hb) · simpa using Ordinal.pos_iff_ne_zero.2 ho · exact (mod_lt _ <| opow_ne_zero _ hb).trans_le (opow_log_le_self _ ho) -theorem log_mod_opow_log_lt_log_self {b o : Ordinal} (hb : 1 < b) (ho : o ≠ 0) (hbo : b ≤ o) : +theorem log_mod_opow_log_lt_log_self {b o : Ordinal} (hb : 1 < b) (hbo : b ≤ o) : log b (o % (b ^ log b o)) < log b o := by rcases eq_or_ne (o % (b ^ log b o)) 0 with h | h · rw [h, log_zero_right] - apply log_pos hb ho hbo + exact log_pos hb (one_le_iff_ne_zero.1 (hb.le.trans hbo)) hbo · rw [← succ_le_iff, succ_log_def hb h] apply csInf_le' apply mod_lt rw [← Ordinal.pos_iff_ne_zero] exact opow_pos _ (zero_lt_one.trans hb) -theorem opow_mul_add_pos {b v : Ordinal} (hb : b ≠ 0) (u : Ordinal) (hv : v ≠ 0) (w : Ordinal) : - 0 < b ^ u * v + w := - (opow_pos u <| Ordinal.pos_iff_ne_zero.2 hb).trans_le <| - (le_mul_left _ <| Ordinal.pos_iff_ne_zero.2 hv).trans <| le_add_right _ _ - -theorem opow_mul_add_lt_opow_mul_succ {b u w : Ordinal} (v : Ordinal) (hw : w < b ^ u) : - b ^ u * v + w < b ^ u * succ v := by rwa [mul_succ, add_lt_add_iff_left] - -theorem opow_mul_add_lt_opow_succ {b u v w : Ordinal} (hvb : v < b) (hw : w < b ^ u) : - b ^ u * v + w < b ^ succ u := by - convert (opow_mul_add_lt_opow_mul_succ v hw).trans_le (mul_le_mul_left' (succ_le_of_lt hvb) _) - using 1 - exact opow_succ b u - -theorem log_opow_mul_add {b u v w : Ordinal} (hb : 1 < b) (hv : v ≠ 0) (hvb : v < b) - (hw : w < b ^ u) : log b (b ^ u * v + w) = u := by - have hne' := (opow_mul_add_pos (zero_lt_one.trans hb).ne' u hv w).ne' - by_contra! hne - cases' lt_or_gt_of_ne hne with h h - · rw [← lt_opow_iff_log_lt hb hne'] at h - exact h.not_le ((le_mul_left _ (Ordinal.pos_iff_ne_zero.2 hv)).trans (le_add_right _ _)) - · conv at h => change u < log b (b ^ u * v + w) - rw [← succ_le_iff, ← opow_le_iff_le_log hb hne'] at h - exact (not_lt_of_le h) (opow_mul_add_lt_opow_succ hvb hw) +theorem log_eq_iff {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) (y : Ordinal) : + log b x = y ↔ b ^ y ≤ x ∧ x < b ^ succ y := by + constructor + · rintro rfl + use opow_log_le_self b hx, lt_opow_succ_log_self hb x + · rintro ⟨hx₁, hx₂⟩ + apply le_antisymm + · rwa [← lt_succ_iff, ← lt_opow_iff_log_lt hb hx] + · rwa [← opow_le_iff_le_log hb hx] + +theorem log_opow_mul_add {b u v w : Ordinal} (hb : 1 < b) (hv : v ≠ 0) (hw : w < b ^ u) : + log b (b ^ u * v + w) = u + log b v := by + rw [log_eq_iff hb] + · constructor + · rw [opow_add] + exact (mul_le_mul_left' (opow_log_le_self b hv) _).trans (le_add_right _ w) + · apply (add_lt_add_left hw _).trans_le + rw [← mul_succ, ← add_succ, opow_add] + apply mul_le_mul_left' + rw [succ_le_iff] + exact lt_opow_succ_log_self hb _ + · exact fun h ↦ mul_ne_zero (opow_ne_zero u (bot_lt_of_lt hb).ne') hv <| + left_eq_zero_of_add_eq_zero h + +theorem log_opow_mul {b v : Ordinal} (hb : 1 < b) (u : Ordinal) (hv : v ≠ 0) : + log b (b ^ u * v) = u + log b v := by + simpa using log_opow_mul_add hb hv (opow_pos u (bot_lt_of_lt hb)) theorem log_opow {b : Ordinal} (hb : 1 < b) (x : Ordinal) : log b (b ^ x) = x := by - convert log_opow_mul_add hb zero_ne_one.symm hb (opow_pos x (zero_lt_one.trans hb)) - using 1 - rw [add_zero, mul_one] + convert log_opow_mul hb x zero_ne_one.symm using 1 + · rw [mul_one] + · rw [log_one_right, add_zero] theorem div_opow_log_pos (b : Ordinal) {o : Ordinal} (ho : o ≠ 0) : 0 < o / (b ^ log b o) := by rcases eq_zero_or_pos b with (rfl | hb) @@ -386,11 +465,10 @@ theorem div_opow_log_lt {b : Ordinal} (o : Ordinal) (hb : 1 < b) : o / (b ^ log theorem add_log_le_log_mul {x y : Ordinal} (b : Ordinal) (hx : x ≠ 0) (hy : y ≠ 0) : log b x + log b y ≤ log b (x * y) := by - by_cases hb : 1 < b + obtain hb | hb := lt_or_le 1 b · rw [← opow_le_iff_le_log hb (mul_ne_zero hx hy), opow_add] exact mul_le_mul' (opow_log_le_self b hx) (opow_log_le_self b hy) - -- Porting note: `le_refl` is required. - simp only [log_of_not_one_lt_left hb, zero_add, le_refl] + · simpa only [log_of_left_le_one hb, zero_add] using le_rfl /-! ### Interaction with `Nat.cast` -/ @@ -403,7 +481,7 @@ theorem natCast_opow (m : ℕ) : ∀ n : ℕ, ↑(m ^ n : ℕ) = (m : Ordinal) ^ theorem iSup_pow {o : Ordinal} (ho : 0 < o) : ⨆ n : ℕ, o ^ n = o ^ ω := by simp_rw [← opow_natCast] rcases (one_le_iff_pos.2 ho).lt_or_eq with ho₁ | rfl - · exact (opow_isNormal ho₁).apply_omega + · exact (opow_isNormal ho₁).apply_omega0 · rw [one_opow] refine le_antisymm (Ordinal.iSup_le fun n => by rw [one_opow]) ?_ exact_mod_cast Ordinal.le_iSup _ 0 @@ -413,7 +491,7 @@ set_option linter.deprecated false in theorem sup_opow_nat {o : Ordinal} (ho : 0 < o) : (sup fun n : ℕ => o ^ n) = o ^ ω := by simp_rw [← opow_natCast] rcases (one_le_iff_pos.2 ho).lt_or_eq with ho₁ | rfl - · exact (opow_isNormal ho₁).apply_omega + · exact (opow_isNormal ho₁).apply_omega0 · rw [one_opow] refine le_antisymm (sup_le fun n => by rw [one_opow]) ?_ convert le_sup (fun n : ℕ => 1 ^ (n : Ordinal)) 0 diff --git a/Mathlib/SetTheory/Ordinal/FixedPoint.lean b/Mathlib/SetTheory/Ordinal/FixedPoint.lean index 1c8d3dce7bab4..2e5804f50bae6 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPoint.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPoint.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Violeta Hernández Palacios, Mario Carneiro. All rights reser Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios, Mario Carneiro -/ -import Mathlib.SetTheory.Ordinal.Arithmetic +import Mathlib.SetTheory.Ordinal.Enum import Mathlib.SetTheory.Ordinal.Exponential import Mathlib.Logic.UnivLE @@ -22,8 +22,8 @@ Moreover, we prove some lemmas about the fixed points of specific normal functio * `nfpFamily`, `nfpBFamily`, `nfp`: the next fixed point of a (family of) normal function(s). * `fp_family_unbounded`, `fp_bfamily_unbounded`, `fp_unbounded`: the (common) fixed points of a (family of) normal function(s) are unbounded in the ordinals. -* `deriv_add_eq_mul_omega_add`: a characterization of the derivative of addition. -* `deriv_mul_eq_opow_omega_mul`: a characterization of the derivative of multiplication. +* `deriv_add_eq_mul_omega0_add`: a characterization of the derivative of addition. +* `deriv_mul_eq_opow_omega0_mul`: a characterization of the derivative of multiplication. -/ @@ -131,6 +131,14 @@ theorem nfpFamily_eq_self {f : ι → Ordinal → Ordinal} {a} (h : ∀ i, f i a -- Todo: This is actually a special case of the fact the intersection of club sets is a club set. /-- A generalization of the fixed point lemma for normal functions: any family of normal functions has an unbounded set of common fixed points. -/ +theorem not_bddAbove_fp_family (H : ∀ i, IsNormal (f i)) : + ¬ BddAbove (⋂ i, Function.fixedPoints (f i)) := by + rw [not_bddAbove_iff] + refine fun a ↦ ⟨nfpFamily f (succ a), ?_, (lt_succ a).trans_le (le_nfpFamily f _)⟩ + rintro _ ⟨i, rfl⟩ + exact nfpFamily_fp (H i) _ + +@[deprecated not_bddAbove_fp_family (since := "2024-09-20")] theorem fp_family_unbounded (H : ∀ i, IsNormal (f i)) : (⋂ i, Function.fixedPoints (f i)).Unbounded (· < ·) := fun a => ⟨nfpFamily.{u, v} f a, fun s ⟨i, hi⟩ => by @@ -208,7 +216,7 @@ theorem fp_iff_derivFamily (H : ∀ i, IsNormal (f i)) {a} : /-- For a family of normal functions, `Ordinal.derivFamily` enumerates the common fixed points. -/ theorem derivFamily_eq_enumOrd (H : ∀ i, IsNormal (f i)) : derivFamily.{u, v} f = enumOrd (⋂ i, Function.fixedPoints (f i)) := by - rw [← eq_enumOrd _ (fp_family_unbounded.{u, v} H)] + rw [eq_comm, eq_enumOrd _ (not_bddAbove_fp_family H)] use (derivFamily_isNormal f).strictMono rw [Set.range_eq_iff] refine ⟨?_, fun a ha => ?_⟩ @@ -303,6 +311,16 @@ theorem nfpBFamily_eq_self {a} (h : ∀ i hi, f i hi a = a) : nfpBFamily.{u, v} /-- A generalization of the fixed point lemma for normal functions: any family of normal functions has an unbounded set of common fixed points. -/ +theorem not_bddAbove_fp_bfamily (H : ∀ i hi, IsNormal (f i hi)) : + ¬ BddAbove (⋂ (i) (hi), Function.fixedPoints (f i hi)) := by + rw [not_bddAbove_iff] + refine fun a ↦ ⟨nfpBFamily _ f (succ a), ?_, (lt_succ a).trans_le (le_nfpBFamily f _)⟩ + rw [Set.mem_iInter₂] + exact fun i hi ↦ nfpBFamily_fp (H i hi) _ + +/-- A generalization of the fixed point lemma for normal functions: any family of normal functions + has an unbounded set of common fixed points. -/ +@[deprecated not_bddAbove_fp_bfamily (since := "2024-09-20")] theorem fp_bfamily_unbounded (H : ∀ i hi, IsNormal (f i hi)) : (⋂ (i) (hi), Function.fixedPoints (f i hi)).Unbounded (· < ·) := fun a => ⟨nfpBFamily.{u, v} _ f a, by @@ -349,7 +367,7 @@ theorem fp_iff_derivBFamily (H : ∀ i hi, IsNormal (f i hi)) {a} : /-- For a family of normal functions, `Ordinal.derivBFamily` enumerates the common fixed points. -/ theorem derivBFamily_eq_enumOrd (H : ∀ i hi, IsNormal (f i hi)) : derivBFamily.{u, v} o f = enumOrd (⋂ (i) (hi), Function.fixedPoints (f i hi)) := by - rw [← eq_enumOrd _ (fp_bfamily_unbounded.{u, v} H)] + rw [eq_comm, eq_enumOrd _ (not_bddAbove_fp_bfamily H)] use (derivBFamily_isNormal f).strictMono rw [Set.range_eq_iff] refine ⟨fun a => Set.mem_iInter₂.2 fun i hi => derivBFamily_fp (H i hi) a, fun a ha => ?_⟩ @@ -447,6 +465,14 @@ theorem nfp_eq_self {f : Ordinal → Ordinal} {a} (h : f a = a) : nfp f a = a := /-- The fixed point lemma for normal functions: any normal function has an unbounded set of fixed points. -/ +theorem not_bddAbove_fp (H : IsNormal f) : ¬ BddAbove (Function.fixedPoints f) := by + convert not_bddAbove_fp_family fun _ : Unit => H + exact (Set.iInter_const _).symm + +set_option linter.deprecated false in +/-- The fixed point lemma for normal functions: any normal function has an unbounded set of +fixed points. -/ +@[deprecated not_bddAbove_fp (since := "2024-09-20")] theorem fp_unbounded (H : IsNormal f) : (Function.fixedPoints f).Unbounded (· < ·) := by convert fp_family_unbounded fun _ : Unit => H exact (Set.iInter_const _).symm @@ -523,20 +549,23 @@ end /-! ### Fixed points of addition -/ @[simp] -theorem nfp_add_zero (a) : nfp (a + ·) 0 = a * omega := by +theorem nfp_add_zero (a) : nfp (a + ·) 0 = a * ω := by simp_rw [← iSup_iterate_eq_nfp, ← iSup_mul_nat] congr; funext n induction' n with n hn · rw [Nat.cast_zero, mul_zero, iterate_zero_apply] · rw [iterate_succ_apply', Nat.add_comm, Nat.cast_add, Nat.cast_one, mul_one_add, hn] -theorem nfp_add_eq_mul_omega {a b} (hba : b ≤ a * omega) : nfp (a + ·) b = a * omega := by +theorem nfp_add_eq_mul_omega0 {a b} (hba : b ≤ a * ω) : nfp (a + ·) b = a * ω := by apply le_antisymm (nfp_le_fp (add_isNormal a).monotone hba _) · rw [← nfp_add_zero] exact nfp_monotone (add_isNormal a).monotone (Ordinal.zero_le b) - · dsimp; rw [← mul_one_add, one_add_omega] + · dsimp; rw [← mul_one_add, one_add_omega0] + +@[deprecated (since := "2024-09-30")] +alias nfp_add_eq_mul_omega := nfp_add_eq_mul_omega0 -theorem add_eq_right_iff_mul_omega_le {a b : Ordinal} : a + b = b ↔ a * omega ≤ b := by +theorem add_eq_right_iff_mul_omega0_le {a b : Ordinal} : a + b = b ↔ a * ω ≤ b := by refine ⟨fun h => ?_, fun h => ?_⟩ · rw [← nfp_add_zero a, ← deriv_zero_right] cases' (add_isNormal a).fp_iff_deriv.1 h with c hc @@ -544,25 +573,34 @@ theorem add_eq_right_iff_mul_omega_le {a b : Ordinal} : a + b = b ↔ a * omega exact (deriv_isNormal _).monotone (Ordinal.zero_le _) · have := Ordinal.add_sub_cancel_of_le h nth_rw 1 [← this] - rwa [← add_assoc, ← mul_one_add, one_add_omega] + rwa [← add_assoc, ← mul_one_add, one_add_omega0] -theorem add_le_right_iff_mul_omega_le {a b : Ordinal} : a + b ≤ b ↔ a * omega ≤ b := by - rw [← add_eq_right_iff_mul_omega_le] +@[deprecated (since := "2024-09-30")] +alias add_eq_right_iff_mul_omega_le := add_eq_right_iff_mul_omega0_le + +theorem add_le_right_iff_mul_omega0_le {a b : Ordinal} : a + b ≤ b ↔ a * ω ≤ b := by + rw [← add_eq_right_iff_mul_omega0_le] exact (add_isNormal a).le_iff_eq -theorem deriv_add_eq_mul_omega_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * omega + b := by +@[deprecated (since := "2024-09-30")] +alias add_le_right_iff_mul_omega_le := add_le_right_iff_mul_omega0_le + +theorem deriv_add_eq_mul_omega0_add (a b : Ordinal.{u}) : deriv (a + ·) b = a * ω + b := by revert b rw [← funext_iff, IsNormal.eq_iff_zero_and_succ (deriv_isNormal _) (add_isNormal _)] refine ⟨?_, fun a h => ?_⟩ · rw [deriv_zero_right, add_zero] exact nfp_add_zero a · rw [deriv_succ, h, add_succ] - exact nfp_eq_self (add_eq_right_iff_mul_omega_le.2 ((le_add_right _ _).trans (le_succ _))) + exact nfp_eq_self (add_eq_right_iff_mul_omega0_le.2 ((le_add_right _ _).trans (le_succ _))) + +@[deprecated (since := "2024-09-30")] +alias deriv_add_eq_mul_omega_add := deriv_add_eq_mul_omega0_add /-! ### Fixed points of multiplication -/ @[simp] -theorem nfp_mul_one {a : Ordinal} (ha : 0 < a) : nfp (a * ·) 1 = (a^omega) := by +theorem nfp_mul_one {a : Ordinal} (ha : 0 < a) : nfp (a * ·) 1 = (a ^ ω) := by rw [← iSup_iterate_eq_nfp, ← iSup_pow ha] congr funext n @@ -577,22 +615,25 @@ theorem nfp_mul_zero (a : Ordinal) : nfp (a * ·) 0 = 0 := by induction' n with n hn; · rfl dsimp only; rwa [iterate_succ_apply, mul_zero] -theorem nfp_mul_eq_opow_omega {a b : Ordinal} (hb : 0 < b) (hba : b ≤ (a^omega)) : - nfp (a * ·) b = (a^omega.{u}) := by +theorem nfp_mul_eq_opow_omega0 {a b : Ordinal} (hb : 0 < b) (hba : b ≤ (a ^ ω)) : + nfp (a * ·) b = (a ^ (ω : Ordinal.{u})) := by rcases eq_zero_or_pos a with ha | ha - · rw [ha, zero_opow omega_ne_zero] at hba ⊢ + · rw [ha, zero_opow omega0_ne_zero] at hba ⊢ simp_rw [Ordinal.le_zero.1 hba, zero_mul] exact nfp_zero_left 0 apply le_antisymm · apply nfp_le_fp (mul_isNormal ha).monotone hba - rw [← opow_one_add, one_add_omega] + rw [← opow_one_add, one_add_omega0] rw [← nfp_mul_one ha] exact nfp_monotone (mul_isNormal ha).monotone (one_le_iff_pos.2 hb) -theorem eq_zero_or_opow_omega_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = b) : - b = 0 ∨ (a^omega.{u}) ≤ b := by +@[deprecated (since := "2024-09-30")] +alias nfp_mul_eq_opow_omega := nfp_mul_eq_opow_omega0 + +theorem eq_zero_or_opow_omega0_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = b) : + b = 0 ∨ (a ^ (ω : Ordinal.{u})) ≤ b := by rcases eq_zero_or_pos a with ha | ha - · rw [ha, zero_opow omega_ne_zero] + · rw [ha, zero_opow omega0_ne_zero] exact Or.inr (Ordinal.zero_le b) rw [or_iff_not_imp_left] intro hb @@ -600,51 +641,66 @@ theorem eq_zero_or_opow_omega_le_of_mul_eq_right {a b : Ordinal} (hab : a * b = rw [← Ne, ← one_le_iff_ne_zero] at hb exact nfp_le_fp (mul_isNormal ha).monotone hb (le_of_eq hab) -theorem mul_eq_right_iff_opow_omega_dvd {a b : Ordinal} : a * b = b ↔ (a^omega) ∣ b := by +@[deprecated (since := "2024-09-30")] +alias eq_zero_or_opow_omega_le_of_mul_eq_right := eq_zero_or_opow_omega0_le_of_mul_eq_right + +theorem mul_eq_right_iff_opow_omega0_dvd {a b : Ordinal} : a * b = b ↔ (a ^ ω) ∣ b := by rcases eq_zero_or_pos a with ha | ha - · rw [ha, zero_mul, zero_opow omega_ne_zero, zero_dvd_iff] + · rw [ha, zero_mul, zero_opow omega0_ne_zero, zero_dvd_iff] exact eq_comm refine ⟨fun hab => ?_, fun h => ?_⟩ · rw [dvd_iff_mod_eq_zero] - rw [← div_add_mod b (a^omega), mul_add, ← mul_assoc, ← opow_one_add, one_add_omega, + rw [← div_add_mod b (a ^ ω), mul_add, ← mul_assoc, ← opow_one_add, one_add_omega0, add_left_cancel] at hab - cases' eq_zero_or_opow_omega_le_of_mul_eq_right hab with hab hab + cases' eq_zero_or_opow_omega0_le_of_mul_eq_right hab with hab hab · exact hab - refine (not_lt_of_le hab (mod_lt b (opow_ne_zero omega ?_))).elim + refine (not_lt_of_le hab (mod_lt b (opow_ne_zero ω ?_))).elim rwa [← Ordinal.pos_iff_ne_zero] cases' h with c hc - rw [hc, ← mul_assoc, ← opow_one_add, one_add_omega] + rw [hc, ← mul_assoc, ← opow_one_add, one_add_omega0] -theorem mul_le_right_iff_opow_omega_dvd {a b : Ordinal} (ha : 0 < a) : - a * b ≤ b ↔ (a^omega) ∣ b := by - rw [← mul_eq_right_iff_opow_omega_dvd] +@[deprecated (since := "2024-09-30")] +alias mul_eq_right_iff_opow_omega_dvd := mul_eq_right_iff_opow_omega0_dvd + +theorem mul_le_right_iff_opow_omega0_dvd {a b : Ordinal} (ha : 0 < a) : + a * b ≤ b ↔ (a ^ ω) ∣ b := by + rw [← mul_eq_right_iff_opow_omega0_dvd] exact (mul_isNormal ha).le_iff_eq -theorem nfp_mul_opow_omega_add {a c : Ordinal} (b) (ha : 0 < a) (hc : 0 < c) (hca : c ≤ (a^omega)) : - nfp (a * ·) ((a^omega) * b + c) = (a^omega.{u}) * succ b := by +@[deprecated (since := "2024-09-30")] +alias mul_le_right_iff_opow_omega_dvd := mul_le_right_iff_opow_omega0_dvd + +theorem nfp_mul_opow_omega0_add {a c : Ordinal} (b) (ha : 0 < a) (hc : 0 < c) + (hca : c ≤ a ^ ω) : nfp (a * ·) (a ^ ω * b + c) = (a ^ (ω : Ordinal.{u})) * succ b := by apply le_antisymm · apply nfp_le_fp (mul_isNormal ha).monotone · rw [mul_succ] apply add_le_add_left hca - · dsimp only; rw [← mul_assoc, ← opow_one_add, one_add_omega] - · cases' mul_eq_right_iff_opow_omega_dvd.1 ((mul_isNormal ha).nfp_fp ((a^omega) * b + c)) with + · dsimp only; rw [← mul_assoc, ← opow_one_add, one_add_omega0] + · cases' mul_eq_right_iff_opow_omega0_dvd.1 ((mul_isNormal ha).nfp_fp ((a ^ ω) * b + c)) with d hd rw [hd] apply mul_le_mul_left' - have := le_nfp (Mul.mul a) ((a^omega) * b + c) - erw [hd] at this - have := (add_lt_add_left hc ((a^omega) * b)).trans_le this - rw [add_zero, mul_lt_mul_iff_left (opow_pos omega ha)] at this + have := le_nfp (a * ·) (a ^ ω * b + c) + rw [hd] at this + have := (add_lt_add_left hc (a ^ ω * b)).trans_le this + rw [add_zero, mul_lt_mul_iff_left (opow_pos ω ha)] at this rwa [succ_le_iff] -theorem deriv_mul_eq_opow_omega_mul {a : Ordinal.{u}} (ha : 0 < a) (b) : - deriv (a * ·) b = (a^omega) * b := by +@[deprecated (since := "2024-09-30")] +alias nfp_mul_opow_omega_add := nfp_mul_opow_omega0_add + +theorem deriv_mul_eq_opow_omega0_mul {a : Ordinal.{u}} (ha : 0 < a) (b) : + deriv (a * ·) b = (a ^ ω) * b := by revert b rw [← funext_iff, - IsNormal.eq_iff_zero_and_succ (deriv_isNormal _) (mul_isNormal (opow_pos omega ha))] + IsNormal.eq_iff_zero_and_succ (deriv_isNormal _) (mul_isNormal (opow_pos ω ha))] refine ⟨?_, fun c h => ?_⟩ · dsimp only; rw [deriv_zero_right, nfp_mul_zero, mul_zero] · rw [deriv_succ, h] - exact nfp_mul_opow_omega_add c ha zero_lt_one (one_le_iff_pos.2 (opow_pos _ ha)) + exact nfp_mul_opow_omega0_add c ha zero_lt_one (one_le_iff_pos.2 (opow_pos _ ha)) + +@[deprecated (since := "2024-09-30")] +alias deriv_mul_eq_opow_omega_mul := deriv_mul_eq_opow_omega0_mul end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean index 7cb80b64b2db5..97272de665f4f 100644 --- a/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean +++ b/Mathlib/SetTheory/Ordinal/FixedPointApproximants.lean @@ -8,7 +8,7 @@ import Mathlib.SetTheory.Ordinal.Arithmetic /-! # Ordinal Approximants for the Fixed points on complete lattices -This file sets up the ordinal approximation theory of fixed points +This file sets up the ordinal-indexed approximation theory of fixed points of a monotone function in a complete lattice [Cousot1979]. The proof follows loosely the one from [Echenique2005]. @@ -17,15 +17,15 @@ ordinals from mathlib. It still allows an approximation scheme indexed over the ## Main definitions -* `OrdinalApprox.lfpApprox`: The ordinal approximation of the least fixed point - greater or equal then an initial value of a bundled monotone function. -* `OrdinalApprox.gfpApprox`: The ordinal approximation of the greatest fixed point - less or equal then an initial value of a bundled monotone function. +* `OrdinalApprox.lfpApprox`: The ordinal-indexed approximation of the least fixed point + greater or equal than an initial value of a bundled monotone function. +* `OrdinalApprox.gfpApprox`: The ordinal-indexed approximation of the greatest fixed point + less or equal than an initial value of a bundled monotone function. ## Main theorems -* `OrdinalApprox.lfp_mem_range_lfpApprox`: The approximation of +* `OrdinalApprox.lfp_mem_range_lfpApprox`: The ordinal-indexed approximation of the least fixed point eventually reaches the least fixed point -* `OrdinalApprox.gfp_mem_range_gfpApprox`: The approximation of +* `OrdinalApprox.gfp_mem_range_gfpApprox`: The ordinal-indexed approximation of the greatest fixed point eventually reaches the greatest fixed point ## References @@ -50,12 +50,10 @@ theorem not_injective_limitation_set : ¬ InjOn g (Iio (ord <| succ #α)) := by have h := lift_mk_le_lift_mk_of_injective <| injOn_iff_injective.1 h_inj have mk_initialSeg_subtype : #(Iio (ord <| succ #α)) = lift.{u + 1} (succ #α) := by - simpa only [coe_setOf, card_typein, card_ord] using mk_initialSeg (ord <| succ #α) + simpa only [coe_setOf, card_typein, card_ord] using mk_Iio_ordinal (ord <| succ #α) rw [mk_initialSeg_subtype, lift_lift, lift_le] at h exact not_le_of_lt (Order.lt_succ #α) h - - end Cardinal namespace OrdinalApprox @@ -67,14 +65,17 @@ variable [CompleteLattice α] (f : α →o α) (x : α) open Function fixedPoints Cardinal Order OrderHom set_option linter.unusedVariables false in -/-- Ordinal approximants of the least fixed point greater then an initial value x -/ +/-- The ordinal-indexed sequence approximating the least fixed point greater than +an initial value `x`. It is defined in such a way that we have `lfpApprox 0 x = x` and +`lfpApprox a x = ⨆ b < a, f (lfpApprox b x)`. -/ def lfpApprox (a : Ordinal.{u}) : α := sSup ({ f (lfpApprox b) | (b : Ordinal) (h : b < a) } ∪ {x}) termination_by a decreasing_by exact h theorem lfpApprox_monotone : Monotone (lfpApprox f x) := by - unfold Monotone; intros a b h; unfold lfpApprox + intros a b h + rw [lfpApprox, lfpApprox] refine sSup_le_sSup ?h apply sup_le_sup_right simp only [exists_prop, Set.le_eq_subset, Set.setOf_subset_setOf, forall_exists_index, and_imp, @@ -84,14 +85,14 @@ theorem lfpApprox_monotone : Monotone (lfpApprox f x) := by exact ⟨lt_of_lt_of_le h' h, rfl⟩ theorem le_lfpApprox {a : Ordinal} : x ≤ lfpApprox f x a := by - unfold lfpApprox + rw [lfpApprox] apply le_sSup simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, true_or] theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : lfpApprox f x (a+1) = f (lfpApprox f x a) := by apply le_antisymm - · conv => left; unfold lfpApprox + · conv => left; rw [lfpApprox] apply sSup_le simp only [Ordinal.add_one_eq_succ, lt_succ_iff, exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, forall_eq_or_imp, forall_exists_index, and_imp, @@ -102,7 +103,7 @@ theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : exact le_lfpApprox f x · intros a' h apply f.2; apply lfpApprox_monotone; exact h - · conv => right; unfold lfpApprox + · conv => right; rw [lfpApprox] apply le_sSup simp only [Ordinal.add_one_eq_succ, lt_succ_iff, exists_prop] rw [Set.mem_union] @@ -110,14 +111,46 @@ theorem lfpApprox_add_one (h : x ≤ f x) (a : Ordinal) : simp only [Set.mem_setOf_eq] use a -/-- The ordinal approximants of the least fixed point are stabilizing - when reaching a fixed point of f -/ +theorem lfpApprox_mono_left : Monotone (lfpApprox : (α →o α) → _) := by + intro f g h x a + induction a using Ordinal.induction with + | h i ih => + rw [lfpApprox, lfpApprox] + apply sSup_le + simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert, + forall_eq_or_imp, le_sup_left, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, + true_and] + intro i' h_lt + apply le_sup_of_le_right + apply le_sSup_of_le + · use i' + · apply le_trans (h _) + simp only [OrderHom.toFun_eq_coe] + exact g.monotone (ih i' h_lt) + +theorem lfpApprox_mono_mid : Monotone (lfpApprox f) := by + intro x₁ x₂ h a + induction a using Ordinal.induction with + | h i ih => + rw [lfpApprox, lfpApprox] + apply sSup_le + simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, sSup_insert, + forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] + constructor + · exact le_sup_of_le_left h + · intro i' h_i' + apply le_sup_of_le_right + apply le_sSup_of_le + · use i' + · exact f.monotone (ih i' h_i') + +/-- The approximations of the least fixed point stabilize at a fixed point of `f` -/ theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ab : a ≤ b) (h : lfpApprox f x a ∈ fixedPoints f) : lfpApprox f x b = lfpApprox f x a := by rw [mem_fixedPoints_iff] at h induction b using Ordinal.induction with | h b IH => apply le_antisymm - · conv => left; unfold lfpApprox + · conv => left; rw [lfpApprox] apply sSup_le simp only [exists_prop, Set.union_singleton, Set.mem_insert_iff, Set.mem_setOf_eq, forall_eq_or_imp, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂] @@ -131,8 +164,8 @@ theorem lfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : x ≤ f x) (h_ · rw [IH a' ha'b (le_of_not_lt haa), h] · exact lfpApprox_monotone f x h_ab -/-- There are distinct ordinals smaller than the successor of the domains cardinals - with equal value -/ +/-- There are distinct indices smaller than the successor of the domain's cardinality +yielding the same value -/ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α, a ≠ b ∧ lfpApprox f x a = lfpApprox f x b := by have h_ninj := not_injective_limitation_set <| lfpApprox f x @@ -144,8 +177,8 @@ theorem exists_lfpApprox_eq_lfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| · intro h_eq; rw [Subtype.coe_inj] at h_eq; exact h_nab h_eq · exact h_fab -/-- If there are distinct ordinals with equal value then - every value succeeding the smaller ordinal are fixed points -/ +/-- If the sequence of ordinal-indexed approximations takes a value twice, +then it actually stabilised at that value. -/ lemma lfpApprox_mem_fixedPoints_of_eq {a b c : Ordinal} (h_init : x ≤ f x) (h_ab : a < b) (h_ac : a ≤ c) (h_fab : lfpApprox f x a = lfpApprox f x b) : lfpApprox f x c ∈ fixedPoints f := by @@ -159,7 +192,7 @@ lemma lfpApprox_mem_fixedPoints_of_eq {a b c : Ordinal} · exact h_ac · exact lfpApprox_mem_fixedPoint -/-- A fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/ theorem lfpApprox_ord_mem_fixedPoint (h_init : x ≤ f x) : lfpApprox f x (ord <| succ #α) ∈ fixedPoints f := by let ⟨a, h_a, b, h_b, h_nab, h_fab⟩ := exists_lfpApprox_eq_lfpApprox f x @@ -171,13 +204,13 @@ theorem lfpApprox_ord_mem_fixedPoint (h_init : x ≤ f x) : exact lfpApprox_mem_fixedPoints_of_eq f x h_init (h_nab.symm.lt_of_le h_ba) (le_of_lt h_b) (h_fab.symm) -/-- Every value of the ordinal approximants are less or equal than every fixed point of f greater - then the initial value -/ +/-- Every value of the approximation is less or equal than every fixed point of `f` +greater or equal than the initial value -/ theorem lfpApprox_le_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : x ≤ a) (i : Ordinal) : lfpApprox f x i ≤ a := by induction i using Ordinal.induction with | h i IH => - unfold lfpApprox + rw [lfpApprox] apply sSup_le simp only [exists_prop] intro y h_y @@ -186,13 +219,13 @@ theorem lfpApprox_le_of_mem_fixedPoints {a : α} | inl h_y => let ⟨j, h_j_lt, h_j⟩ := h_y rw [← h_j, ← h_a] - apply f.monotone' - exact IH j h_j_lt + exact f.monotone' (IH j h_j_lt) | inr h_y => rw [h_y] exact h_le_init -/-- The least fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation sequence converges at the successor of the domain's cardinality +to the least fixed point if starting from `⊥` -/ theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by apply le_antisymm · have h_lfp : ∃ y : fixedPoints f, lfp f = y := by use ⊥; exact rfl @@ -204,13 +237,15 @@ theorem lfpApprox_ord_eq_lfp : lfpApprox f ⊥ (ord <| succ #α) = lfp f := by let ⟨x, h_x⟩ := h_fix; rw [h_x] exact lfp_le_fixed f x.prop -/-- Some ordinal approximation of the least fixed point is the least fixed point. -/ +/-- Some approximation of the least fixed point starting from `⊥` is the least fixed point. -/ theorem lfp_mem_range_lfpApprox : lfp f ∈ Set.range (lfpApprox f ⊥) := by use ord <| succ #α exact lfpApprox_ord_eq_lfp f set_option linter.unusedVariables false in -/-- Ordinal approximants of the greatest fixed point -/ +/-- The ordinal-indexed sequence approximating the greatest fixed point greater than +an initial value `x`. It is defined in such a way that we have `gfpApprox 0 x = x` and +`gfpApprox a x = ⨅ b < a, f (lfpApprox b x)`. -/ def gfpApprox (a : Ordinal.{u}) : α := sInf ({ f (gfpApprox b) | (b : Ordinal) (h : b < a) } ∪ {x}) termination_by a @@ -230,34 +265,42 @@ theorem gfpApprox_add_one (h : f x ≤ x) (a : Ordinal) : gfpApprox f x (a+1) = f (gfpApprox f x a) := lfpApprox_add_one (OrderHom.dual f) x h a -/-- The ordinal approximants of the least fixed point are stabilizing - when reaching a fixed point of f -/ +theorem gfpApprox_mono_left : Monotone (gfpApprox : (α →o α) → _) := by + intro f g h + have : OrderHom.dual g ≤ OrderHom.dual f := h + exact lfpApprox_mono_left this + +theorem gfpApprox_mono_mid : Monotone (gfpApprox f) := + fun _ _ h => lfpApprox_mono_mid (OrderHom.dual f) h + +/-- The approximations of the greatest fixed point stabilize at a fixed point of `f` -/ theorem gfpApprox_eq_of_mem_fixedPoints {a b : Ordinal} (h_init : f x ≤ x) (h_ab : a ≤ b) (h : gfpApprox f x a ∈ fixedPoints f) : gfpApprox f x b = gfpApprox f x a := lfpApprox_eq_of_mem_fixedPoints (OrderHom.dual f) x h_init h_ab h -/-- There are distinct ordinals smaller than the successor of the domains cardinals with - equal value -/ +/-- There are distinct indices smaller than the successor of the domain's cardinality +yielding the same value -/ theorem exists_gfpApprox_eq_gfpApprox : ∃ a < ord <| succ #α, ∃ b < ord <| succ #α, a ≠ b ∧ gfpApprox f x a = gfpApprox f x b := exists_lfpApprox_eq_lfpApprox (OrderHom.dual f) x -/-- A fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation at the index of the successor of the domain's cardinality is a fixed point -/ lemma gfpApprox_ord_mem_fixedPoint (h_init : f x ≤ x) : gfpApprox f x (ord <| succ #α) ∈ fixedPoints f := lfpApprox_ord_mem_fixedPoint (OrderHom.dual f) x h_init -/-- Every value of the ordinal approximants are greater or equal than every fixed point of f - that is smaller then the initial value -/ +/-- Every value of the approximation is greater or equal than every fixed point of `f` +less or equal than the initial value -/ lemma le_gfpApprox_of_mem_fixedPoints {a : α} (h_a : a ∈ fixedPoints f) (h_le_init : a ≤ x) (i : Ordinal) : a ≤ gfpApprox f x i := lfpApprox_le_of_mem_fixedPoints (OrderHom.dual f) x h_a h_le_init i -/-- The greatest fixed point of f is reached after the successor of the domains cardinality -/ +/-- The approximation sequence converges at the successor of the domain's cardinality +to the greatest fixed point if starting from `⊥` -/ theorem gfpApprox_ord_eq_gfp : gfpApprox f ⊤ (ord <| succ #α) = gfp f := lfpApprox_ord_eq_lfp (OrderHom.dual f) -/-- Some ordinal approximation of the greatest fixed point is the greatest fixed point. -/ +/-- Some approximation of the least fixed point starting from `⊤` is the greatest fixed point. -/ theorem gfp_mem_range_gfpApprox : gfp f ∈ Set.range (gfpApprox f ⊤) := lfp_mem_range_lfpApprox (OrderHom.dual f) diff --git a/Mathlib/SetTheory/Ordinal/Nimber.lean b/Mathlib/SetTheory/Ordinal/Nimber.lean index 538d61ec4400d..8a3f05befdbaa 100644 --- a/Mathlib/SetTheory/Ordinal/Nimber.lean +++ b/Mathlib/SetTheory/Ordinal/Nimber.lean @@ -3,6 +3,7 @@ Copyright (c) 2024 Violeta Hernández Palacios. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios -/ +import Mathlib.Data.Nat.Bitwise import Mathlib.SetTheory.Ordinal.Arithmetic /-! @@ -19,6 +20,12 @@ impartial game is equivalent to some game of nim. If `x ≈ nim o₁` and `y ≈ `x + y ≈ nim (o₁ + o₂)`, where the ordinals are summed together as nimbers. Unfortunately, the nim product admits no such characterization. +## Notation + +Following [On Numbers And Games][conway2001] (p. 121), we define notation `∗o` for the cast from +`Ordinal` to `Nimber`. Note that for general `n : ℕ`, `∗n` is **not** the same as `↑n`. For +instance, `∗2 ≠ 0`, whereas `↑2 = ↑1 + ↑1 = 0`. + ## Implementation notes The nimbers inherit the order from the ordinals - this makes working with minimum excluded values @@ -65,6 +72,9 @@ def Ordinal.toNimber : Ordinal ≃o Nimber := def Nimber.toOrdinal : Nimber ≃o Ordinal := OrderIso.refl _ +@[inherit_doc] +scoped[Nimber] prefix:75 "∗" => Ordinal.toNimber + namespace Nimber open Ordinal @@ -74,8 +84,8 @@ theorem toOrdinal_symm_eq : Nimber.toOrdinal.symm = Ordinal.toNimber := rfl @[simp] -theorem toOrdinal_toNimber (a : Nimber) : - Ordinal.toNimber (Nimber.toOrdinal a) = a := rfl +theorem toOrdinal_toNimber (a : Nimber) : ∗(Nimber.toOrdinal a) = a := + rfl theorem lt_wf : @WellFounded Nimber (· < ·) := Ordinal.lt_wf @@ -102,27 +112,27 @@ theorem toOrdinal_one : toOrdinal 1 = 1 := rfl @[simp] -theorem toOrdinal_eq_zero (a) : toOrdinal a = 0 ↔ a = 0 := +theorem toOrdinal_eq_zero {a} : toOrdinal a = 0 ↔ a = 0 := Iff.rfl @[simp] -theorem toOrdinal_eq_one (a) : toOrdinal a = 1 ↔ a = 1 := +theorem toOrdinal_eq_one {a} : toOrdinal a = 1 ↔ a = 1 := Iff.rfl @[simp] -theorem toOrdinal_max {a b : Nimber} : toOrdinal (max a b) = max (toOrdinal a) (toOrdinal b) := +theorem toOrdinal_max (a b : Nimber) : toOrdinal (max a b) = max (toOrdinal a) (toOrdinal b) := rfl @[simp] -theorem toOrdinal_min {a b : Nimber} : toOrdinal (min a b) = min (toOrdinal a) (toOrdinal b) := +theorem toOrdinal_min (a b : Nimber) : toOrdinal (min a b) = min (toOrdinal a) (toOrdinal b) := rfl -theorem succ_def (a : Nimber) : succ a = toNimber (toOrdinal a + 1) := +theorem succ_def (a : Nimber) : succ a = ∗(toOrdinal a + 1) := rfl /-- A recursor for `Nimber`. Use as `induction x`. -/ @[elab_as_elim, cases_eliminator, induction_eliminator] -protected def rec {β : Nimber → Sort*} (h : ∀ a, β (toNimber a)) : ∀ a, β a := fun a => +protected def rec {β : Nimber → Sort*} (h : ∀ a, β (∗a)) : ∀ a, β a := fun a => h (toOrdinal a) /-- `Ordinal.induction` but for `Nimber`. -/ @@ -138,6 +148,9 @@ protected theorem not_lt_zero (a : Nimber) : ¬ a < 0 := protected theorem pos_iff_ne_zero {a : Nimber} : 0 < a ↔ a ≠ 0 := Ordinal.pos_iff_ne_zero +theorem eq_nat_of_le_nat {a : Nimber} {b : ℕ} (h : a ≤ ∗b) : ∃ c : ℕ, a = ∗c := + Ordinal.lt_omega0.1 (h.trans_lt (nat_lt_omega0 b)) + instance small_Iio (a : Nimber.{u}) : Small.{u} (Set.Iio a) := Ordinal.small_Iio a instance small_Iic (a : Nimber.{u}) : Small.{u} (Set.Iic a) := Ordinal.small_Iic a instance small_Ico (a b : Nimber.{u}) : Small.{u} (Set.Ico a b) := Ordinal.small_Ico a b @@ -150,42 +163,40 @@ end Nimber theorem not_small_nimber : ¬ Small.{u} Nimber.{max u v} := not_small_ordinal -namespace Ordinal +open Nimber -variable {a b c : Ordinal.{u}} +namespace Ordinal @[simp] theorem toNimber_symm_eq : toNimber.symm = Nimber.toOrdinal := rfl @[simp] -theorem toNimber_toOrdinal (a : Ordinal) : Nimber.toOrdinal (toNimber a) = a := +theorem toNimber_toOrdinal (a : Ordinal) : Nimber.toOrdinal (∗a) = a := rfl @[simp] -theorem toNimber_zero : toNimber 0 = 0 := +theorem toNimber_zero : ∗0 = 0 := rfl @[simp] -theorem toNimber_one : toNimber 1 = 1 := +theorem toNimber_one : ∗1 = 1 := rfl @[simp] -theorem toNimber_eq_zero (a) : toNimber a = 0 ↔ a = 0 := +theorem toNimber_eq_zero {a} : ∗a = 0 ↔ a = 0 := Iff.rfl @[simp] -theorem toNimber_eq_one (a) : toNimber a = 1 ↔ a = 1 := +theorem toNimber_eq_one {a} : ∗a = 1 ↔ a = 1 := Iff.rfl @[simp] -theorem toNimber_max (a b : Ordinal) : - toNimber (max a b) = max (toNimber a) (toNimber b) := +theorem toNimber_max (a b : Ordinal) : ∗(max a b) = max (∗a) (∗b) := rfl @[simp] -theorem toNimber_min (a b : Ordinal) : - toNimber (min a b) = min (toNimber a) (toNimber b) := +theorem toNimber_min (a b : Ordinal) : ∗(min a b) = min (∗a) (∗b) := rfl end Ordinal @@ -358,4 +369,25 @@ theorem add_trichotomy {a b c : Nimber} (h : a + b + c ≠ 0) : · rw [← hx'] at hx exact Or.inr <| Or.inr hx +/-- Nimber addition of naturals corresponds to the bitwise XOR operation. -/ +theorem add_nat (a b : ℕ) : ∗a + ∗b = ∗(a ^^^ b) := by + apply le_antisymm + · apply add_le_of_forall_ne + all_goals + intro c hc + obtain ⟨c, rfl⟩ := eq_nat_of_le_nat hc.le + rw [OrderIso.lt_iff_lt] at hc + replace hc := Nat.cast_lt.1 hc + rw [add_nat] + simpa using hc.ne + · apply le_of_not_lt + intro hc + obtain ⟨c, hc'⟩ := eq_nat_of_le_nat hc.le + rw [hc', OrderIso.lt_iff_lt, Nat.cast_lt] at hc + obtain h | h := Nat.lt_xor_cases hc + · apply h.ne + simpa [Nat.xor_comm, Nat.xor_cancel_left, ← hc'] using add_nat (c ^^^ b) b + · apply h.ne + simpa [Nat.xor_comm, Nat.xor_cancel_left, ← hc'] using add_nat a (c ^^^ a) + end Nimber diff --git a/Mathlib/SetTheory/Ordinal/Notation.lean b/Mathlib/SetTheory/Ordinal/Notation.lean index d32c08e3c86d1..fd54a141e2131 100644 --- a/Mathlib/SetTheory/Ordinal/Notation.lean +++ b/Mathlib/SetTheory/Ordinal/Notation.lean @@ -139,12 +139,15 @@ theorem repr_ofNat (n : ℕ) : repr (ofNat n) = n := by cases n <;> simp -- @[simp] -- Porting note (#10618): simp can prove this theorem repr_one : repr (ofNat 1) = (1 : ℕ) := repr_ofNat 1 -theorem omega_le_oadd (e n a) : ω ^ repr e ≤ repr (oadd e n a) := by +theorem omega0_le_oadd (e n a) : ω ^ repr e ≤ repr (oadd e n a) := by refine le_trans ?_ (le_add_right _ _) - simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos (repr e) omega_pos).2 (natCast_le.2 n.2) + simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos (repr e) omega0_pos).2 (natCast_le.2 n.2) + +@[deprecated (since := "2024-09-30")] +alias omega_le_oadd := omega0_le_oadd theorem oadd_pos (e n a) : 0 < oadd e n a := - @lt_of_lt_of_le _ _ _ (ω ^ repr e) _ (opow_pos (repr e) omega_pos) (omega_le_oadd e n a) + @lt_of_lt_of_le _ _ _ (ω ^ repr e) _ (opow_pos (repr e) omega0_pos) (omega0_le_oadd e n a) /-- Compare ordinal notations -/ def cmp : ONote → ONote → Ordering @@ -231,14 +234,14 @@ theorem NF.zero_of_zero {e n a} (h : NF (ONote.oadd e n a)) (e0 : e = 0) : a = 0 theorem NFBelow.repr_lt {o b} (h : NFBelow o b) : repr o < ω ^ b := by induction h with - | zero => exact opow_pos _ omega_pos + | zero => exact opow_pos _ omega0_pos | oadd' _ _ h₃ _ IH => rw [repr] apply ((add_lt_add_iff_left _).2 IH).trans_le rw [← mul_succ] - apply (mul_le_mul_left' (succ_le_of_lt (nat_lt_omega _)) _).trans + apply (mul_le_mul_left' (succ_le_of_lt (nat_lt_omega0 _)) _).trans rw [← opow_succ] - exact opow_le_opow_right omega_pos (succ_le_of_lt h₃) + exact opow_le_opow_right omega0_pos (succ_le_of_lt h₃) theorem NFBelow.mono {o b₁ b₂} (bb : b₁ ≤ b₂) (h : NFBelow o b₁) : NFBelow o b₂ := by induction h with @@ -253,7 +256,7 @@ theorem NF.below_of_lt' : ∀ {o b}, repr o < ω ^ b → NF o → NFBelow o b | 0, _, _, _ => NFBelow.zero | ONote.oadd _ _ _, _, H, h => h.below_of_lt <| - (opow_lt_opow_iff_right one_lt_omega).1 <| lt_of_le_of_lt (omega_le_oadd _ _ _) H + (opow_lt_opow_iff_right one_lt_omega0).1 <| lt_of_le_of_lt (omega0_le_oadd _ _ _) H theorem nfBelow_ofNat : ∀ n, NFBelow (ofNat n) 1 | 0 => NFBelow.zero @@ -267,13 +270,13 @@ instance nf_one : NF 1 := by rw [← ofNat_one]; infer_instance theorem oadd_lt_oadd_1 {e₁ n₁ o₁ e₂ n₂ o₂} (h₁ : NF (oadd e₁ n₁ o₁)) (h : e₁ < e₂) : oadd e₁ n₁ o₁ < oadd e₂ n₂ o₂ := @lt_of_lt_of_le _ _ (repr (oadd e₁ n₁ o₁)) _ _ - (NF.below_of_lt h h₁).repr_lt (omega_le_oadd e₂ n₂ o₂) + (NF.below_of_lt h h₁).repr_lt (omega0_le_oadd e₂ n₂ o₂) theorem oadd_lt_oadd_2 {e o₁ o₂ : ONote} {n₁ n₂ : ℕ+} (h₁ : NF (oadd e n₁ o₁)) (h : (n₁ : ℕ) < n₂) : oadd e n₁ o₁ < oadd e n₂ o₂ := by simp only [lt_def, repr] refine lt_of_lt_of_le ((add_lt_add_iff_left _).2 h₁.snd'.repr_lt) (le_trans ?_ (le_add_right _ _)) - rwa [← mul_succ,Ordinal.mul_le_mul_iff_left (opow_pos _ omega_pos), succ_le_iff, natCast_lt] + rwa [← mul_succ,Ordinal.mul_le_mul_iff_left (opow_pos _ omega0_pos), succ_le_iff, natCast_lt] theorem oadd_lt_oadd_3 {e n a₁ a₂} (h : a₁ < a₂) : oadd e n a₁ < oadd e n a₂ := by rw [lt_def]; unfold repr @@ -325,7 +328,7 @@ theorem repr_inj {a b} [NF a] [NF b] : repr a = repr b ↔ a = b := | Ordering.eq, h => h, congr_arg _⟩ -theorem NF.of_dvd_omega_opow {b e n a} (h : NF (ONote.oadd e n a)) +theorem NF.of_dvd_omega0_opow {b e n a} (h : NF (ONote.oadd e n a)) (d : ω ^ b ∣ repr (ONote.oadd e n a)) : b ≤ repr e ∧ ω ^ b ∣ repr a := by have := mt repr_inj.1 (fun h => by injection h : ONote.oadd e n a ≠ 0) @@ -333,9 +336,15 @@ theorem NF.of_dvd_omega_opow {b e n a} (h : NF (ONote.oadd e n a)) simp only [repr] at d exact ⟨L, (dvd_add_iff <| (opow_dvd_opow _ L).mul_right _).1 d⟩ -theorem NF.of_dvd_omega {e n a} (h : NF (ONote.oadd e n a)) : +@[deprecated (since := "2024-09-30")] +alias NF.of_dvd_omega_opow := NF.of_dvd_omega0_opow + +theorem NF.of_dvd_omega0 {e n a} (h : NF (ONote.oadd e n a)) : ω ∣ repr (ONote.oadd e n a) → repr e ≠ 0 ∧ ω ∣ repr a := by - (rw [← opow_one ω, ← one_le_iff_ne_zero]; exact h.of_dvd_omega_opow) + (rw [← opow_one ω, ← one_le_iff_ne_zero]; exact h.of_dvd_omega0_opow) + +@[deprecated (since := "2024-09-30")] +alias NF.of_dvd_omega := NF.of_dvd_omega0 /-- `TopBelow b o` asserts that the largest exponent in `o`, if it exists, is less than `b`. This is an auxiliary definition @@ -443,7 +452,7 @@ theorem repr_add : ∀ (o₁ o₂) [NF o₁] [NF o₂], repr (o₁ + o₂) = rep unfold repr at this cases he' : e' <;> simp only [he', zero_def, opow_zero, repr, gt_iff_lt] at this ⊢ <;> exact lt_of_le_of_lt (le_add_right _ _) this - · simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos (repr e') omega_pos).2 + · simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos (repr e') omega0_pos).2 (natCast_le.2 n'.pos) · rw [ee, ← add_assoc, ← mul_add] @@ -503,7 +512,7 @@ theorem repr_sub : ∀ (o₁ o₂) [NF o₁] [NF o₂], repr (o₁ - o₂) = rep simpa using mul_le_mul_left' (natCast_le.2 <| Nat.succ_pos _) _ · exact (Ordinal.sub_eq_of_add_eq <| - add_absorp (h₂.below_of_lt ee).repr_lt <| omega_le_oadd _ _ _).symm + add_absorp (h₂.below_of_lt ee).repr_lt <| omega0_le_oadd _ _ _).symm /-- Multiplication of ordinal notations (correct only for normal input) -/ def mul : ONote → ONote → ONote @@ -557,7 +566,7 @@ theorem repr_mul : ∀ (o₁ o₂) [NF o₁] [NF o₂], repr (o₁ * o₂) = rep simp [(· * ·)] have ao : repr a₁ + ω ^ repr e₁ * (n₁ : ℕ) = ω ^ repr e₁ * (n₁ : ℕ) := by apply add_absorp h₁.snd'.repr_lt - simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos _ omega_pos).2 (natCast_le.2 n₁.2) + simpa using (Ordinal.mul_le_mul_iff_left <| opow_pos _ omega0_pos).2 (natCast_le.2 n₁.2) by_cases e0 : e₂ = 0 · cases' Nat.exists_eq_succ_of_ne_zero n₂.ne_zero with x xe simp only [e0, repr, PNat.mul_coe, natCast_mul, opow_zero, one_mul] @@ -570,8 +579,8 @@ theorem repr_mul : ∀ (o₁ o₂) [NF o₁] [NF o₂], repr (o₁ * o₂) = rep rw [← mul_assoc] congr 2 have := mt repr_inj.1 e0 - rw [add_mul_limit ao (opow_isLimit_left omega_isLimit this), mul_assoc, - mul_omega_dvd (natCast_pos.2 n₁.pos) (nat_lt_omega _)] + rw [add_mul_limit ao (opow_isLimit_left omega0_isLimit this), mul_assoc, + mul_omega0_dvd (natCast_pos.2 n₁.pos) (nat_lt_omega0 _)] simpa using opow_dvd_opow ω (one_le_iff_ne_zero.2 this) /-- Calculate division and remainder of `o` mod ω. @@ -680,7 +689,7 @@ theorem nf_repr_split' : ∀ {o o' m} [NF o], split' o = (o', m) → NF o' ∧ r · simp at this ⊢ refine IH₁.below_of_lt' - ((Ordinal.mul_lt_mul_iff_left omega_pos).1 <| lt_of_le_of_lt (le_add_right _ m') ?_) + ((Ordinal.mul_lt_mul_iff_left omega0_pos).1 <| lt_of_le_of_lt (le_add_right _ m') ?_) rw [← this, ← IH₂] exact h.snd'.repr_lt · rw [this] @@ -723,9 +732,9 @@ theorem split_dvd {o o' m} [NF o] (h : split o = (o', m)) : ω ∣ repr o' := by theorem split_add_lt {o e n a m} [NF o] (h : split o = (oadd e n a, m)) : repr a + m < ω ^ repr e := by cases' nf_repr_split h with h₁ h₂ - cases' h₁.of_dvd_omega (split_dvd h) with e0 d - apply principal_add_omega_opow _ h₁.snd'.repr_lt (lt_of_lt_of_le (nat_lt_omega _) _) - simpa using opow_le_opow_right omega_pos (one_le_iff_ne_zero.2 e0) + cases' h₁.of_dvd_omega0 (split_dvd h) with e0 d + apply principal_add_omega0_opow _ h₁.snd'.repr_lt (lt_of_lt_of_le (nat_lt_omega0 _) _) + simpa using opow_le_opow_right omega0_pos (one_le_iff_ne_zero.2 e0) @[simp] theorem mulNat_eq_mul (n o) : mulNat o n = o * ofNat n := by cases o <;> cases n <;> rfl @@ -781,22 +790,22 @@ theorem repr_opow_aux₁ {e a} [Ne : NF e] [Na : NF a] {a' : Ordinal} (e0 : repr (ω ^ repr e) ^ (ω : Ordinal.{0}) := by subst aa have No := Ne.oadd n (Na.below_of_lt' h) - have := omega_le_oadd e n a + have := omega0_le_oadd e n a rw [repr] at this refine le_antisymm ?_ (opow_le_opow_left _ this) - apply (opow_le_of_limit ((opow_pos _ omega_pos).trans_le this).ne' omega_isLimit).2 + apply (opow_le_of_limit ((opow_pos _ omega0_pos).trans_le this).ne' omega0_isLimit).2 intro b l have := (No.below_of_lt (lt_succ _)).repr_lt rw [repr] at this apply (opow_le_opow_left b <| this.le).trans rw [← opow_mul, ← opow_mul] - apply opow_le_opow_right omega_pos + apply opow_le_opow_right omega0_pos rcases le_or_lt ω (repr e) with h | h · apply (mul_le_mul_left' (le_succ b) _).trans - rw [← add_one_eq_succ, add_mul_succ _ (one_add_of_omega_le h), add_one_eq_succ, succ_le_iff, + rw [← add_one_eq_succ, add_mul_succ _ (one_add_of_omega0_le h), add_one_eq_succ, succ_le_iff, Ordinal.mul_lt_mul_iff_left (Ordinal.pos_iff_ne_zero.2 e0)] - exact omega_isLimit.2 _ l - · apply (principal_mul_omega (omega_isLimit.2 _ h) l).le.trans + exact omega0_isLimit.2 _ l + · apply (principal_mul_omega0 (omega0_isLimit.2 _ h) l).le.trans simpa using mul_le_mul_right' (one_le_iff_ne_zero.2 e0) ω section @@ -827,30 +836,30 @@ theorem repr_opow_aux₂ {a0 a'} [N0 : NF a0] [Na' : NF a'] (m : ℕ) (d : ω · simp only [R', ONote.repr_scale, ONote.repr, ONote.mulNat_eq_mul, ONote.opowAux, ONote.repr_ofNat, ONote.repr_mul, ONote.repr_add, Ordinal.opow_mul, ONote.zero_add] have α0 : 0 < α' := by simpa [lt_def, repr] using oadd_pos a0 n a' - have ω00 : 0 < ω0 ^ (k : Ordinal) := opow_pos _ (opow_pos _ omega_pos) + have ω00 : 0 < ω0 ^ (k : Ordinal) := opow_pos _ (opow_pos _ omega0_pos) have Rl : R < ω ^ (repr a0 * succ ↑k) := by by_cases k0 : k = 0 · simp only [k0, Nat.cast_zero, succ_zero, mul_one, R] - refine lt_of_lt_of_le ?_ (opow_le_opow_right omega_pos (one_le_iff_ne_zero.2 e0)) - cases' m with m <;> simp [opowAux, omega_pos] + refine lt_of_lt_of_le ?_ (opow_le_opow_right omega0_pos (one_le_iff_ne_zero.2 e0)) + cases' m with m <;> simp [opowAux, omega0_pos] rw [← add_one_eq_succ, ← Nat.cast_succ] - apply nat_lt_omega + apply nat_lt_omega0 · rw [opow_mul] exact IH.1 k0 refine ⟨fun _ => ?_, ?_⟩ · rw [RR, ← opow_mul _ _ (succ k.succ)] have e0 := Ordinal.pos_iff_ne_zero.2 e0 have rr0 : 0 < repr a0 + repr a0 := lt_of_lt_of_le e0 (le_add_left _ _) - apply principal_add_omega_opow + apply principal_add_omega0_opow · simp only [Nat.succ_eq_add_one, Nat.cast_add, Nat.cast_one, add_one_eq_succ, opow_mul, opow_succ, mul_assoc] rw [Ordinal.mul_lt_mul_iff_left ω00, ← Ordinal.opow_add] have : _ < ω ^ (repr a0 + repr a0) := (No.below_of_lt ?_).repr_lt - · exact mul_lt_omega_opow rr0 this (nat_lt_omega _) + · exact mul_lt_omega0_opow rr0 this (nat_lt_omega0 _) · simpa using (add_lt_add_iff_left (repr a0)).2 e0 · exact lt_of_lt_of_le Rl - (opow_le_opow_right omega_pos <| + (opow_le_opow_right omega0_pos <| mul_le_mul_left' (succ_le_succ_iff.2 (natCast_le.2 (le_of_lt k.lt_succ_self))) _) calc (ω0 ^ (k.succ : Ordinal)) * α' + R' @@ -862,10 +871,10 @@ theorem repr_opow_aux₂ {a0 a'} [N0 : NF a0] [Na' : NF a'] (m : ℕ) (d : ω · have αd : ω ∣ α' := dvd_add (dvd_mul_of_dvd_left (by simpa using opow_dvd_opow ω (one_le_iff_ne_zero.2 e0)) _) d rw [mul_add (ω0 ^ (k : Ordinal)), add_assoc, ← mul_assoc, ← opow_succ, - add_mul_limit _ (isLimit_iff_omega_dvd.2 ⟨ne_of_gt α0, αd⟩), mul_assoc, - @mul_omega_dvd n (natCast_pos.2 n.pos) (nat_lt_omega _) _ αd] + add_mul_limit _ (isLimit_iff_omega0_dvd.2 ⟨ne_of_gt α0, αd⟩), mul_assoc, + @mul_omega0_dvd n (natCast_pos.2 n.pos) (nat_lt_omega0 _) _ αd] apply @add_absorp _ (repr a0 * succ ↑k) - · refine principal_add_omega_opow _ ?_ Rl + · refine principal_add_omega0_opow _ ?_ Rl rw [opow_mul, opow_succ, Ordinal.mul_lt_mul_iff_left ω00] exact No.snd'.repr_lt · have := mul_le_mul_left' (one_le_iff_pos.2 <| natCast_pos.2 n.pos) (ω0 ^ succ (k : Ordinal)) @@ -878,7 +887,7 @@ theorem repr_opow_aux₂ {a0 a'} [N0 : NF a0] [Na' : NF a'] (m : ℕ) (d : ω apply add_absorp Rl rw [opow_mul, opow_succ] apply mul_le_mul_left' - simpa [repr] using omega_le_oadd a0 n a' + simpa [repr] using omega0_le_oadd a0 n a' end @@ -897,18 +906,18 @@ theorem repr_opow (o₁ o₂) [NF o₁] [NF o₂] : repr (o₁ ^ o₂) = repr o simp only [opow_def, opowAux2, opow, e₁, h, r₁, e₂, r₂, repr, opow_zero, Nat.succPNat_coe, Nat.cast_succ, Nat.cast_zero, _root_.zero_add, mul_one, add_zero, one_opow, npow_eq_pow] - rw [opow_add, opow_mul, opow_omega, add_one_eq_succ] + rw [opow_add, opow_mul, opow_omega0, add_one_eq_succ] · congr conv_lhs => dsimp [(· ^ ·)] simp [Pow.pow, opow, Ordinal.succ_ne_zero] rw [opow_natCast] · simpa [Nat.one_le_iff_ne_zero] - · rw [← Nat.cast_succ, lt_omega] + · rw [← Nat.cast_succ, lt_omega0] exact ⟨_, rfl⟩ · haveI := N₁.fst haveI := N₁.snd - cases' N₁.of_dvd_omega (split_dvd e₁) with a00 ad + cases' N₁.of_dvd_omega0 (split_dvd e₁) with a00 ad have al := split_add_lt e₁ have aa : repr (a' + ofNat m) = repr a' + m := by simp only [eq_self_iff_true, ONote.repr_ofNat, ONote.repr_add] @@ -955,13 +964,13 @@ private theorem exists_lt_add {α} [hα : Nonempty α] {o : Ordinal} {f : α → refine (H h).imp fun i H => ?_ rwa [← Ordinal.add_sub_cancel_of_le h', add_lt_add_iff_left] -private theorem exists_lt_mul_omega' {o : Ordinal} ⦃a⦄ (h : a < o * ω) : +private theorem exists_lt_mul_omega0' {o : Ordinal} ⦃a⦄ (h : a < o * ω) : ∃ i : ℕ, a < o * ↑i + o := by - obtain ⟨i, hi, h'⟩ := (lt_mul_of_limit omega_isLimit).1 h - obtain ⟨i, rfl⟩ := lt_omega.1 hi + obtain ⟨i, hi, h'⟩ := (lt_mul_of_limit omega0_isLimit).1 h + obtain ⟨i, rfl⟩ := lt_omega0.1 hi exact ⟨i, h'.trans_le (le_add_right _ _)⟩ -private theorem exists_lt_omega_opow' {α} {o b : Ordinal} (hb : 1 < b) (ho : o.IsLimit) +private theorem exists_lt_omega0_opow' {α} {o b : Ordinal} (hb : 1 < b) (ho : o.IsLimit) {f : α → Ordinal} (H : ∀ ⦃a⦄, a < o → ∃ i, a < f i) ⦃a⦄ (h : a < b ^ o) : ∃ i, a < b ^ f i := by obtain ⟨d, hd, h'⟩ := (lt_opow_of_limit (zero_lt_one.trans hb).ne' ho).1 h @@ -1014,39 +1023,40 @@ theorem fundamentalSequence_has_prop (o) : FundamentalSequenceProp o (fundamenta have := PNat.natPred_add_one m; rw [e'] at this; exact PNat.coe_inj.1 this.symm]) <;> (try rw [show m = (m' + 1).succPNat by rw [← e', ← PNat.coe_inj, Nat.succPNat_coe, ← Nat.add_one, PNat.natPred_add_one]]) <;> - simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega, add_lt_add_iff_left, add_zero, - eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, Nat.cast_succ, - Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero, + simp only [repr, iha, ihb, opow_lt_opow_iff_right one_lt_omega0, add_lt_add_iff_left, + add_zero, eq_self_iff_true, lt_add_iff_pos_right, lt_def, mul_one, Nat.cast_zero, + Nat.cast_succ, Nat.succPNat_coe, opow_succ, opow_zero, mul_add_one, PNat.one_coe, succ_zero, _root_.zero_add, zero_def] · decide · exact ⟨rfl, inferInstance⟩ - · have := opow_pos (repr a') omega_pos + · have := opow_pos (repr a') omega0_pos refine - ⟨mul_isLimit this omega_isLimit, fun i => - ⟨this, ?_, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega'⟩ + ⟨mul_isLimit this omega0_isLimit, fun i => + ⟨this, ?_, fun H => @NF.oadd_zero _ _ (iha.2 H.fst)⟩, exists_lt_mul_omega0'⟩ rw [← mul_succ, ← natCast_succ, Ordinal.mul_lt_mul_iff_left this] - apply nat_lt_omega - · have := opow_pos (repr a') omega_pos + apply nat_lt_omega0 + · have := opow_pos (repr a') omega0_pos refine - ⟨add_isLimit _ (mul_isLimit this omega_isLimit), fun i => ⟨this, ?_, ?_⟩, - exists_lt_add exists_lt_mul_omega'⟩ + ⟨add_isLimit _ (mul_isLimit this omega0_isLimit), fun i => ⟨this, ?_, ?_⟩, + exists_lt_add exists_lt_mul_omega0'⟩ · rw [← mul_succ, ← natCast_succ, Ordinal.mul_lt_mul_iff_left this] - apply nat_lt_omega + apply nat_lt_omega0 · refine fun H => H.fst.oadd _ (NF.below_of_lt' ?_ (@NF.oadd_zero _ _ (iha.2 H.fst))) rw [repr, ← zero_def, repr, add_zero, iha.1, opow_succ, Ordinal.mul_lt_mul_iff_left this] - apply nat_lt_omega + apply nat_lt_omega0 · rcases iha with ⟨h1, h2, h3⟩ - refine ⟨opow_isLimit one_lt_omega h1, fun i => ?_, exists_lt_omega_opow' one_lt_omega h1 h3⟩ + refine ⟨opow_isLimit one_lt_omega0 h1, fun i => ?_, + exists_lt_omega0_opow' one_lt_omega0 h1 h3⟩ obtain ⟨h4, h5, h6⟩ := h2 i exact ⟨h4, h5, fun H => @NF.oadd_zero _ _ (h6 H.fst)⟩ · rcases iha with ⟨h1, h2, h3⟩ refine - ⟨add_isLimit _ (opow_isLimit one_lt_omega h1), fun i => ?_, - exists_lt_add (exists_lt_omega_opow' one_lt_omega h1 h3)⟩ + ⟨add_isLimit _ (opow_isLimit one_lt_omega0 h1), fun i => ?_, + exists_lt_add (exists_lt_omega0_opow' one_lt_omega0 h1 h3)⟩ obtain ⟨h4, h5, h6⟩ := h2 i refine ⟨h4, h5, fun H => H.fst.oadd _ (NF.below_of_lt' ?_ (@NF.oadd_zero _ _ (h6 H.fst)))⟩ rwa [repr, ← zero_def, repr, add_zero, PNat.one_coe, Nat.cast_one, mul_one, - opow_lt_opow_iff_right one_lt_omega] + opow_lt_opow_iff_right one_lt_omega0] · refine ⟨by rw [repr, ihb.1, add_succ, repr], fun H => H.fst.oadd _ (NF.below_of_lt' ?_ (ihb.2 H.snd))⟩ have := H.snd'.repr_lt diff --git a/Mathlib/SetTheory/Ordinal/Principal.lean b/Mathlib/SetTheory/Ordinal/Principal.lean index f149eea4b37a4..2835fd286b3f3 100644 --- a/Mathlib/SetTheory/Ordinal/Principal.lean +++ b/Mathlib/SetTheory/Ordinal/Principal.lean @@ -14,9 +14,9 @@ We define principal or indecomposable ordinals, and we prove the standard proper * `Principal`: A principal or indecomposable ordinal under some binary operation. We include 0 and any other typically excluded edge cases for simplicity. * `unbounded_principal`: Principal ordinals are unbounded. -* `principal_add_iff_zero_or_omega_opow`: The main characterization theorem for additive principal +* `principal_add_iff_zero_or_omega0_opow`: The main characterization theorem for additive principal ordinals. -* `principal_mul_iff_le_two_or_omega_opow_opow`: The main characterization theorem for +* `principal_mul_iff_le_two_or_omega0_opow_opow`: The main characterization theorem for multiplicative principal ordinals. ## TODO @@ -163,39 +163,51 @@ theorem principal_add_iff_add_lt_ne_self {a} : rcases exists_lt_add_of_not_principal_add ha with ⟨b, hb, c, hc, rfl⟩ exact (H b hb c hc).irrefl⟩ -theorem add_omega {a : Ordinal} (h : a < ω) : a + ω = ω := by - rcases lt_omega.1 h with ⟨n, rfl⟩ +theorem add_omega0 {a : Ordinal} (h : a < ω) : a + ω = ω := by + rcases lt_omega0.1 h with ⟨n, rfl⟩ clear h; induction' n with n IH · rw [Nat.cast_zero, zero_add] - · rwa [Nat.cast_succ, add_assoc, one_add_of_omega_le (le_refl _)] + · rwa [Nat.cast_succ, add_assoc, one_add_of_omega0_le (le_refl _)] -theorem principal_add_omega : Principal (· + ·) ω := - principal_add_iff_add_left_eq_self.2 fun _ => add_omega +@[deprecated (since := "2024-09-30")] +alias add_omega := add_omega0 -theorem add_omega_opow {a b : Ordinal} (h : a < ω ^ b) : a + ω ^ b = ω ^ b := by +theorem principal_add_omega0 : Principal (· + ·) ω := + principal_add_iff_add_left_eq_self.2 fun _ => add_omega0 + +@[deprecated (since := "2024-09-30")] +alias principal_add_omega := principal_add_omega0 + +theorem add_omega0_opow {a b : Ordinal} (h : a < ω ^ b) : a + ω ^ b = ω ^ b := by refine le_antisymm ?_ (le_add_left _ a) induction' b using limitRecOn with b _ b l IH · rw [opow_zero, ← succ_zero, lt_succ_iff, Ordinal.le_zero] at h rw [h, zero_add] · rw [opow_succ] at h - rcases (lt_mul_of_limit omega_isLimit).1 h with ⟨x, xo, ax⟩ + rcases (lt_mul_of_limit omega0_isLimit).1 h with ⟨x, xo, ax⟩ apply (add_le_add_right ax.le _).trans - rw [opow_succ, ← mul_add, add_omega xo] - · rcases (lt_opow_of_limit omega_ne_zero l).1 h with ⟨x, xb, ax⟩ - apply (((add_isNormal a).trans <| opow_isNormal one_lt_omega).limit_le l).2 + rw [opow_succ, ← mul_add, add_omega0 xo] + · rcases (lt_opow_of_limit omega0_ne_zero l).1 h with ⟨x, xb, ax⟩ + apply (((add_isNormal a).trans <| opow_isNormal one_lt_omega0).limit_le l).2 intro y yb calc a + ω ^ y ≤ a + ω ^ max x y := - add_le_add_left (opow_le_opow_right omega_pos (le_max_right x y)) _ + add_le_add_left (opow_le_opow_right omega0_pos (le_max_right x y)) _ _ ≤ ω ^ max x y := - IH _ (max_lt xb yb) <| ax.trans_le <| opow_le_opow_right omega_pos <| le_max_left x y + IH _ (max_lt xb yb) <| ax.trans_le <| opow_le_opow_right omega0_pos <| le_max_left x y _ ≤ ω ^ b := - opow_le_opow_right omega_pos <| (max_lt xb yb).le + opow_le_opow_right omega0_pos <| (max_lt xb yb).le + +@[deprecated (since := "2024-09-30")] +alias add_omega_opow := add_omega0_opow + +theorem principal_add_omega0_opow (o : Ordinal) : Principal (· + ·) (ω ^ o) := + principal_add_iff_add_left_eq_self.2 fun _ => add_omega0_opow -theorem principal_add_omega_opow (o : Ordinal) : Principal (· + ·) (ω ^ o) := - principal_add_iff_add_left_eq_self.2 fun _ => add_omega_opow +@[deprecated (since := "2024-09-30")] +alias principal_add_omega_opow := principal_add_omega0_opow /-- The main characterization theorem for additive principal ordinals. -/ -theorem principal_add_iff_zero_or_omega_opow {o : Ordinal} : +theorem principal_add_iff_zero_or_omega0_opow {o : Ordinal} : Principal (· + ·) o ↔ o = 0 ∨ o ∈ Set.range (ω ^ · : Ordinal → Ordinal) := by rcases eq_or_ne o 0 with (rfl | ho) · simp only [principal_zero, Or.inl] @@ -203,12 +215,12 @@ theorem principal_add_iff_zero_or_omega_opow {o : Ordinal} : simp only [ho, false_or] refine ⟨fun H => ⟨_, ((lt_or_eq_of_le (opow_log_le_self _ ho)).resolve_left fun h => ?_)⟩, - fun ⟨b, e⟩ => e.symm ▸ fun a => add_omega_opow⟩ + fun ⟨b, e⟩ => e.symm ▸ fun a => add_omega0_opow⟩ have := H _ h - have := lt_opow_succ_log_self one_lt_omega o - rw [opow_succ, lt_mul_of_limit omega_isLimit] at this + have := lt_opow_succ_log_self one_lt_omega0 o + rw [opow_succ, lt_mul_of_limit omega0_isLimit] at this rcases this with ⟨a, ao, h'⟩ - rcases lt_omega.1 ao with ⟨n, rfl⟩ + rcases lt_omega0.1 ao with ⟨n, rfl⟩ clear ao revert h' apply not_lt_of_le @@ -218,18 +230,21 @@ theorem principal_add_iff_zero_or_omega_opow {o : Ordinal} : · simp [Nat.cast_zero, mul_zero, zero_add] · simp only [Nat.cast_succ, mul_add_one, add_assoc, this, IH] +@[deprecated (since := "2024-09-30")] +alias principal_add_iff_zero_or_omega_opow := principal_add_iff_zero_or_omega0_opow + theorem opow_principal_add_of_principal_add {a} (ha : Principal (· + ·) a) (b : Ordinal) : Principal (· + ·) (a ^ b) := by - rcases principal_add_iff_zero_or_omega_opow.1 ha with (rfl | ⟨c, rfl⟩) + rcases principal_add_iff_zero_or_omega0_opow.1 ha with (rfl | ⟨c, rfl⟩) · rcases eq_or_ne b 0 with (rfl | hb) · rw [opow_zero] exact principal_add_one · rwa [zero_opow hb] · rw [← opow_mul] - exact principal_add_omega_opow _ + exact principal_add_omega0_opow _ theorem add_absorp {a b c : Ordinal} (h₁ : a < ω ^ b) (h₂ : ω ^ b ≤ c) : a + c = c := by - rw [← Ordinal.add_sub_cancel_of_le h₂, ← add_assoc, add_omega_opow h₁] + rw [← Ordinal.add_sub_cancel_of_le h₂, ← add_assoc, add_omega0_opow h₁] theorem mul_principal_add_is_principal_add (a : Ordinal.{u}) {b : Ordinal.{u}} (hb₁ : b ≠ 1) (hb : Principal (· + ·) b) : Principal (· + ·) (a * b) := by @@ -302,44 +317,59 @@ theorem principal_mul_iff_mul_left_eq {o : Ordinal} : rw [← h a ha hao] exact (mul_isNormal ha).strictMono hbo -theorem principal_mul_omega : Principal (· * ·) ω := fun a b ha hb => - match a, b, lt_omega.1 ha, lt_omega.1 hb with +theorem principal_mul_omega0 : Principal (· * ·) ω := fun a b ha hb => + match a, b, lt_omega0.1 ha, lt_omega0.1 hb with | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by dsimp only; rw [← natCast_mul] - apply nat_lt_omega + apply nat_lt_omega0 + +@[deprecated (since := "2024-09-30")] +alias principal_mul_omega := principal_mul_omega0 + +theorem mul_omega0 {a : Ordinal} (a0 : 0 < a) (ha : a < ω) : a * ω = ω := + principal_mul_iff_mul_left_eq.1 principal_mul_omega0 a a0 ha -theorem mul_omega {a : Ordinal} (a0 : 0 < a) (ha : a < ω) : a * ω = ω := - principal_mul_iff_mul_left_eq.1 principal_mul_omega a a0 ha +@[deprecated (since := "2024-09-30")] +alias mul_omega := mul_omega0 -theorem mul_lt_omega_opow {a b c : Ordinal} (c0 : 0 < c) (ha : a < ω ^ c) (hb : b < ω) : +theorem mul_lt_omega0_opow {a b c : Ordinal} (c0 : 0 < c) (ha : a < ω ^ c) (hb : b < ω) : a * b < ω ^ c := by rcases zero_or_succ_or_limit c with (rfl | ⟨c, rfl⟩ | l) · exact (lt_irrefl _).elim c0 · rw [opow_succ] at ha - rcases ((mul_isNormal <| opow_pos _ omega_pos).limit_lt omega_isLimit).1 ha with ⟨n, hn, an⟩ + rcases ((mul_isNormal <| opow_pos _ omega0_pos).limit_lt omega0_isLimit).1 ha with ⟨n, hn, an⟩ apply (mul_le_mul_right' (le_of_lt an) _).trans_lt - rw [opow_succ, mul_assoc, mul_lt_mul_iff_left (opow_pos _ omega_pos)] - exact principal_mul_omega hn hb - · rcases ((opow_isNormal one_lt_omega).limit_lt l).1 ha with ⟨x, hx, ax⟩ + rw [opow_succ, mul_assoc, mul_lt_mul_iff_left (opow_pos _ omega0_pos)] + exact principal_mul_omega0 hn hb + · rcases ((opow_isNormal one_lt_omega0).limit_lt l).1 ha with ⟨x, hx, ax⟩ refine (mul_le_mul' (le_of_lt ax) (le_of_lt hb)).trans_lt ?_ - rw [← opow_succ, opow_lt_opow_iff_right one_lt_omega] + rw [← opow_succ, opow_lt_opow_iff_right one_lt_omega0] exact l.2 _ hx -theorem mul_omega_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < ω ^ ω ^ b) : +@[deprecated (since := "2024-09-30")] +alias mul_lt_omega_opow := mul_lt_omega0_opow + +theorem mul_omega0_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < ω ^ ω ^ b) : a * ω ^ ω ^ b = ω ^ ω ^ b := by obtain rfl | b0 := eq_or_ne b 0 · rw [opow_zero, opow_one] at h ⊢ - exact mul_omega a0 h + exact mul_omega0 a0 h · apply le_antisymm · obtain ⟨x, xb, ax⟩ := - (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h + (lt_opow_of_limit omega0_ne_zero (opow_isLimit_left omega0_isLimit b0)).1 h apply (mul_le_mul_right' (le_of_lt ax) _).trans - rw [← opow_add, add_omega_opow xb] + rw [← opow_add, add_omega0_opow xb] · conv_lhs => rw [← one_mul (ω ^ _)] exact mul_le_mul_right' (one_le_iff_pos.2 a0) _ -theorem principal_mul_omega_opow_opow (o : Ordinal) : Principal (· * ·) (ω ^ ω ^ o) := - principal_mul_iff_mul_left_eq.2 fun _ => mul_omega_opow_opow +@[deprecated (since := "2024-09-30")] +alias mul_omega_opow_opow := mul_omega0_opow_opow + +theorem principal_mul_omega0_opow_opow (o : Ordinal) : Principal (· * ·) (ω ^ ω ^ o) := + principal_mul_iff_mul_left_eq.2 fun _ => mul_omega0_opow_opow + +@[deprecated (since := "2024-09-30")] +alias principal_mul_omega_opow_opow := principal_mul_omega0_opow_opow theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b) (ho : Principal (· * ·) (b ^ o)) : Principal (· + ·) o := by @@ -349,24 +379,30 @@ theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b) rwa [← opow_add, opow_lt_opow_iff_right hb] at this /-- The main characterization theorem for multiplicative principal ordinals. -/ -theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} : +theorem principal_mul_iff_le_two_or_omega0_opow_opow {o : Ordinal} : Principal (· * ·) o ↔ o ≤ 2 ∨ o ∈ Set.range (ω ^ ω ^ · : Ordinal → Ordinal) := by refine ⟨fun ho => ?_, ?_⟩ · rcases le_or_lt o 2 with ho₂ | ho₂ · exact Or.inl ho₂ - · rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with - (rfl | ⟨a, rfl⟩) + · rcases principal_add_iff_zero_or_omega0_opow.1 (principal_add_of_principal_mul ho ho₂.ne') + with (rfl | ⟨a, rfl⟩) · exact (Ordinal.not_lt_zero 2 ho₂).elim - · rcases principal_add_iff_zero_or_omega_opow.1 - (principal_add_of_principal_mul_opow one_lt_omega ho) with (rfl | ⟨b, rfl⟩) + · rcases principal_add_iff_zero_or_omega0_opow.1 + (principal_add_of_principal_mul_opow one_lt_omega0 ho) with (rfl | ⟨b, rfl⟩) · simp · exact Or.inr ⟨b, rfl⟩ · rintro (ho₂ | ⟨a, rfl⟩) · exact principal_mul_of_le_two ho₂ - · exact principal_mul_omega_opow_opow a + · exact principal_mul_omega0_opow_opow a + +@[deprecated (since := "2024-09-30")] +alias principal_mul_iff_le_two_or_omega_opow_opow := principal_mul_iff_le_two_or_omega0_opow_opow -theorem mul_omega_dvd {a : Ordinal} (a0 : 0 < a) (ha : a < ω) : ∀ {b}, ω ∣ b → a * b = b - | _, ⟨b, rfl⟩ => by rw [← mul_assoc, mul_omega a0 ha] +theorem mul_omega0_dvd {a : Ordinal} (a0 : 0 < a) (ha : a < ω) : ∀ {b}, ω ∣ b → a * b = b + | _, ⟨b, rfl⟩ => by rw [← mul_assoc, mul_omega0 a0 ha] + +@[deprecated (since := "2024-09-30")] +alias mul_omega_dvd := mul_omega0_dvd theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b) (hb₂ : 2 < b) : a * b = b ^ succ (log b a) := by @@ -387,15 +423,21 @@ theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal /-! #### Exponential principal ordinals -/ -theorem principal_opow_omega : Principal (· ^ ·) ω := fun a b ha hb => - match a, b, lt_omega.1 ha, lt_omega.1 hb with +theorem principal_opow_omega0 : Principal (· ^ ·) ω := fun a b ha hb => + match a, b, lt_omega0.1 ha, lt_omega0.1 hb with | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by simp_rw [← natCast_opow] - apply nat_lt_omega + apply nat_lt_omega0 + +@[deprecated (since := "2024-09-30")] +alias principal_opow_omega := principal_opow_omega0 -theorem opow_omega {a : Ordinal} (a1 : 1 < a) (h : a < ω) : a ^ ω = ω := - ((opow_le_of_limit (one_le_iff_ne_zero.1 <| le_of_lt a1) omega_isLimit).2 fun _ hb => - (principal_opow_omega h hb).le).antisymm +theorem opow_omega0 {a : Ordinal} (a1 : 1 < a) (h : a < ω) : a ^ ω = ω := + ((opow_le_of_limit (one_le_iff_ne_zero.1 <| le_of_lt a1) omega0_isLimit).2 fun _ hb => + (principal_opow_omega0 h hb).le).antisymm (right_le_opow _ a1) +@[deprecated (since := "2024-09-30")] +alias opow_omega := opow_omega0 + end Ordinal diff --git a/Mathlib/SetTheory/Ordinal/Topology.lean b/Mathlib/SetTheory/Ordinal/Topology.lean index 73e5ab814961e..6993d517742e4 100644 --- a/Mathlib/SetTheory/Ordinal/Topology.lean +++ b/Mathlib/SetTheory/Ordinal/Topology.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Violeta Hernández Palacios. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Violeta Hernández Palacios -/ -import Mathlib.SetTheory.Ordinal.Arithmetic +import Mathlib.SetTheory.Ordinal.Enum import Mathlib.Tactic.TFAE import Mathlib.Topology.Order.Monotone @@ -219,27 +219,26 @@ theorem isNormal_iff_strictMono_and_continuous (f : Ordinal.{u} → Ordinal.{u}) ⟨_, toType_nonempty_iff_ne_zero.2 ho.1, typein (· < ·), fun i => h _ (typein_lt_self i), sup_typein_limit ho.2⟩ -theorem enumOrd_isNormal_iff_isClosed (hs : s.Unbounded (· < ·)) : +theorem enumOrd_isNormal_iff_isClosed (hs : ¬ BddAbove s) : IsNormal (enumOrd s) ↔ IsClosed s := by have Hs := enumOrd_strictMono hs refine ⟨fun h => isClosed_iff_iSup.2 fun {ι} hι f hf => ?_, fun h => (isNormal_iff_strictMono_limit _).2 ⟨Hs, fun a ha o H => ?_⟩⟩ - · let g : ι → Ordinal.{u} := fun i => (enumOrdOrderIso hs).symm ⟨_, hf i⟩ + · let g : ι → Ordinal.{u} := fun i => (enumOrdOrderIso s hs).symm ⟨_, hf i⟩ suffices enumOrd s (⨆ i, g i) = ⨆ i, f i by rw [← this] exact enumOrd_mem hs _ rw [IsNormal.map_iSup h g] congr ext x - change ((enumOrdOrderIso hs) _).val = f x + change (enumOrdOrderIso s hs _).val = f x rw [OrderIso.apply_symm_apply] · rw [isClosed_iff_bsup] at h suffices enumOrd s a ≤ bsup.{u, u} a fun b (_ : b < a) => enumOrd s b from this.trans (bsup_le H) - cases' enumOrd_surjective hs _ - (h ha.1 (fun b _ => enumOrd s b) fun b _ => enumOrd_mem hs b) with - b hb + obtain ⟨b, hb⟩ := enumOrd_surjective hs (h ha.1 (fun b _ => enumOrd s b) + fun b _ => enumOrd_mem hs b) rw [← hb] apply Hs.monotone by_contra! hba diff --git a/Mathlib/SetTheory/ZFC/Basic.lean b/Mathlib/SetTheory/ZFC/Basic.lean index bede4eaab6232..bc21fd9e20d72 100644 --- a/Mathlib/SetTheory/ZFC/Basic.lean +++ b/Mathlib/SetTheory/ZFC/Basic.lean @@ -367,7 +367,7 @@ theorem mem_insert_of_mem {y z : PSet} (x) (h : z ∈ y) : z ∈ insert x y := @[simp] theorem mem_singleton {x y : PSet} : x ∈ ({y} : PSet) ↔ Equiv x y := mem_insert_iff.trans - ⟨fun o => Or.rec (fun h => h) (fun n => absurd n (not_mem_empty _)) o, Or.inl⟩ + ⟨fun o => Or.rec id (fun n => absurd n (not_mem_empty _)) o, Or.inl⟩ theorem mem_pair {x y z : PSet} : x ∈ ({y, z} : PSet) ↔ Equiv x y ∨ Equiv x z := by simp @@ -834,6 +834,10 @@ theorem mem_sep {p : ZFSet.{u} → Prop} {x y : ZFSet.{u}} : Quotient.inductionOn₂ x y fun _ _ => PSet.mem_sep (p := p ∘ mk) fun _ _ h => (Quotient.sound h).subst +@[simp] +theorem sep_empty (p : ZFSet → Prop) : (∅ : ZFSet).sep p = ∅ := + (eq_empty _).mpr fun _ h ↦ not_mem_empty _ (mem_sep.mp h).1 + @[simp] theorem toSet_sep (a : ZFSet) (p : ZFSet → Prop) : (ZFSet.sep p a).toSet = { x ∈ a.toSet | p x } := by @@ -886,9 +890,8 @@ def sUnion : ZFSet → ZFSet := prefix:110 "⋃₀ " => ZFSet.sUnion /-- The intersection operator, the collection of elements in all of the elements of a ZFC set. We -special-case `⋂₀ ∅ = ∅`. -/ -noncomputable def sInter (x : ZFSet) : ZFSet := by - classical exact if h : x.Nonempty then ZFSet.sep (fun y => ∀ z ∈ x, y ∈ z) h.some else ∅ +define `⋂₀ ∅ = ∅`. -/ +def sInter (x : ZFSet) : ZFSet := (⋃₀ x).sep (fun y => ∀ z ∈ x, y ∈ z) @[inherit_doc] prefix:110 "⋂₀ " => ZFSet.sInter @@ -899,9 +902,12 @@ theorem mem_sUnion {x y : ZFSet.{u}} : y ∈ ⋃₀ x ↔ ∃ z ∈ x, y ∈ z : ⟨fun ⟨z, h⟩ => ⟨⟦z⟧, h⟩, fun ⟨z, h⟩ => Quotient.inductionOn z (fun z h => ⟨z, h⟩) h⟩ theorem mem_sInter {x y : ZFSet} (h : x.Nonempty) : y ∈ ⋂₀ x ↔ ∀ z ∈ x, y ∈ z := by - rw [sInter, dif_pos h] - simp only [mem_toSet, mem_sep, and_iff_right_iff_imp] - exact fun H => H _ h.some_mem + unfold sInter + simp only [and_iff_right_iff_imp, mem_sep] + intro mem + apply mem_sUnion.mpr + replace ⟨s, h⟩ := h + exact ⟨_, h, mem _ h⟩ @[simp] theorem sUnion_empty : ⋃₀ (∅ : ZFSet.{u}) = ∅ := by @@ -909,7 +915,7 @@ theorem sUnion_empty : ⋃₀ (∅ : ZFSet.{u}) = ∅ := by simp @[simp] -theorem sInter_empty : ⋂₀ (∅ : ZFSet) = ∅ := dif_neg <| by simp +theorem sInter_empty : ⋂₀ (∅ : ZFSet) = ∅ := by simp [sInter] theorem mem_of_mem_sInter {x y z : ZFSet} (hy : y ∈ ⋂₀ x) (hz : z ∈ x) : y ∈ z := by rcases eq_empty_or_nonempty x with (rfl | hx) diff --git a/Mathlib/Tactic.lean b/Mathlib/Tactic.lean index ce50b9c0db698..46952152d3576 100644 --- a/Mathlib/Tactic.lean +++ b/Mathlib/Tactic.lean @@ -1,5 +1,6 @@ import Mathlib.Tactic.Abel import Mathlib.Tactic.AdaptationNote +import Mathlib.Tactic.Algebraize import Mathlib.Tactic.ApplyAt import Mathlib.Tactic.ApplyCongr import Mathlib.Tactic.ApplyFun @@ -134,6 +135,7 @@ import Mathlib.Tactic.LinearCombination' import Mathlib.Tactic.LinearCombination.Lemmas import Mathlib.Tactic.Linter import Mathlib.Tactic.Linter.AdmitLinter +import Mathlib.Tactic.Linter.DocPrime import Mathlib.Tactic.Linter.FlexibleLinter import Mathlib.Tactic.Linter.GlobalAttributeIn import Mathlib.Tactic.Linter.HashCommandLinter @@ -141,6 +143,7 @@ import Mathlib.Tactic.Linter.HaveLetLinter import Mathlib.Tactic.Linter.Lint import Mathlib.Tactic.Linter.MinImports import Mathlib.Tactic.Linter.OldObtain +import Mathlib.Tactic.Linter.PPRoundtrip import Mathlib.Tactic.Linter.RefineLinter import Mathlib.Tactic.Linter.Style import Mathlib.Tactic.Linter.TextBased @@ -150,6 +153,7 @@ import Mathlib.Tactic.Measurability.Init import Mathlib.Tactic.MinImports import Mathlib.Tactic.MkIffOfInductiveProp import Mathlib.Tactic.ModCases +import Mathlib.Tactic.Module import Mathlib.Tactic.Monotonicity import Mathlib.Tactic.Monotonicity.Attr import Mathlib.Tactic.Monotonicity.Basic @@ -205,6 +209,7 @@ import Mathlib.Tactic.RewriteSearch import Mathlib.Tactic.Rify import Mathlib.Tactic.Ring import Mathlib.Tactic.Ring.Basic +import Mathlib.Tactic.Ring.Compare import Mathlib.Tactic.Ring.PNat import Mathlib.Tactic.Ring.RingNF import Mathlib.Tactic.Sat.FromLRAT diff --git a/Mathlib/Tactic/Algebraize.lean b/Mathlib/Tactic/Algebraize.lean new file mode 100644 index 0000000000000..74c3a9eaf8230 --- /dev/null +++ b/Mathlib/Tactic/Algebraize.lean @@ -0,0 +1,298 @@ +/- +Copyright (c) 2024 Calle Sönne. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Johan Commelin, Nick Kuhn, Arend Mellendijk, Christian Merten, Calle Sönne, Adam Topaz +-/ + +import Mathlib.Algebra.Algebra.Tower + +/-! + +## Algebraize tactic + +This file defines the `algebraize` tactic. The basic functionality of this tactic is to +automatically add `Algebra` instances given `RingHom`s. For example, `algebraize [f, g]` where +`f : A →+* B` and `g : B →+* C` are `RingHom`s, will add the instances `Algebra A B` and +`Algebra B C` corresponding to these `RingHom`s. + +## Further functionality + +When given a composition of `RingHom`s, e.g. `algebraize [g.comp f]`, the tactic will also try to +add the instance `IsScalarTower A B C` if possible. + +After having added suitable `Algebra` and `IsScalarTower` instances, the tactic will search through +the local context for `RingHom` properties that can be converted to properties of the corresponding +`Algebra`. For example, given `f : A →+* B` and `hf : f.FiniteType`, then `algebraize [f]` will add +the instance `Algebra A B` and the corresponding property `Algebra.FiniteType A B`. The tactic knows +which `RingHom` properties have a corresponding `Algebra` property through the `algebraize` +attribute. + +## Algebraize attribute + +The `algebraize` attribute is used to tag `RingHom` properties that can be converted to `Algebra` +properties. It assumes that the tagged declaration has a name of the form `RingHom.Property` and +that the corresponding `Algebra` property has the name `Algebra.Property`. + +If not, the `Name` of the corresponding algebra property can be provided as optional argument. The +specified declaration should be one of the following: + +1. An inductive type (i.e. the `Algebra` property itself), in this case it is assumed that the +`RingHom` and the `Algebra` property are definitionally the same, and the tactic will construct the +`Algebra` property by giving the `RingHom` property as a term. +2. A constructor for the `Algebra` property. In this case it is assumed that the `RingHom` property +is the last argument of the constructor, and that no other explicit argument is needed. The tactic +then constructs the `Algebra` property by applying the constructor to the `RingHom` property. + +Here are three examples of properties tagged with the `algebraize` attribute: +``` +@[algebraize] +def RingHom.FiniteType (f : A →+* B) : Prop := + @Algebra.FiniteType A B _ _ f.toAlgebra +``` +An example when the `Name` is provided (as the `Algebra` does not have the expected name): +``` +@[algebraize Module.Finite] +def RingHom.Finite (f : A →+* B) : Prop := + letI : Algebra A B := f.toAlgebra + Module.Finite A B +``` +An example with a constructor as parameter (as the two properties are not definitonally the same): +``` +@[algebraize Algebra.Flat.out] +class RingHom.Flat {R : Type u} {S : Type v} [CommRing R] [CommRing S] (f : R →+* S) : Prop where + out : f.toAlgebra.Flat := by infer_instance +``` + +## algebraize_only + +To avoid searching through the local context and adding corresponding `Algebra` properties, use +`algebraize_only` which only adds `Algebra` and `IsScalarTower` instances. +-/ + +open Lean Elab Tactic Term Meta + +namespace Lean.Attr + +/-- Function that extracts the name of the corresponding `Algebra` property from a `RingHom` +property that has been tagged with the `algebraize` attribute. This is done by either returning the +parameter of the attribute, or by assuming that the tagged declaration has name `RingHom.Property` +and then returning `Algebra.Property`. -/ +def algebraizeGetParam (thm : Name) (stx : Syntax) : AttrM Name := do + match stx with + | `(attr| algebraize $name:ident) => return name.getId + /- If no argument is provided, assume `thm` is of the form `RingHom.Property`, + and return `Algebra.Property` -/ + | `(attr| algebraize) => + match thm with + | .str `RingHom t => return .str `Algebra t + | _ => + throwError "theorem name must be of the form `RingHom.Property` if no argument is provided" + | _ => throwError "unexpected algebraize argument" + +/-- A user attribute that is used to tag `RingHom` properties that can be converted to `Algebra` +properties. Using an (optional) parameter, it will also generate a `Name` of a declaration which +will help the `algebraize` tactic access the corresponding `Algebra` property. + +There are two cases for what declaration corresponding to this `Name` can be. + +1. An inductive type (i.e. the `Algebra` property itself), in this case it is assumed that the +`RingHom` and the `Algebra` property are definitionally the same, and the tactic will construct the +`Algebra` property by giving the `RingHom` property as a term. +2. A constructor for the `Algebra` property. In this case it is assumed that the `RingHom` property +is the last argument of the constructor, and that no other explicit argument is needed. The tactic +then constructs the `Algebra` property by applying the constructor to the `RingHom` property. + +Finally, if no argument is provided to the `algebraize` attribute, it is assumed that the tagged +declaration has name `RingHom.Property` and that the corresponding `Algebra` property has name +`Algebra.Property`. The attribute then returns `Algebra.Property` (so assume case 1 above). -/ +initialize algebraizeAttr : ParametricAttribute Name ← + registerParametricAttribute { + name := `algebraize, + descr := +"Tag that lets the `algebraize` tactic know which `Algebra` property corresponds to this `RingHom` +property.", + getParam := algebraizeGetParam } + +end Lean.Attr + +namespace Mathlib.Tactic + +namespace Algebraize + +/-- Given an expression `f` of type `RingHom A B` where `A` and `B` are commutative semirings, +this function adds the instance `Algebra A B` to the context (if it does not already exist). + +This function also requries the type of `f`, given by the parameter `ft`. The reason this is done +(even though `ft` can be inferred from `f`) is to avoid recomputing `ft` in the `algebraize` tactic, +as when `algebraize` calls `addAlgebraInstanceFromRingHom` it has already computed `ft`. -/ +def addAlgebraInstanceFromRingHom (f ft : Expr) : TacticM Unit := withMainContext do + let (_, l) := ft.getAppFnArgs + -- The type of the corresponding algebra instance + let alg ← mkAppOptM ``Algebra #[l[0]!, l[1]!, none, none] + -- If the instance already exists, we do not do anything + unless (← synthInstance? alg).isSome do + liftMetaTactic fun mvarid => do + let nm ← mkFreshBinderNameForTactic `algInst + let mvar ← mvarid.define nm alg (← mkAppM ``RingHom.toAlgebra #[f]) + let (_, mvar) ← mvar.intro1P + return [mvar] + +/-- Given an expression `g.comp f` which is the composition of two `RingHom`s, this function adds +the instance `IsScalarTower A B C` to the context (if it does not already exist). -/ +def addIsScalarTowerInstanceFromRingHomComp (fn : Expr) : TacticM Unit := withMainContext do + let (_, l) := fn.getAppFnArgs + let tower ← mkAppOptM ``IsScalarTower #[l[0]!, l[1]!, l[2]!, none, none, none] + -- If the instance already exists, we do not do anything + unless (← synthInstance? tower).isSome do + liftMetaTactic fun mvarid => do + let nm ← mkFreshBinderNameForTactic `scalarTowerInst + let h ← mkFreshExprMVar (← mkAppM ``Eq #[ + ← mkAppOptM ``algebraMap #[l[0]!, l[2]!, none, none, none], + ← mkAppM ``RingHom.comp #[ + ← mkAppOptM ``algebraMap #[l[1]!, l[2]!, none, none, none], + ← mkAppOptM ``algebraMap #[l[0]!, l[1]!, none, none, none]]]) + -- Note: this could fail, but then `algebraize` will just continue, and won't add this instance + h.mvarId!.refl + let val ← mkAppOptM ``IsScalarTower.of_algebraMap_eq' + #[l[0]!, l[1]!, l[2]!, none, none, none, none, none, none, h] + let mvar ← mvarid.define nm tower val + let (_, mvar) ← mvar.intro1P + return [mvar] + +/-- This function takes an array of expressions `t`, all of which are assumed to be `RingHom`s, +and searches through the local context to find any additional properties of these `RingHoms`, after +which it tries to add the corresponding `Algebra` properties to the context. It only looks for +properties that have been tagged with the `algebraize` attribute, and uses this tag to find the +corresponding `Algebra` property. -/ +def addProperties (t : Array Expr) : TacticM Unit := withMainContext do + let ctx ← getLCtx + ctx.forM fun decl => do + if decl.isImplementationDetail then return + let (nm, args) := decl.type.getAppFnArgs + -- Check if the type of the current hypothesis has been tagged with the `algebraize` attribute + match Attr.algebraizeAttr.getParam? (← getEnv) nm with + -- If it has, `p` will be the name of the corresponding `Algebra` property (or a constructor) + | some p => + -- The last argument of the `RingHom` property is assumed to be `f` + let f := args[args.size - 1]! + -- Check that `f` appears in the list of functions given to `algebraize` + if ¬ (← t.anyM (Meta.isDefEq · f)) then return + + let cinfo ← getConstInfo p + let n ← getExpectedNumArgs cinfo.type + let pargs := Array.mkArray n (none : Option Expr) + /- If the attribute points to the corresponding `Algebra` property itself, we assume that it + is definitionally the same as the `RingHom` property. Then, we just need to construct its type + and the local declaration will already give a valid term. -/ + match cinfo with + | .inductInfo _ => + let pargs := pargs.set! 0 args[0]! + let pargs := pargs.set! 1 args[1]! + let tp ← mkAppOptM p pargs -- This should be the type `Algebra.Property A B` + unless (← synthInstance? tp).isSome do + liftMetaTactic fun mvarid => do + let nm ← mkFreshBinderNameForTactic `algebraizeInst + let mvar ← mvarid.define nm tp decl.toExpr + let (_, mvar) ← mvar.intro1P + return [mvar] + /- Otherwise, the attribute points to a constructor of the `Algebra` property. In this case, + we assume that the `RingHom` property is the last argument of the constructor (and that + this is all we need to supply explicitly). -/ + | .ctorInfo ctor => + -- construct the desired value + let pargs := pargs.set! (n - 1) decl.toExpr + let val ← mkAppOptM p pargs + + -- construct the expected type + let alg ← mkAppOptM ``Algebra #[args[0]!, args[1]!, none, none] + let algInst := (← synthInstance? alg) + let mut argsType := Array.mkArray (ctor.numParams) (none : Option Expr) + argsType := argsType.set! 0 args[0]! + argsType := argsType.set! 1 args[1]! + argsType := argsType.set! (ctor.numParams - 1) algInst + let tp := ← mkAppOptM ctor.induct argsType + + unless (← synthInstance? tp).isSome do + liftMetaTactic fun mvarid => do + let nm ← mkFreshBinderNameForTactic `algebraizeInst + let mvar ← mvarid.define nm tp val + let (_, mvar) ← mvar.intro1P + return [mvar] + | _ => logError s!"bad argument to `algebraize` attribute: {p}. \ + Only supporting inductive types or constructors." + | none => return + +/-- Configuration for `algebraize`. -/ +structure Config where + /-- If true (default), the tactic will search the local context for `RingHom` properties + that can be converted to `Algebra` properties. -/ + properties : Bool := true +deriving Inhabited + +/-- Function elaborating `Algebraize.Config`. -/ +declare_config_elab elabAlgebraizeConfig Algebraize.Config + +end Algebraize + +open Algebraize Lean.Parser.Tactic + +/-- A list of terms passed to `algebraize` as argument. -/ +syntax algebraizeTermSeq := " [" withoutPosition(term,*,?) "]" + +/-- Tactic that, given `RingHom`s, adds the corresponding `Algebra` and (if possible) +`IsScalarTower` instances, as well as `Algebra` corresponding to `RingHom` properties available +as hypotheses. + +Example: given `f : A →+* B` and `g : B →+* C`, and `hf : f.FiniteType`, `algebraize [f, g]` will +add the instances `Algebra A B`, `Algebra B C`, and `Algebra.FiniteType A B`. + +See the `algebraize` tag for instructions on what properties can be added. + +The tactic also comes with a configuration option `properties`. If set to `true` (default), the +tactic searches through the local context for `RingHom` properties that can be converted to +`Algebra` properties. The macro `algebraize_only` calls +`algebraize (config := {properties := false})`, +so in other words it only adds `Algebra` and `IsScalarTower` instances. -/ +syntax "algebraize" (ppSpace config)? (ppSpace algebraizeTermSeq)? : tactic + +elab_rules : tactic + | `(tactic| algebraize $[$config]? $args) => do + let cfg ← elabAlgebraizeConfig (mkOptionalNode config) + let t ← match args with + | `(algebraizeTermSeq| [$rs,*]) => rs.getElems.mapM fun i => Term.elabTerm i none + | _ => + throwError "" + if t.size == 0 then + logWarningAt args "`algebraize []` without arguments has no effect!" + -- We loop through the given terms and add algebra instances + for f in t do + let ft ← inferType f + match ft.getAppFn with + | Expr.const ``RingHom _ => addAlgebraInstanceFromRingHom f ft + | _ => throwError m!"{f} is not of type `RingHom`" + -- After having added the algebra instances we try to add scalar tower instances + for f in t do + match f.getAppFn with + | Expr.const ``RingHom.comp _ => + try addIsScalarTowerInstanceFromRingHomComp f + catch _ => continue + | _ => continue + + -- Search through the local context to find other instances of algebraize + if cfg.properties then + addProperties t + | `(tactic| algebraize $[$config]?) => do + throwError "`algebraize` expects a list of arguments: `algebraize [f]`" + +/-- Version of `algebraize`, which only adds `Algebra` instances and `IsScalarTower` instances, +but does not try to add any instances about any properties tagged with +`@[algebraize]`, like for example `Finite` or `IsIntegral`. -/ +syntax "algebraize_only" (ppSpace algebraizeTermSeq)? : tactic + +macro_rules + | `(tactic| algebraize_only $args) => + `(tactic| algebraize (config := {properties := false}) $args) + | `(tactic| algebraize_only) => + `(tactic| algebraize (config := {properties := false})) + +end Mathlib.Tactic diff --git a/Mathlib/Tactic/Attr/Register.lean b/Mathlib/Tactic/Attr/Register.lean index 98101a86367d7..cc80f10b4abbf 100644 --- a/Mathlib/Tactic/Attr/Register.lean +++ b/Mathlib/Tactic/Attr/Register.lean @@ -84,3 +84,6 @@ register_simp_attr nontriviality /-- A stub attribute for `is_poly`. -/ register_label_attr is_poly + +/-- A simp set for the `fin_omega` wrapper around `omega`. -/ +register_simp_attr fin_omega diff --git a/Mathlib/Tactic/CC/Addition.lean b/Mathlib/Tactic/CC/Addition.lean index 39157d0e58cab..51dcb46a44da0 100644 --- a/Mathlib/Tactic/CC/Addition.lean +++ b/Mathlib/Tactic/CC/Addition.lean @@ -842,7 +842,7 @@ def dbgTraceACState : CCM Unit := do def mkACProof (e₁ e₂ : Expr) : MetaM Expr := do let eq ← mkEq e₁ e₂ let .mvar m ← mkFreshExprSyntheticOpaqueMVar eq | failure - AC.rewriteUnnormalized m + AC.rewriteUnnormalizedRefl m let pr ← instantiateMVars (.mvar m) mkExpectedTypeHint pr eq @@ -1470,7 +1470,8 @@ partial def propagateEqUp (e : Expr) : CCM Unit := do if ← isInterpretedValue ra <&&> isInterpretedValue rb <&&> pure (ra.int?.isNone || ra.int? != rb.int?) then raNeRb := some - (Expr.app (.proj ``Iff 0 (← mkAppM ``bne_iff_ne #[ra, rb])) (← mkEqRefl (.const ``true []))) + (Expr.app (.proj ``Iff 0 (← mkAppOptM ``bne_iff_ne #[none, none, none, ra, rb])) + (← mkEqRefl (.const ``true []))) else if let some c₁ ← isConstructorApp? ra then if let some c₂ ← isConstructorApp? rb then @@ -1808,7 +1809,8 @@ def propagateValueInconsistency (e₁ e₂ : Expr) : CCM Unit := do let some eqProof ← getEqProof e₁ e₂ | failure let trueEqFalse ← mkEq (.const ``True []) (.const ``False []) let neProof := - Expr.app (.proj ``Iff 0 (← mkAppM ``bne_iff_ne #[e₁, e₂])) (← mkEqRefl (.const ``true [])) + Expr.app (.proj ``Iff 0 (← mkAppOptM ``bne_iff_ne #[none, none, none, e₁, e₂])) + (← mkEqRefl (.const ``true [])) let H ← mkAbsurd trueEqFalse eqProof neProof pushEq (.const ``True []) (.const ``False []) H diff --git a/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean b/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean index e7c2dd37d4f41..42225947c25da 100644 --- a/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean +++ b/Mathlib/Tactic/CategoryTheory/Bicategory/Datatypes.lean @@ -103,7 +103,7 @@ instance : MonadMor₁ BicategoryM where section universe w v u -variable {B : Type u} [Bicategory.{w, v} B] {a b c d e : B} +variable {B : Type u} [Bicategory.{w, v} B] {a b c : B} theorem structuralIso_inv {f g : a ⟶ b} (η : f ≅ g) : η.symm.hom = η.inv := by diff --git a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean index 2e58492c79e90..7104020508294 100644 --- a/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean +++ b/Mathlib/Tactic/CategoryTheory/BicategoryCoherence.lean @@ -27,7 +27,7 @@ open CategoryTheory CategoryTheory.FreeBicategory open scoped Bicategory -variable {B : Type u} [Bicategory.{w, v} B] {a b c d e : B} +variable {B : Type u} [Bicategory.{w, v} B] {a b c d : B} namespace Mathlib.Tactic.BicategoryCoherence diff --git a/Mathlib/Tactic/CategoryTheory/Elementwise.lean b/Mathlib/Tactic/CategoryTheory/Elementwise.lean index 6ed09d82703a2..4a108c00b9927 100644 --- a/Mathlib/Tactic/CategoryTheory/Elementwise.lean +++ b/Mathlib/Tactic/CategoryTheory/Elementwise.lean @@ -93,7 +93,7 @@ def elementwiseExpr (src : Name) (type pf : Expr) (simpSides := true) : -- check that it's not a simp-trivial equality: forallTelescope ty' fun _ ty' => do if let some (_, lhs, rhs) := ty'.eq? then - if ← Std.Tactic.Lint.isSimpEq lhs rhs then + if ← Batteries.Tactic.Lint.isSimpEq lhs rhs then throwError "applying simp to both sides reduces elementwise lemma for {src} \ to the trivial equality {ty'}. \ Either add `nosimp` or remove the `elementwise` attribute." diff --git a/Mathlib/Tactic/CategoryTheory/Slice.lean b/Mathlib/Tactic/CategoryTheory/Slice.lean index f3f88410158c6..d0c2105619b6e 100644 --- a/Mathlib/Tactic/CategoryTheory/Slice.lean +++ b/Mathlib/Tactic/CategoryTheory/Slice.lean @@ -2,7 +2,6 @@ Copyright (c) 2018 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison - -/ import Mathlib.CategoryTheory.Category.Basic import Mathlib.Tactic.Conv diff --git a/Mathlib/Tactic/DeprecateMe.lean b/Mathlib/Tactic/DeprecateMe.lean index 3fb56313bec00..b84b97f0b4c2c 100644 --- a/Mathlib/Tactic/DeprecateMe.lean +++ b/Mathlib/Tactic/DeprecateMe.lean @@ -107,7 +107,7 @@ Technically, the command also take an optional `String` argument to fill in the However, its use is mostly intended for debugging purposes, where having a variable date would make tests time-dependent. -/ -elab tk:"deprecate to " id:ident* dat:(str)? ppLine cmd:command : command => do +elab tk:"deprecate to " id:ident* dat:(ppSpace str ppSpace)? ppLine cmd:command : command => do let oldEnv ← getEnv try elabCommand cmd diff --git a/Mathlib/Tactic/FunProp/ContDiff.lean b/Mathlib/Tactic/FunProp/ContDiff.lean index adc20fffe2b95..037d1812296a5 100644 --- a/Mathlib/Tactic/FunProp/ContDiff.lean +++ b/Mathlib/Tactic/FunProp/ContDiff.lean @@ -23,8 +23,7 @@ variable {K : Type*} [NontriviallyNormedField K] variable {E : Type*} [NormedAddCommGroup E] [NormedSpace K E] variable {F : Type*} [NormedAddCommGroup F] [NormedSpace K F] variable {G : Type*} [NormedAddCommGroup G] [NormedSpace K G] -variable {G' : Type*} [NormedAddCommGroup G'] [NormedSpace K G'] -variable {f f₀ f₁ g : E → F} {x} {s t} {n} +variable {f : E → F} {x} {s} {n} theorem contDiff_id' : ContDiff K n (fun x : E => x) := contDiff_id @@ -42,8 +41,8 @@ theorem ContDiffAt.comp' {f : E → F} {g : F → G} (hg : ContDiffAt K n g (f x -- theorem ContDiffOn.comp'' {g : F → G} {t : Set F} (hg : ContDiffOn K n g t) -- (hf : ContDiffOn K n f s) (st : Set.MapsTo f s t) : ContDiffOn K n (fun x => g (f x)) s := -variable {ι ι' : Type*} [Fintype ι] [Fintype ι'] {F' : ι → Type*} [∀ i, NormedAddCommGroup (F' i)] - [∀ i, NormedSpace K (F' i)] {φ : ∀ i, E → F' i} {Φ : E → ∀ i, F' i} +variable {ι : Type*} [Fintype ι] {F' : ι → Type*} [∀ i, NormedAddCommGroup (F' i)] + [∀ i, NormedSpace K (F' i)] {Φ : E → ∀ i, F' i} theorem contDiff_pi' (hΦ : ∀ i, ContDiff K n fun x => Φ x i) : ContDiff K n Φ := contDiff_pi.2 hΦ @@ -60,8 +59,7 @@ section div variable {K : Type*} [NontriviallyNormedField K] variable {E : Type*} [NormedAddCommGroup E] [NormedSpace K E] -variable {F : Type*} [NormedAddCommGroup F] [NormedSpace K F] -variable {f f₀ f₁ g : E → F} {x} {s t} {n} +variable {s} theorem ContDiffOn.div' [CompleteSpace K] {f g : E → K} {n} (hf : ContDiffOn K n f s) (hg : ContDiffOn K n g s) (h₀ : ∀ x ∈ s, g x ≠ 0) : ContDiffOn K n (fun x => f x / g x) s := @@ -74,7 +72,6 @@ end div section deriv variable {K : Type*} [NontriviallyNormedField K] -variable {E : Type*} [NormedAddCommGroup E] [NormedSpace K E] variable {F : Type*} [NormedAddCommGroup F] [NormedSpace K F] /-- Original version `ContDiff.differentiable_iteratedDeriv` introduces a new variable `(n:ℕ∞)` diff --git a/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean b/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean index da93ffa29a9af..141a5bb819107 100644 --- a/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean +++ b/Mathlib/Tactic/FunProp/RefinedDiscrTree.lean @@ -449,7 +449,7 @@ partial def reduce (e : Expr) (config : WhnfCoreConfig) : MetaM Expr := do /-- Repeatedly apply reduce while stripping lambda binders and introducing their variables -/ @[specialize] partial def lambdaTelescopeReduce {m} [Monad m] [MonadLiftT MetaM m] [MonadControlT MetaM m] - [Inhabited α] (e : Expr) (fvars : List FVarId) (config : WhnfCoreConfig) + [Nonempty α] (e : Expr) (fvars : List FVarId) (config : WhnfCoreConfig) (k : Expr → List FVarId → m α) : m α := do match ← reduce e config with | .lam n d b bi => diff --git a/Mathlib/Tactic/GeneralizeProofs.lean b/Mathlib/Tactic/GeneralizeProofs.lean index 7acd8bef29e3e..645637ae46a0f 100644 --- a/Mathlib/Tactic/GeneralizeProofs.lean +++ b/Mathlib/Tactic/GeneralizeProofs.lean @@ -341,7 +341,7 @@ This continuation `k` is passed The `propToFVar` map is updated with the new proposition fvars. -/ -partial def withGeneralizedProofs {α : Type} [Inhabited α] (e : Expr) (ty? : Option Expr) +partial def withGeneralizedProofs {α : Type} [Nonempty α] (e : Expr) (ty? : Option Expr) (k : Array Expr → Array Expr → Expr → MGen α) : MGen α := do let propToFVar := (← get).propToFVar @@ -351,7 +351,7 @@ partial def withGeneralizedProofs {α : Type} [Inhabited α] (e : Expr) (ty? : O post-abstracted{indentD e}\nnew generalizations: {generalizations}" let rec /-- Core loop for `withGeneralizedProofs`, adds generalizations one at a time. -/ - go [Inhabited α] (i : Nat) (fvars pfs : Array Expr) + go [Nonempty α] (i : Nat) (fvars pfs : Array Expr) (proofToFVar propToFVar : ExprMap Expr) : MGen α := do if h : i < generalizations.size then let (ty, pf) := generalizations[i] diff --git a/Mathlib/Tactic/IntervalCases.lean b/Mathlib/Tactic/IntervalCases.lean index 52169b6406e4c..37e90dfc742f4 100644 --- a/Mathlib/Tactic/IntervalCases.lean +++ b/Mathlib/Tactic/IntervalCases.lean @@ -5,6 +5,7 @@ Authors: Kim Morrison, Mario Carneiro -/ import Mathlib.Tactic.NormNum import Mathlib.Tactic.FinCases +import Mathlib.Control.Basic /-! # Case bash on variables in finite intervals diff --git a/Mathlib/Tactic/Lemma.lean b/Mathlib/Tactic/Lemma.lean index 901874a9f585a..10d49cd8d8a8f 100644 --- a/Mathlib/Tactic/Lemma.lean +++ b/Mathlib/Tactic/Lemma.lean @@ -12,8 +12,9 @@ import Lean.Parser.Command open Lean +-- higher priority to override the one in Batteries /-- `lemma` means the same as `theorem`. It is used to denote "less important" theorems -/ -syntax (name := lemma) declModifiers +syntax (name := lemma) (priority := default + 1) declModifiers group("lemma " declId ppIndent(declSig) declVal) : command /-- Implementation of the `lemma` command, by macro expansion to `theorem`. -/ diff --git a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean index 053e563cbbe5e..d1b3479c6c896 100644 --- a/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean +++ b/Mathlib/Tactic/Linarith/Oracle/FourierMotzkin.lean @@ -259,7 +259,7 @@ The linarith monad extends an exceptional monad with a `LinarithData` state. An exception produces a contradictory `PComp`. -/ abbrev LinarithM : Type → Type := - StateT LinarithData (ExceptT PComp Id) + StateT LinarithData (ExceptT PComp Lean.Core.CoreM) /-- Returns the current max variable. -/ def getMaxVar : LinarithM ℕ := @@ -273,7 +273,7 @@ def getPCompSet : LinarithM PCompSet := def validate : LinarithM Unit := do match (← getPCompSet).toList.find? (fun p : PComp => p.isContr) with | none => return () - | some c => throw c + | some c => throwThe _ c /-- Updates the current state with a new max variable and comparisons, @@ -305,9 +305,12 @@ from the `linarith` state. -/ def elimVarM (a : ℕ) : LinarithM Unit := do let vs ← getMaxVar - if (a ≤ vs) then (do + if (a ≤ vs) then + Lean.Core.checkSystem decl_name%.toString let ⟨pos, neg, notPresent⟩ := splitSetByVarSign a (← getPCompSet) - update (vs - 1) (pos.foldl (fun s p => s.union (elimWithSet a p neg)) notPresent)) + update (vs - 1) (← pos.foldlM (fun s p => do + Lean.Core.checkSystem decl_name%.toString + pure (s.union (elimWithSet a p neg))) notPresent) else pure () @@ -328,9 +331,12 @@ def mkLinarithData (hyps : List Comp) (maxVar : ℕ) : LinarithData := /-- An oracle that uses Fourier-Motzkin elimination. -/ def CertificateOracle.fourierMotzkin : CertificateOracle where - produceCertificate hyps maxVar := match ExceptT.run - (StateT.run (do validate; elimAllVarsM : LinarithM Unit) (mkLinarithData hyps maxVar)) with - | (Except.ok _) => failure - | (Except.error contr) => return contr.src.flatten + produceCertificate hyps maxVar := do + let linarithData := mkLinarithData hyps maxVar + let result ← + (ExceptT.run (StateT.run (do validate; elimAllVarsM : LinarithM Unit) linarithData) : _) + match result with + | (Except.ok _) => failure + | (Except.error contr) => return contr.src.flatten end Linarith diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Gauss.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Gauss.lean index ab46c5726b44f..93cad0a43aa77 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Gauss.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/Gauss.lean @@ -15,7 +15,7 @@ solution which is done by standard Gaussian Elimination algorithm implemented in namespace Linarith.SimplexAlgorithm.Gauss /-- The monad for the Gaussian Elimination algorithm. -/ -abbrev GaussM (n m : Nat) (matType : Nat → Nat → Type) := StateM <| matType n m +abbrev GaussM (n m : Nat) (matType : Nat → Nat → Type) := StateT (matType n m) Lean.CoreM variable {n m : Nat} {matType : Nat → Nat → Type} [UsableInSimplexAlgorithm matType] @@ -35,6 +35,7 @@ def getTableauImp : GaussM n m matType <| Tableau matType := do let mut col : Nat := 0 while row < n && col < m do + Lean.Core.checkSystem decl_name%.toString match ← findNonzeroRow row col with | .none => free := free.push col @@ -74,7 +75,7 @@ Given matrix `A`, solves the linear equation `A x = 0` and returns the solution some variables are free and others (basic) variable are expressed as linear combinations of the free ones. -/ -def getTableau (A : matType n m) : Tableau matType := Id.run do +def getTableau (A : matType n m) : Lean.CoreM (Tableau matType) := do return (← getTableauImp.run A).fst end Linarith.SimplexAlgorithm.Gauss diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean index c93e2e33f9b24..97f8d6d475622 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/PositiveVector.lean @@ -90,10 +90,10 @@ def findPositiveVector {n m : Nat} {matType : Nat → Nat → Type} [UsableInSim /- Using Gaussian elimination split variable into free and basic forming the tableau that will be operated by the Simplex Algorithm. -/ - let initTableau := Gauss.getTableau B + let initTableau ← Gauss.getTableau B /- Run the Simplex Algorithm and extract the solution. -/ - let res := runSimplexAlgorithm.run initTableau + let res ← runSimplexAlgorithm.run initTableau if res.fst.isOk then return extractSolution res.snd else diff --git a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean index 924814fa69fce..9858e94c23f14 100644 --- a/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean +++ b/Mathlib/Tactic/Linarith/Oracle/SimplexAlgorithm/SimplexAlgorithm.lean @@ -21,7 +21,7 @@ inductive SimplexAlgorithmException /-- The monad for the Simplex Algorithm. -/ abbrev SimplexAlgorithmM (matType : Nat → Nat → Type) [UsableInSimplexAlgorithm matType] := - ExceptT SimplexAlgorithmException <| StateM (Tableau matType) + ExceptT SimplexAlgorithmException <| StateT (Tableau matType) Lean.CoreM variable {matType : Nat → Nat → Type} [UsableInSimplexAlgorithm matType] @@ -77,7 +77,7 @@ def chooseEnteringVar : SimplexAlgorithmM matType Nat := do /- If there is no such variable the solution does not exist for sure. -/ match enterIdxOpt with - | .none => throw SimplexAlgorithmException.infeasible + | .none => throwThe SimplexAlgorithmException SimplexAlgorithmException.infeasible | .some enterIdx => return enterIdx /-- @@ -116,6 +116,7 @@ such exists. -/ def runSimplexAlgorithm : SimplexAlgorithmM matType Unit := do while !(← checkSuccess) do + Lean.Core.checkSystem decl_name%.toString let ⟨exitIdx, enterIdx⟩ ← choosePivots doPivotOperation exitIdx enterIdx diff --git a/Mathlib/Tactic/Linarith/Verification.lean b/Mathlib/Tactic/Linarith/Verification.lean index 9cda494376353..b8702e24fc4f5 100644 --- a/Mathlib/Tactic/Linarith/Verification.lean +++ b/Mathlib/Tactic/Linarith/Verification.lean @@ -191,6 +191,7 @@ def proveFalseByLinarith (transparency : TransparencyMode) (oracle : Certificate | _, [] => throwError "no args to linarith" | g, l@(h::_) => do trace[linarith.detail] "Beginning work in `proveFalseByLinarith`." + Lean.Core.checkSystem decl_name%.toString -- for the elimination to work properly, we must add a proof of `-1 < 0` to the list, -- along with negated equality proofs. let l' ← addNegEqProofs l diff --git a/Mathlib/Tactic/Linter.lean b/Mathlib/Tactic/Linter.lean index e40a62f821d5a..2f67da1bea192 100644 --- a/Mathlib/Tactic/Linter.lean +++ b/Mathlib/Tactic/Linter.lean @@ -11,4 +11,4 @@ This file is ignored by `shake`: import Mathlib.Tactic.Linter.FlexibleLinter import Mathlib.Tactic.Linter.HaveLetLinter import Mathlib.Tactic.Linter.MinImports -import Mathlib.Tactic.Linter.TextBased +import Mathlib.Tactic.Linter.PPRoundtrip diff --git a/Mathlib/Tactic/Linter/DocPrime.lean b/Mathlib/Tactic/Linter/DocPrime.lean new file mode 100644 index 0000000000000..79a08666bae3f --- /dev/null +++ b/Mathlib/Tactic/Linter/DocPrime.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2024 Damiano Testa. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damiano Testa +-/ +import Lean.Elab.Command + +/-! +# The "docPrime" linter + +The "docPrime" linter emits a warning on declarations that have no doc-string and whose +name ends with a `'`. Such declarations are expected to have a documented explanation +for the presence of a `'` in their name. This may consist of discussion of the difference relative +to an unprimed version of that declaration, or an explanation as to why no better naming scheme +is possible. +-/ + +open Lean Elab + +namespace Mathlib.Linter + +/-- +The "docPrime" linter emits a warning on declarations that have no doc-string and whose +name ends with a `'`. + +The file `scripts/no_lints_prime_decls.txt` contains a list of temporary exceptions to this linter. +This list should not be appended to, and become emptied over time. +-/ +register_option linter.docPrime : Bool := { + defValue := false + descr := "enable the docPrime linter" +} + +namespace DocPrime + +@[inherit_doc Mathlib.Linter.linter.docPrime] +def docPrimeLinter : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.docPrime (← getOptions) do + return + if (← get).messages.hasErrors then + return + unless [``Lean.Parser.Command.declaration, `lemma].contains stx.getKind do return + -- ignore private declarations + if (stx.find? (·.isOfKind ``Lean.Parser.Command.private)).isSome then return + let docstring := stx[0][0] + -- The current declaration's id, possibly followed by a list of universe names. + let declId := + if stx[1].isOfKind ``Lean.Parser.Command.instance then + stx[1][3][0] + else + stx[1][1] + -- The name of the current declaration, with namespaces resolved. + let declName := + if let `_root_ :: rest := declId[0].getId.components then + rest.foldl (· ++ ·) default + else (← getCurrNamespace) ++ declId[0].getId + let msg := m!"`{declName}` is missing a doc-string, please add one.\n\ + Declarations whose name ends with a `'` are expected to contain an explanation for the \ + presence of a `'` in their doc-string. This may consist of discussion of the difference \ + relative to the unprimed version, or an explanation as to why no better naming scheme \ + is possible." + if docstring[0][1].getAtomVal.isEmpty && declName.toString.back == '\'' then + if ← System.FilePath.pathExists "scripts/no_lints_prime_decls.txt" then + if (← IO.FS.lines "scripts/no_lints_prime_decls.txt").contains declName.toString then + return + else + Linter.logLint linter.docPrime declId msg + else + Linter.logLint linter.docPrime declId msg + +initialize addLinter docPrimeLinter + +end DocPrime + +end Mathlib.Linter diff --git a/Mathlib/Tactic/Linter/Lint.lean b/Mathlib/Tactic/Linter/Lint.lean index c4fe07059049e..6d00f05354dde 100644 --- a/Mathlib/Tactic/Linter/Lint.lean +++ b/Mathlib/Tactic/Linter/Lint.lean @@ -13,7 +13,7 @@ In this file we define additional linters for mathlib. Perhaps these should be moved to Batteries in the future. -/ -namespace Std.Tactic.Lint +namespace Batteries.Tactic.Lint open Lean Meta /-- @@ -45,7 +45,7 @@ Linter that checks whether a structure should be in Prop. | some _ => return none -- TODO: enforce `YYYY-MM-DD` format | none => return m!"`deprecated` attribute without `since` date" -end Std.Tactic.Lint +end Batteries.Tactic.Lint namespace Mathlib.Linter @@ -320,6 +320,12 @@ register_option linter.style.longFile : Nat := { descr := "enable the longFile linter" } +/-- The number of lines that the `longFile` linter considers the default. -/ +register_option linter.style.longFileDefValue : Nat := { + defValue := 1500 + descr := "a soft upper bound on the number of lines of each file" +} + namespace Style.longFile @[inherit_doc Mathlib.Linter.linter.style.longFile] @@ -327,7 +333,7 @@ def longFileLinter : Linter where run := withSetOptionIn fun stx ↦ do let linterBound := linter.style.longFile.get (← getOptions) if linterBound == 0 then return - let defValue := 1500 + let defValue := linter.style.longFileDefValue.get (← getOptions) let smallOption := match stx with | `(set_option linter.style.longFile $x) => TSyntax.getNat ⟨x.raw⟩ ≤ defValue | _ => false diff --git a/Mathlib/Tactic/Linter/PPRoundtrip.lean b/Mathlib/Tactic/Linter/PPRoundtrip.lean new file mode 100644 index 0000000000000..f6f25280cc338 --- /dev/null +++ b/Mathlib/Tactic/Linter/PPRoundtrip.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2024 Damiano Testa. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Damiano Testa +-/ + +import Lean.Elab.Command +import Mathlib.Init + +/-! +# The "ppRoundtrip" linter + +The "ppRoundtrip" linter emits a warning when the syntax of a command differs substantially +from the pretty-printed version of itself. +-/ +open Lean Elab Command + +namespace Mathlib.Linter + +/-- +The "ppRoundtrip" linter emits a warning when the syntax of a command differs substantially +from the pretty-printed version of itself. + +The linter makes an effort to start the highlighting at the first difference. +However, it may not always be successful. +It also prints both the source code and the "expected code" in a 5-character radius from +the first difference. +-/ +register_option linter.ppRoundtrip : Bool := { + defValue := false + descr := "enable the ppRoundtrip linter" +} + +/-- `polishPP s` takes as input a `String` `s`, assuming that it is the output of +pretty-printing a lean command. +The main intent is to convert `s` to a reasonable candidate for a desirable source code format. +The function first replaces consecutive whitespace sequences into a single space (` `), in an +attempt to side-step line-break differences. +After that, it applies some pre-emptive changes: +* doc-module beginnings tend to have some whitespace following them, so we add a space back in; +* name quotations such as ``` ``Nat``` get pretty-printed as ``` `` Nat```, so we remove a space + after double back-ticks, but take care of adding one more for triple (or more) back-ticks; +* `notation3` is not followed by a pretty-printer space, so we add it here (#15515). +-/ +def polishPP (s : String) : String := + let s := s.split (·.isWhitespace) + (" ".intercalate (s.filter (!·.isEmpty))) + |>.replace "/-!" "/-! " + |>.replace "``` " "``` " -- avoid losing an existing space after the triple back-ticks + -- as a consequence of the following replacement + |>.replace "`` " "``" -- weird pp ```#eval ``«Nat»``` pretty-prints as ```#eval `` «Nat»``` + |>.replace "notation3(" "notation3 (" + |>.replace "notation3\"" "notation3 \"" + +/-- `polishSource s` is similar to `polishPP s`, but expects the input to be actual source code. +For this reason, `polishSource s` performs more conservative changes: +it only replace all whitespace starting from a linebreak (`\n`) with a single whitespace. -/ +def polishSource (s : String) : String × Array Nat := + let split := s.split (· == '\n') + let preWS := split.foldl (init := #[]) fun p q => + let txt := q.trimLeft.length + (p.push (q.length - txt)).push txt + let preWS := preWS.eraseIdx 0 + let s := (split.map .trimLeft).filter (· != "") + (" ".intercalate (s.filter (!·.isEmpty)), preWS) + +/-- `posToShiftedPos lths diff` takes as input an array `lths` of natural numbers, +and one further natural number `diff`. +It adds up the elements of `lths` occupying the odd positions, as long as the sum of the +elements in the even positions does not exceed `diff`. +It returns the sum of the accumulated odds and `diff`. +This is useful to figure out the difference between the output of `polishSource s` and `s` itself. +It plays a role similar to the `fileMap`. -/ +def posToShiftedPos (lths : Array Nat) (diff : Nat) : Nat := Id.run do + let mut (ws, noWS) := (diff, 0) + for con in [:lths.size / 2] do + let curr := lths[2 * con]! + if noWS + curr < diff then + noWS := noWS + curr + ws := ws + lths[2 * con + 1]! + else + break + return ws + +/-- `zoomString str centre offset` returns the substring of `str` consisting of the `offset` +characters around the `centre`th character. -/ +def zoomString (str : String) (centre offset : Nat) : Substring := + { str := str, startPos := ⟨centre - offset⟩, stopPos := ⟨centre + offset⟩ } + +/-- `capSourceInfo s p` "shortens" all end-position information in the `SourceInfo` `s` to be +at most `p`, trimming down also the relevant substrings. -/ +def capSourceInfo (s : SourceInfo) (p : Nat) : SourceInfo := + match s with + | .original leading pos trailing endPos => + .original leading pos {trailing with stopPos := ⟨min endPos.1 p⟩} ⟨min endPos.1 p⟩ + | .synthetic pos endPos canonical => + .synthetic pos ⟨min endPos.1 p⟩ canonical + | .none => s + +/-- `capSyntax stx p` applies `capSourceInfo · s` to all `SourceInfo`s in all +`node`s, `atom`s and `ident`s contained in `stx`. + +This is used to trim away all "fluff" that follows a command: comments and whitespace after +a command get removed with `capSyntax stx stx.getTailPos?.get!`. +-/ +partial +def capSyntax (stx : Syntax) (p : Nat) : Syntax := + match stx with + | .node si k args => .node (capSourceInfo si p) k (args.map (capSyntax · p)) + | .atom si val => .atom (capSourceInfo si p) (val.take p) + | .ident si r v pr => .ident (capSourceInfo si p) { r with stopPos := ⟨min r.stopPos.1 p⟩ } v pr + | s => s + +namespace PPRoundtrip + +@[inherit_doc Mathlib.Linter.linter.ppRoundtrip] +def ppRoundtrip : Linter where run := withSetOptionIn fun stx ↦ do + unless Linter.getLinterValue linter.ppRoundtrip (← getOptions) do + return + if (← MonadState.get).messages.hasErrors then + return + let stx := capSyntax stx (stx.getTailPos?.getD default).1 + let origSubstring := stx.getSubstring?.getD default + let (real, lths) := polishSource origSubstring.toString + let fmt ← (liftCoreM do PrettyPrinter.ppCategory `command stx <|> (do + Linter.logLint linter.ppRoundtrip stx + m!"The ppRoundtrip linter had some parsing issues: \ + feel free to silence it with `set_option linter.ppRoundtrip false in` \ + and report this error!" + return real)) + let st := polishPP fmt.pretty + if st != real then + let diff := real.firstDiffPos st + let pos := posToShiftedPos lths diff.1 + origSubstring.startPos.1 + let f := origSubstring.str.drop (pos) + let extraLth := (f.takeWhile (· != st.get diff)).length + let srcCtxt := zoomString real diff.1 5 + let ppCtxt := zoomString st diff.1 5 + Linter.logLint linter.ppRoundtrip (.ofRange ⟨⟨pos⟩, ⟨pos + extraLth + 1⟩⟩) + m!"source context\n'{srcCtxt}'\n'{ppCtxt}'\npretty-printed context" + +initialize addLinter ppRoundtrip + +end Mathlib.Linter.PPRoundtrip diff --git a/Mathlib/Tactic/Linter/UnusedTactic.lean b/Mathlib/Tactic/Linter/UnusedTactic.lean index 7528d2a53673f..67eb1b34f7d9f 100644 --- a/Mathlib/Tactic/Linter/UnusedTactic.lean +++ b/Mathlib/Tactic/Linter/UnusedTactic.lean @@ -92,6 +92,7 @@ initialize allowedRef : IO.Ref (Std.HashSet SyntaxNodeKind) ← |>.insert `Mathlib.Tactic.tacticMatch_target_ |>.insert `change? |>.insert `«tactic#adaptation_note_» + |>.insert `tacticSleep_heartbeats_ /-- `#allow_unused_tactic` takes an input a space-separated list of identifiers. These identifiers are then allowed by the unused tactic linter: diff --git a/Mathlib/Tactic/ModCases.lean b/Mathlib/Tactic/ModCases.lean index 9846cca299457..fd1a5afdd358f 100644 --- a/Mathlib/Tactic/ModCases.lean +++ b/Mathlib/Tactic/ModCases.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Mario Carneiro, Heather Macbeth -/ import Mathlib.Data.Int.ModEq +import Mathlib.Tactic.HaveI /-! # `mod_cases` tactic diff --git a/Mathlib/Tactic/Module.lean b/Mathlib/Tactic/Module.lean new file mode 100644 index 0000000000000..fd9b22fd82518 --- /dev/null +++ b/Mathlib/Tactic/Module.lean @@ -0,0 +1,657 @@ +/- +Copyright (c) 2024 Heather Macbeth. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Heather Macbeth +-/ +import Mathlib.Algebra.Algebra.Tower +import Mathlib.Algebra.BigOperators.GroupWithZero.Action +import Mathlib.Tactic.Ring +import Mathlib.Util.AtomM + +/-! # A tactic for normalization over modules + +This file provides the two tactics `match_scalars` and `module`. Given a goal which is an equality +in a type `M` (with `M` an `AddCommMonoid`), the `match_scalars` tactic parses the LHS and RHS of +the goal as linear combinations of `M`-atoms over some semiring `R`, and reduces the goal to +the respective equalities of the `R`-coefficients of each atom. The `module` tactic does this and +then runs the `ring` tactic on each of these coefficient-wise equalities, failing if this does not +resolve them. + +The scalar type `R` is not pre-determined: instead it starts as `ℕ` (when each atom is initially +given a scalar `(1:ℕ)`) and gets bumped up into bigger semirings when such semirings are +encountered. However, to permit this, it is assumed that there is a "linear order" on all the +semirings which appear in the expression: for any two semirings `R` and `S` which occur, we have +either `Algebra R S` or `Algebra S R`). +-/ + +open Lean hiding Module +open Meta Elab Qq Mathlib.Tactic List + +namespace Mathlib.Tactic.Module + +/-! ### Theory of lists of pairs (scalar, vector) + +This section contains the lemmas which are orchestrated by the `match_scalars` and `module` tactics +to prove goals in modules. The basic object which these lemmas concern is `NF R M`, a type synonym +for a list of ordered pairs in `R × M`, where typically `M` is an `R`-module. +-/ + +/-- Basic theoretical "normal form" object of the `match_scalars` and `module` tactics: a type +synonym for a list of ordered pairs in `R × M`, where typically `M` is an `R`-module. This is the +form to which the tactics reduce module expressions. + +(It is not a full "normal form" because the scalars, i.e. `R` components, are not themselves +ring-normalized. But this partial normal form is more convenient for our purposes.) -/ +def NF (R : Type*) (M : Type*) := List (R × M) + +namespace NF +variable {S : Type*} {R : Type*} {M : Type*} + +/-- Augment a `Module.NF R M` object `l`, i.e. a list of pairs in `R × M`, by prepending another +pair `p : R × M`. -/ +@[match_pattern] +def cons (p : R × M) (l : NF R M) : NF R M := p :: l + +@[inherit_doc cons] infixl:100 " ::ᵣ " => cons + +/-- Evaluate a `Module.NF R M` object `l`, i.e. a list of pairs in `R × M`, to an element of `M`, by +forming the "linear combination" it specifies: scalar-multiply each `R` term to the corresponding +`M` term, then add them all up. -/ +def eval [Add M] [Zero M] [SMul R M] (l : NF R M) : M := (l.map (fun (⟨r, x⟩ : R × M) ↦ r • x)).sum + +@[simp] theorem eval_cons [AddMonoid M] [SMul R M] (p : R × M) (l : NF R M) : + (p ::ᵣ l).eval = p.1 • p.2 + l.eval := by + unfold eval cons + rw [List.map_cons] + rw [List.sum_cons] + +theorem atom_eq_eval [AddMonoid M] (x : M) : x = NF.eval [(1, x)] := by simp [eval] + +variable (M) in +theorem zero_eq_eval [AddMonoid M] : (0:M) = NF.eval (R := ℕ) (M := M) [] := rfl + +theorem add_eq_eval₁ [AddMonoid M] [SMul R M] (a₁ : R × M) {a₂ : R × M} {l₁ l₂ l : NF R M} + (h : l₁.eval + (a₂ ::ᵣ l₂).eval = l.eval) : + (a₁ ::ᵣ l₁).eval + (a₂ ::ᵣ l₂).eval = (a₁ ::ᵣ l).eval := by + simp only [eval_cons, ← h, add_assoc] + +theorem add_eq_eval₂ [Semiring R] [AddCommMonoid M] [Module R M] (r₁ r₂ : R) (x : M) + {l₁ l₂ l : NF R M} (h : l₁.eval + l₂.eval = l.eval) : + ((r₁, x) ::ᵣ l₁).eval + ((r₂, x) ::ᵣ l₂).eval = ((r₁ + r₂, x) ::ᵣ l).eval := by + simp only [← h, eval_cons, add_smul, add_assoc] + congr! 1 + simp only [← add_assoc] + congr! 1 + rw [add_comm] + +theorem add_eq_eval₃ [Semiring R] [AddCommMonoid M] [Module R M] {a₁ : R × M} (a₂ : R × M) + {l₁ l₂ l : NF R M} (h : (a₁ ::ᵣ l₁).eval + l₂.eval = l.eval) : + (a₁ ::ᵣ l₁).eval + (a₂ ::ᵣ l₂).eval = (a₂ ::ᵣ l).eval := by + simp only [eval_cons, ← h] + nth_rw 4 [add_comm] + simp only [add_assoc] + congr! 2 + rw [add_comm] + +theorem add_eq_eval {R₁ R₂ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] {l₁ l₂ l : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} + {x₁ x₂ : M} (hx₁ : x₁ = l₁'.eval) (hx₂ : x₂ = l₂'.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval + l₂.eval = l.eval) : + x₁ + x₂ = l.eval := by + rw [hx₁, hx₂, ← h₁, ← h₂, h] + +theorem sub_eq_eval₁ [SMul R M] [AddGroup M] (a₁ : R × M) {a₂ : R × M} {l₁ l₂ l : NF R M} + (h : l₁.eval - (a₂ ::ᵣ l₂).eval = l.eval) : + (a₁ ::ᵣ l₁).eval - (a₂ ::ᵣ l₂).eval = (a₁ ::ᵣ l).eval := by + simp only [eval_cons, ← h, sub_eq_add_neg, add_assoc] + +theorem sub_eq_eval₂ [Ring R] [AddCommGroup M] [Module R M] (r₁ r₂ : R) (x : M) {l₁ l₂ l : NF R M} + (h : l₁.eval - l₂.eval = l.eval) : + ((r₁, x) ::ᵣ l₁).eval - ((r₂, x) ::ᵣ l₂).eval = ((r₁ - r₂, x) ::ᵣ l).eval := by + simp only [← h, eval_cons, sub_smul, sub_eq_add_neg, neg_add, add_smul, neg_smul, add_assoc] + congr! 1 + simp only [← add_assoc] + congr! 1 + rw [add_comm] + +theorem sub_eq_eval₃ [Ring R] [AddCommGroup M] [Module R M] {a₁ : R × M} (a₂ : R × M) + {l₁ l₂ l : NF R M} (h : (a₁ ::ᵣ l₁).eval - l₂.eval = l.eval) : + (a₁ ::ᵣ l₁).eval - (a₂ ::ᵣ l₂).eval = ((-a₂.1, a₂.2) ::ᵣ l).eval := by + simp only [eval_cons, neg_smul, neg_add, sub_eq_add_neg, ← h, ← add_assoc] + congr! 1 + rw [add_comm, add_assoc] + +theorem sub_eq_eval {R₁ R₂ S₁ S₂ : Type*} [AddCommGroup M] [Ring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] [Semiring S₁] [Module S₁ M] [Semiring S₂] + [Module S₂ M] {l₁ l₂ l : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} {l₁'' : NF S₁ M} + {l₂'' : NF S₂ M} {x₁ x₂ : M} (hx₁ : x₁ = l₁''.eval) (hx₂ : x₂ = l₂''.eval) + (h₁' : l₁'.eval = l₁''.eval) (h₂' : l₂'.eval = l₂''.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval - l₂.eval = l.eval) : + x₁ - x₂ = l.eval := by + rw [hx₁, hx₂, ← h₁', ← h₂', ← h₁, ← h₂, h] + +instance [Neg R] : Neg (NF R M) where + neg l := l.map fun (a, x) ↦ (-a, x) + +theorem eval_neg [AddCommGroup M] [Ring R] [Module R M] (l : NF R M) : (-l).eval = - l.eval := by + simp only [NF.eval, List.map_map, List.sum_neg, NF.instNeg] + congr + ext p + simp + +theorem zero_sub_eq_eval [AddCommGroup M] [Ring R] [Module R M] (l : NF R M) : + 0 - l.eval = (-l).eval := by + simp [eval_neg] + +theorem neg_eq_eval [AddCommGroup M] [Semiring S] [Module S M] [Ring R] [Module R M] {l : NF R M} + {l₀ : NF S M} (hl : l.eval = l₀.eval) {x : M} (h : x = l₀.eval) : + - x = (-l).eval := by + rw [h, ← hl, eval_neg] + +instance [Mul R] : SMul R (NF R M) where + smul r l := l.map fun (a, x) ↦ (r * a, x) + +@[simp] theorem smul_apply [Mul R] (r : R) (l : NF R M) : r • l = l.map fun (a, x) ↦ (r * a, x) := + rfl + +theorem eval_smul [AddCommMonoid M] [Semiring R] [Module R M] {l : NF R M} {x : M} (h : x = l.eval) + (r : R) : (r • l).eval = r • x := by + unfold NF.eval at h ⊢ + simp only [h, smul_sum, map_map, NF.smul_apply] + congr + ext p + simp [mul_smul] + +theorem smul_eq_eval {R₀ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₀] + [Module R₀ M] [Semiring S] [Module S M] {l : NF R M} {l₀ : NF R₀ M} {s : S} {r : R} + {x : M} (hx : x = l₀.eval) (hl : l.eval = l₀.eval) (hs : r • x = s • x) : + s • x = (r • l).eval := by + rw [← hs, hx, ← hl, eval_smul] + rfl + +theorem eq_cons_cons [AddMonoid M] [SMul R M] {r₁ r₂ : R} (m : M) {l₁ l₂ : NF R M} (h1 : r₁ = r₂) + (h2 : l₁.eval = l₂.eval) : + ((r₁, m) ::ᵣ l₁).eval = ((r₂, m) ::ᵣ l₂).eval := by + simp only [NF.eval, NF.cons] at * + simp [h1, h2] + +theorem eq_cons_const [AddCommMonoid M] [Semiring R] [Module R M] {r : R} (m : M) {n : M} + {l : NF R M} (h1 : r = 0) (h2 : l.eval = n) : + ((r, m) ::ᵣ l).eval = n := by + simp only [NF.eval, NF.cons] at * + simp [h1, h2] + +theorem eq_const_cons [AddCommMonoid M] [Semiring R] [Module R M] {r : R} (m : M) {n : M} + {l : NF R M} (h1 : 0 = r) (h2 : n = l.eval) : + n = ((r, m) ::ᵣ l).eval := by + simp only [NF.eval, NF.cons] at * + simp [← h1, h2] + +theorem eq_of_eval_eq_eval {R₁ R₂ : Type*} [AddCommMonoid M] [Semiring R] [Module R M] [Semiring R₁] + [Module R₁ M] [Semiring R₂] [Module R₂ M] {l₁ l₂ : NF R M} {l₁' : NF R₁ M} {l₂' : NF R₂ M} + {x₁ x₂ : M} (hx₁ : x₁ = l₁'.eval) (hx₂ : x₂ = l₂'.eval) (h₁ : l₁.eval = l₁'.eval) + (h₂ : l₂.eval = l₂'.eval) (h : l₁.eval = l₂.eval) : + x₁ = x₂ := by + rw [hx₁, hx₂, ← h₁, ← h₂, h] + +variable (R) + +/-- Operate on a `Module.NF S M` object `l`, i.e. a list of pairs in `S × M`, where `S` is some +commutative semiring, by applying to each `S`-component the algebra-map from `S` into a specified +`S`-algebra `R`. -/ +def algebraMap [CommSemiring S] [Semiring R] [Algebra S R] (l : NF S M) : NF R M := + l.map (fun ⟨s, x⟩ ↦ (_root_.algebraMap S R s, x)) + +theorem eval_algebraMap [CommSemiring S] [Semiring R] [Algebra S R] [AddMonoid M] [SMul S M] + [MulAction R M] [IsScalarTower S R M] (l : NF S M) : + (l.algebraMap R).eval = l.eval := by + simp only [NF.eval, algebraMap, map_map] + congr + ext + simp [IsScalarTower.algebraMap_smul] + +end NF + +variable {u v : Level} + +/-! ### Lists of expressions representing scalars and vectors, and operations on such lists -/ + +/-- Basic meta-code "normal form" object of the `match_scalars` and `module` tactics: a type synonym +for a list of ordered triples comprising expressions representing terms of two types `R` and `M` +(where typically `M` is an `R`-module), together with a natural number "index". + +The natural number represents the index of the `M` term in the `AtomM` monad: this is not enforced, +but is sometimes assumed in operations. Thus when items `((a₁, x₁), k)` and `((a₂, x₂), k)` +appear in two different `Module.qNF` objects (i.e. with the same `ℕ`-index `k`), it is expected that +the expressions `x₁` and `x₂` are the same. It is also expected that the items in a `Module.qNF` +list are in strictly increasing order by natural-number index. + +By forgetting the natural number indices, an expression representing a `Mathlib.Tactic.Module.NF` +object can be built from a `Module.qNF` object; this construction is provided as +`Mathlib.Tactic.Module.qNF.toNF`. -/ +abbrev qNF (R : Q(Type u)) (M : Q(Type v)) := List ((Q($R) × Q($M)) × ℕ) + +namespace qNF + +variable {M : Q(Type v)} {R : Q(Type u)} + +/-- Given `l` of type `qNF R M`, i.e. a list of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s and a natural +number), build an `Expr` representing an object of type `NF R M` (i.e. `List (R × M)`) in the +in the obvious way: by forgetting the natural numbers and gluing together the `Expr`s. -/ +def toNF (l : qNF R M) : Q(NF $R $M) := + let l' : List Q($R × $M) := (l.map Prod.fst).map (fun (a, x) ↦ q(($a, $x))) + let qt : List Q($R × $M) → Q(List ($R × $M)) := List.rec q([]) (fun e _ l ↦ q($e ::ᵣ $l)) + qt l' + +/-- Given `l` of type `qNF R₁ M`, i.e. a list of `(Q($R₁) × Q($M)) × ℕ`s (two `Expr`s and a natural +number), apply an expression representing a function with domain `R₁` to each of the `Q($R₁)` +components. -/ +def onScalar {u₁ u₂ : Level} {R₁ : Q(Type u₁)} {R₂ : Q(Type u₂)} (l : qNF R₁ M) (f : Q($R₁ → $R₂)) : + qNF R₂ M := + l.map fun ((a, x), k) ↦ ((q($f $a), x), k) + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct another such term `l`, which will have the property that in the +`$R`-module `$M`, the sum of the "linear combinations" represented by `l₁` and `l₂` is the linear +combination represented by `l`. + +The construction assumes, to be valid, that the lists `l₁` and `l₂` are in strictly increasing order +by `ℕ`-component, and that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with +the same `ℕ`-component `k`, then the expressions `x₁` and `x₂` are equal. + +The construction is as follows: merge the two lists, except that if pairs `(a₁, x₁)` and `(a₂, x₂)` +appear in `l₁`, `l₂` respectively with the same `ℕ`-component `k`, then contribute a term +`(a₁ + a₂, x₁)` to the output list with `ℕ`-component `k`. -/ +def add (iR : Q(Semiring $R)) : qNF R M → qNF R M → qNF R M + | [], l => l + | l, [] => l + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + ((a₁, x₁), k₁) ::ᵣ add iR t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + else if k₁ = k₂ then + ((q($a₁ + $a₂), x₁), k₁) ::ᵣ add iR t₁ t₂ + else + ((a₂, x₂), k₂) ::ᵣ add iR (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), recursively construct a proof that in the `$R`-module `$M`, the sum of the +"linear combinations" represented by `l₁` and `l₂` is the linear combination represented by +`Module.qNF.add iR l₁ l₁`.-/ +def mkAddProof {iR : Q(Semiring $R)} {iM : Q(AddCommMonoid $M)} (iRM : Q(Module $R $M)) + (l₁ l₂ : qNF R M) : + Q(NF.eval $(l₁.toNF) + NF.eval $(l₂.toNF) = NF.eval $((qNF.add iR l₁ l₂).toNF)) := + match l₁, l₂ with + | [], l => (q(zero_add (NF.eval $(l.toNF))):) + | l, [] => (q(add_zero (NF.eval $(l.toNF))):) + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + let pf := mkAddProof iRM t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + (q(NF.add_eq_eval₁ ($a₁, $x₁) $pf):) + else if k₁ = k₂ then + let pf := mkAddProof iRM t₁ t₂ + (q(NF.add_eq_eval₂ $a₁ $a₂ $x₁ $pf):) + else + let pf := mkAddProof iRM (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + (q(NF.add_eq_eval₃ ($a₂, $x₂) $pf):) + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct another such term `l`, which will have the property that in the +`$R`-module `$M`, the difference of the "linear combinations" represented by `l₁` and `l₂` is the +linear combination represented by `l`. + +The construction assumes, to be valid, that the lists `l₁` and `l₂` are in strictly increasing order +by `ℕ`-component, and that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with +the same `ℕ`-component `k`, then the expressions `x₁` and `x₂` are equal. + +The construction is as follows: merge the first list and the negation of the second list, except +that if pairs `(a₁, x₁)` and `(a₂, x₂)` appear in `l₁`, `l₂` respectively with the same +`ℕ`-component `k`, then contribute a term `(a₁ - a₂, x₁)` to the output list with `ℕ`-component `k`. +-/ +def sub (iR : Q(Ring $R)) : qNF R M → qNF R M → qNF R M + | [], l => l.onScalar q(Neg.neg) + | l, [] => l + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + ((a₁, x₁), k₁) ::ᵣ sub iR t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + else if k₁ = k₂ then + ((q($a₁ - $a₂), x₁), k₁) ::ᵣ sub iR t₁ t₂ + else + ((q(-$a₂), x₂), k₂) ::ᵣ sub iR (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + +/-- Given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), recursively construct a proof that in the `$R`-module `$M`, the difference +of the "linear combinations" represented by `l₁` and `l₂` is the linear combination represented by +`Module.qNF.sub iR l₁ l₁`.-/ +def mkSubProof (iR : Q(Ring $R)) (iM : Q(AddCommGroup $M)) (iRM : Q(Module $R $M)) + (l₁ l₂ : qNF R M) : + Q(NF.eval $(l₁.toNF) - NF.eval $(l₂.toNF) = NF.eval $((qNF.sub iR l₁ l₂).toNF)) := + match l₁, l₂ with + | [], l => (q(NF.zero_sub_eq_eval $(l.toNF)):) + | l, [] => (q(sub_zero (NF.eval $(l.toNF))):) + | ((a₁, x₁), k₁) ::ᵣ t₁, ((a₂, x₂), k₂) ::ᵣ t₂ => + if k₁ < k₂ then + let pf := mkSubProof iR iM iRM t₁ (((a₂, x₂), k₂) ::ᵣ t₂) + (q(NF.sub_eq_eval₁ ($a₁, $x₁) $pf):) + else if k₁ = k₂ then + let pf := mkSubProof iR iM iRM t₁ t₂ + (q(NF.sub_eq_eval₂ $a₁ $a₂ $x₁ $pf):) + else + let pf := mkSubProof iR iM iRM (((a₁, x₁), k₁) ::ᵣ t₁) t₂ + (q(NF.sub_eq_eval₃ ($a₂, $x₂) $pf):) + +variable {iM : Q(AddCommMonoid $M)} + {u₁ : Level} {R₁ : Q(Type u₁)} {iR₁ : Q(Semiring $R₁)} (iRM₁ : Q(@Module $R₁ $M $iR₁ $iM)) + {u₂ : Level} {R₂ : Q(Type u₂)} (iR₂ : Q(Semiring $R₂)) (iRM₂ : Q(@Module $R₂ $M $iR₂ $iM)) + +/-- Given an expression `M` representing a type which is an `AddCommMonoid` and a module over *two* +semirings `R₁` and `R₂`, find the "bigger" of the two semirings. That is, we assume that it will +turn out to be the case that either (1) `R₁` is an `R₂`-algebra and the `R₂` scalar action on `M` is +induced from `R₁`'s scalar action on `M`, or (2) vice versa; we return the semiring `R₁` in the +first case and `R₂` in the second case. + +Moreover, given expressions representing particular scalar multiplications of `R₁` and/or `R₂` on +`M` (a `List (R₁ × M)`, a `List (R₂ × M)`, a pair `(r, x) : R₂ × M`), bump these up to the "big" +ring by applying the algebra-map where needed. -/ +def matchRings (l₁ : qNF R₁ M) (l₂ : qNF R₂ M) (r : Q($R₂)) (x : Q($M)) : + MetaM <| Σ u : Level, Σ R : Q(Type u), Σ iR : Q(Semiring $R), Σ _ : Q(@Module $R $M $iR $iM), + (Σ l₁' : qNF R M, Q(NF.eval $(l₁'.toNF) = NF.eval $(l₁.toNF))) + × (Σ l₂' : qNF R M, Q(NF.eval $(l₂'.toNF) = NF.eval $(l₂.toNF))) + × (Σ r' : Q($R), Q($r' • $x = $r • $x)) := do + if ← withReducible <| isDefEq R₁ R₂ then + -- the case when `R₁ = R₂` is handled separately, so as not to require commutativity of that ring + pure ⟨u₁, R₁, iR₁, iRM₁, ⟨l₁, q(rfl)⟩, ⟨l₂, (q(@rfl _ (NF.eval $(l₂.toNF))):)⟩, + r, (q(@rfl _ ($r • $x)):)⟩ + -- otherwise the "smaller" of the two rings must be commutative + else try + -- first try to exhibit `R₂` as an `R₁`-algebra + let _i₁ ← synthInstanceQ q(CommSemiring $R₁) + let _i₃ ← synthInstanceQ q(Algebra $R₁ $R₂) + let _i₄ ← synthInstanceQ q(IsScalarTower $R₁ $R₂ $M) + assumeInstancesCommute + let l₁' : qNF R₂ M := l₁.onScalar q(algebraMap $R₁ $R₂) + pure ⟨u₂, R₂, iR₂, iRM₂, ⟨l₁', (q(NF.eval_algebraMap $R₂ $(l₁.toNF)):)⟩, ⟨l₂, q(rfl)⟩, + r, q(rfl)⟩ + catch _ => try + -- then if that fails, try to exhibit `R₁` as an `R₂`-algebra + let _i₁ ← synthInstanceQ q(CommSemiring $R₂) + let _i₃ ← synthInstanceQ q(Algebra $R₂ $R₁) + let _i₄ ← synthInstanceQ q(IsScalarTower $R₂ $R₁ $M) + assumeInstancesCommute + let l₂' : qNF R₁ M := l₂.onScalar q(algebraMap $R₂ $R₁) + let r' : Q($R₁) := q(algebraMap $R₂ $R₁ $r) + pure ⟨u₁, R₁, iR₁, iRM₁, ⟨l₁, q(rfl)⟩, ⟨l₂', (q(NF.eval_algebraMap $R₁ $(l₂.toNF)):)⟩, + r', (q(IsScalarTower.algebraMap_smul $R₁ $r $x):)⟩ + catch _ => + throwError "match_scalars failed: {R₁} is not an {R₂}-algebra and {R₂} is not an {R₁}-algebra" + +end qNF + +/-! ### Core of the `module` tactic -/ + +variable {M : Q(Type v)} + +/-- The main algorithm behind the `match_scalars` and `module` tactics: partially-normalizing an +expression in an additive commutative monoid `M` into the form c1 • x1 + c2 • x2 + ... c_k • x_k, +where x1, x2, ... are distinct atoms in `M`, and c1, c2, ... are scalars. The scalar type of the +expression is not pre-determined: instead it starts as `ℕ` (when each atom is initially given a +scalar `(1:ℕ)`) and gets bumped up into bigger semirings when such semirings are encountered. + +It is assumed that there is a "linear order" on all the semirings which appear in the expression: +for any two semirings `R` and `S` which occur, we have either `Algebra R S` or `Algebra S R`). + +TODO: implement a variant in which a semiring `R` is provided by the user, and the assumption is +instead that for any semiring `S` which occurs, we have `Algebra S R`. The PR #16984 provides a +proof-of-concept implementation of this variant, but it would need some polishing before joining +Mathlib. + +Possible TODO, if poor performance on large problems is witnessed: switch the implementation from +`AtomM` to `CanonM`, per the discussion +https://github.com/leanprover-community/mathlib4/pull/16593/files#r1749623191 -/ +partial def parse (iM : Q(AddCommMonoid $M)) (x : Q($M)) : + AtomM (Σ u : Level, Σ R : Q(Type u), Σ iR : Q(Semiring $R), Σ _ : Q(@Module $R $M $iR $iM), + Σ l : qNF R M, Q($x = NF.eval $(l.toNF))) := do + match x with + /- parse an addition: `x₁ + x₂` -/ + | ~q($x₁ + $x₂) => + let ⟨_, _, _, iRM₁, l₁', pf₁'⟩ ← parse iM x₁ + let ⟨_, _, _, iRM₂, l₂', pf₂'⟩ ← parse iM x₂ + -- lift from the semirings of scalars parsed from `x₁`, `x₂` (say `R₁`, `R₂`) to `R₁ ⊗ R₂` + let ⟨u, R, iR, iRM, ⟨l₁, pf₁⟩, ⟨l₂, pf₂⟩, _⟩ ← qNF.matchRings iRM₁ _ iRM₂ l₁' l₂' q(0) q(0) + -- build the new list and proof + let pf := qNF.mkAddProof iRM l₁ l₂ + pure ⟨u, R, iR, iRM, qNF.add iR l₁ l₂, (q(NF.add_eq_eval $pf₁' $pf₂' $pf₁ $pf₂ $pf):)⟩ + /- parse a subtraction: `x₁ - x₂` -/ + | ~q(@HSub.hSub _ _ _ (@instHSub _ $iM') $x₁ $x₂) => + let ⟨_, _, _, iRM₁, l₁'', pf₁''⟩ ← parse iM x₁ + let ⟨_, _, _, iRM₂, l₂'', pf₂''⟩ ← parse iM x₂ + -- lift from the semirings of scalars parsed from `x₁`, `x₂` (say `R₁`, `R₂`) to `R₁ ⊗ R₂ ⊗ ℤ` + let iZ := q(Int.instSemiring) + let iMZ ← synthInstanceQ q(Module ℤ $M) + let ⟨_, _, _, iRM₁', ⟨l₁', pf₁'⟩, _, _⟩ ← qNF.matchRings iRM₁ iZ iMZ l₁'' [] q(0) q(0) + let ⟨_, _, _, iRM₂', ⟨l₂', pf₂'⟩, _, _⟩ ← qNF.matchRings iRM₂ iZ iMZ l₂'' [] q(0) q(0) + let ⟨u, R, iR, iRM, ⟨l₁, pf₁⟩, ⟨l₂, pf₂⟩, _⟩ ← qNF.matchRings iRM₁' _ iRM₂' l₁' l₂' q(0) q(0) + let iR' ← synthInstanceQ q(Ring $R) + let iM' ← synthInstanceQ q(AddCommGroup $M) + assumeInstancesCommute + -- build the new list and proof + let pf := qNF.mkSubProof iR' iM' iRM l₁ l₂ + pure ⟨u, R, iR, iRM, qNF.sub iR' l₁ l₂, + q(NF.sub_eq_eval $pf₁'' $pf₂'' $pf₁' $pf₂' $pf₁ $pf₂ $pf)⟩ + /- parse a negation: `-y` -/ + | ~q(@Neg.neg _ $iM' $y) => + let ⟨u₀, _, _, iRM₀, l₀, pf₀⟩ ← parse iM y + -- lift from original semiring of scalars (say `R₀`) to `R₀ ⊗ ℤ` + let _i ← synthInstanceQ q(AddCommGroup $M) + let iZ := q(Int.instSemiring) + let iMZ ← synthInstanceQ q(Module ℤ $M) + let ⟨u, R, iR, iRM, ⟨l, pf⟩, _, _⟩ ← qNF.matchRings iRM₀ iZ iMZ l₀ [] q(0) q(0) + let _i' ← synthInstanceQ q(Ring $R) + assumeInstancesCommute + -- build the new list and proof + pure ⟨u, R, iR, iRM, l.onScalar q(Neg.neg), (q(NF.neg_eq_eval $pf $pf₀):)⟩ + /- parse a scalar multiplication: `(s₀ : S) • y` -/ + | ~q(@HSMul.hSMul _ _ _ (@instHSMul $S _ $iS) $s₀ $y) => + let ⟨_, _, _, iRM₀, l₀, pf₀⟩ ← parse iM y + let i₁ ← synthInstanceQ q(Semiring $S) + let i₂ ← synthInstanceQ q(Module $S $M) + assumeInstancesCommute + -- lift from original semiring of scalars (say `R₀`) to `R₀ ⊗ S` + let ⟨u, R, iR, iRM, ⟨l, pf_l⟩, _, ⟨s, pf_r⟩⟩ ← qNF.matchRings iRM₀ i₁ i₂ l₀ [] s₀ y + -- build the new list and proof + pure ⟨u, R, iR, iRM, l.onScalar q(HMul.hMul $s), (q(NF.smul_eq_eval $pf₀ $pf_l $pf_r):)⟩ + /- parse a `(0:M)` -/ + | ~q(0) => + pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [], q(NF.zero_eq_eval $M)⟩ + /- anything else should be treated as an atom -/ + | _ => + let k : ℕ ← AtomM.addAtom x + pure ⟨0, q(Nat), q(Nat.instSemiring), q(AddCommGroup.toNatModule), [((q(1), x), k)], + q(NF.atom_eq_eval $x)⟩ + +/-- Given expressions `R` and `M` representing types such that `M`'s is a module over `R`'s, and +given two terms `l₁`, `l₂` of type `qNF R M`, i.e. lists of `(Q($R) × Q($M)) × ℕ`s (two `Expr`s +and a natural number), construct a list of new goals: that the `R`-coefficient of an `M`-atom which +appears in only one list is zero, and that the `R`-coefficients of an `M`-atom which appears in both +lists are equal. Also construct (dependent on these new goals) a proof that the "linear +combinations" represented by `l₁` and `l₂` are equal in `M`. -/ +partial def reduceCoefficientwise {R : Q(Type u)} {_ : Q(AddCommMonoid $M)} {_ : Q(Semiring $R)} + (iRM : Q(Module $R $M)) (l₁ l₂ : qNF R M) : + MetaM (List MVarId × Q(NF.eval $(l₁.toNF) = NF.eval $(l₂.toNF))) := do + match l₁, l₂ with + /- if both empty, return a `rfl` proof that `(0:M) = 0` -/ + | [], [] => + let pf : Q(NF.eval $(l₁.toNF) = NF.eval $(l₁.toNF)) := q(rfl) + pure ([], pf) + /- if one of the lists is empty and the other one is not, recurse down the nonempty one, + forming goals that each of the listed coefficients is equal to + zero -/ + | [], ((a, x), _) ::ᵣ L => + let mvar : Q((0:$R) = $a) ← mkFreshExprMVar q((0:$R) = $a) + let (mvars, pf) ← reduceCoefficientwise iRM [] L + pure (mvar.mvarId! :: mvars, (q(NF.eq_const_cons $x $mvar $pf):)) + | ((a, x), _) ::ᵣ L, [] => + let mvar : Q($a = (0:$R)) ← mkFreshExprMVar q($a = (0:$R)) + let (mvars, pf) ← reduceCoefficientwise iRM L [] + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_const $x $mvar $pf):)) + /- if both lists are nonempty, then deal with the numerically-smallest term in either list, + forming a goal that it is equal to zero (if it appears in only one list) or that its + coefficients in the two lists are the same (if it appears in both lists); then recurse -/ + | ((a₁, x₁), k₁) ::ᵣ L₁, ((a₂, x₂), k₂) ::ᵣ L₂ => + if k₁ < k₂ then + let mvar : Q($a₁ = (0:$R)) ← mkFreshExprMVar q($a₁ = (0:$R)) + let (mvars, pf) ← reduceCoefficientwise iRM L₁ l₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_const $x₁ $mvar $pf):)) + else if k₁ = k₂ then + let mvar : Q($a₁ = $a₂) ← mkFreshExprMVar q($a₁ = $a₂) + let (mvars, pf) ← reduceCoefficientwise iRM L₁ L₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_cons_cons $x₁ $mvar $pf):)) + else + let mvar : Q((0:$R) = $a₂) ← mkFreshExprMVar q((0:$R) = $a₂) + let (mvars, pf) ← reduceCoefficientwise iRM l₁ L₂ + pure (mvar.mvarId! :: mvars, (q(NF.eq_const_cons $x₂ $mvar $pf):)) + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. + +This is an auxiliary function which produces slightly awkward goals in `R`; they are later cleaned +up by the function `Mathlib.Tactic.Module.postprocess`. -/ +def matchScalarsAux (g : MVarId) : AtomM (List MVarId) := do + /- Parse the goal as an equality in a type `M` of two expressions `lhs` and `rhs`, with `M` + carrying an `AddCommMonoid` instance. -/ + let eqData ← do + match (← g.getType').eq? with + | some e => pure e + | none => throwError "goal {← g.getType} is not an equality" + let .sort v₀ ← whnf (← inferType eqData.1) | unreachable! + let some v := v₀.dec | unreachable! + let ((M : Q(Type v)), (lhs : Q($M)), (rhs :Q($M))) := eqData + let iM ← synthInstanceQ q(AddCommMonoid.{v} $M) + /- Construct from the `lhs` expression a term `l₁` of type `qNF R₁ M` for some semiring `R₁` -- + that is, a list of `(Q($R₁) × Q($M)) × ℕ`s (two `Expr`s and a natural number) -- together with a + proof that `lhs` is equal to the `R₁`-linear combination in `M` this represents. -/ + let e₁ ← parse iM lhs + have u₁ : Level := e₁.fst + have R₁ : Q(Type u₁) := e₁.snd.fst + have _iR₁ : Q(Semiring.{u₁} $R₁) := e₁.snd.snd.fst + let iRM₁ ← synthInstanceQ q(Module $R₁ $M) + assumeInstancesCommute + have l₁ : qNF R₁ M := e₁.snd.snd.snd.snd.fst + let pf₁ : Q($lhs = NF.eval $(l₁.toNF)) := e₁.snd.snd.snd.snd.snd + /- Do the same for the `rhs` expression, obtaining a term `l₂` of type `qNF R₂ M` for some + semiring `R₂`. -/ + let e₂ ← parse iM rhs + have u₂ : Level := e₂.fst + have R₂ : Q(Type u₂) := e₂.snd.fst + have _iR₂ : Q(Semiring.{u₂} $R₂) := e₂.snd.snd.fst + let iRM₂ ← synthInstanceQ q(Module $R₂ $M) + have l₂ : qNF R₂ M := e₂.snd.snd.snd.snd.fst + let pf₂ : Q($rhs = NF.eval $(l₂.toNF)) := e₂.snd.snd.snd.snd.snd + /- Lift everything to the same scalar ring, `R`. -/ + let ⟨_, _, _, iRM, ⟨l₁', pf₁'⟩, ⟨l₂', pf₂'⟩, _⟩ ← qNF.matchRings iRM₁ _ iRM₂ l₁ l₂ q(0) q(0) + /- Construct a list of goals for the coefficientwise equality of these formal linear combinations, + and resolve our original goal (modulo these new goals). -/ + let (mvars, pf) ← reduceCoefficientwise iRM l₁' l₂' + g.assign q(NF.eq_of_eval_eq_eval $pf₁ $pf₂ $pf₁' $pf₂' $pf) + return mvars + +/-- Lemmas used to post-process the result of the `match_scalars` and `module` tactics by converting +the `algebraMap` operations which (which proliferate in the constructed scalar goals) to more +familiar forms: `ℕ`, `ℤ` and `ℚ` casts. -/ +def algebraMapThms : Array Name := #[``eq_natCast, ``eq_intCast, ``eq_ratCast] + +/-- Postprocessing for the scalar goals constructed in the `match_scalars` and `module` tactics. +These goals feature a proliferation of `algebraMap` operations (because the scalars start in `ℕ` and +get successively bumped up by `algebraMap`s as new semirings are encountered), so we reinterpret the +most commonly occurring `algebraMap`s (those out of `ℕ`, `ℤ` and `ℚ`) into their standard forms +(`ℕ`, `ℤ` and `ℚ` casts) and then try to disperse the casts using the various `push_cast` lemmas. -/ +def postprocess (mvarId : MVarId) : MetaM MVarId := do + -- collect the available `push_cast` lemmas + let mut thms : SimpTheorems := ← NormCast.pushCastExt.getTheorems + -- augment this list with the `algebraMapThms` lemmas, which handle `algebraMap` operations + for thm in algebraMapThms do + let ⟨levelParams, _, proof⟩ ← abstractMVars (mkConst thm) + thms ← thms.add (.stx (← mkFreshId) Syntax.missing) levelParams proof + -- now run `simp` with these lemmas, and (importantly) *no* simprocs + let ctx : Simp.Context := { + config := { failIfUnchanged := false } + simpTheorems := #[thms] + } + let (some r, _) ← simpTarget mvarId ctx (simprocs := #[]) | + throwError "internal error in match_scalars tactic: postprocessing should not close goals" + return r + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. -/ +def matchScalars (g : MVarId) : MetaM (List MVarId) := do + let mvars ← AtomM.run .instances (matchScalarsAux g) + mvars.mapM postprocess + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some semiring `R`, and reduce the goal to +the respective equalities of the `R`-coefficients of each atom. + +For example, this produces the goal `⊢ a * 1 + b * 1 = (b + a) * 1`: +``` +example [AddCommMonoid M] [Semiring R] [Module R M] (a b : R) (x : M) : + a • x + b • x = (b + a) • x := by + match_scalars +``` +This produces the two goals `⊢ a * (a * 1) + b * (b * 1) = 1` (from the `x` atom) and +`⊢ a * -(b * 1) + b * (a * 1) = 0` (from the `y` atom): +``` +example [AddCommGroup M] [Ring R] [Module R M] (a b : R) (x : M) : + a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + match_scalars +``` +This produces the goal `⊢ -2 * (a * 1) = a * (-2 * 1)`: +``` +example [AddCommGroup M] [Ring R] [Module R M] (a : R) (x : M) : + -(2:R) • a • x = a • (-2:ℤ) • x := by + match_scalars +``` +The scalar type for the goals produced by the `match_scalars` tactic is the largest scalar type +encountered; for example, if `ℕ`, `ℚ` and a characteristic-zero field `K` all occur as scalars, then +the goals produced are equalities in `K`. A variant of `push_cast` is used internally in +`match_scalars` to interpret scalars from the other types in this largest type. + +If the set of scalar types encountered is not totally ordered (in the sense that for all rings `R`, +`S` encountered, it holds that either `Algebra R S` or `Algebra S R`), then the `match_scalars` +tactic fails. +-/ +elab "match_scalars" : tactic => Tactic.liftMetaTactic matchScalars + +/-- Given a goal which is an equality in a type `M` (with `M` an `AddCommMonoid`), parse the LHS and +RHS of the goal as linear combinations of `M`-atoms over some commutative semiring `R`, and prove +the goal by checking that the LHS- and RHS-coefficients of each atom are the same up to +ring-normalization in `R`. + +(If the proofs of coefficient-wise equality will require more reasoning than just +ring-normalization, use the tactic `match_scalars` instead, and then prove coefficient-wise equality +by hand.) + +Example uses of the `module` tactic: +``` +example [AddCommMonoid M] [CommSemiring R] [Module R M] (a b : R) (x : M) : + a • x + b • x = (b + a) • x := by + module + +example [AddCommMonoid M] [Field K] [CharZero K] [Module K M] (x : M) : + (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by + module + +example [AddCommGroup M] [CommRing R] [Module R M] (a : R) (v w : M) : + (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by + module + +example [AddCommGroup M] [CommRing R] [Module R M] (a b μ ν : R) (x y : M) : + (μ - ν) • a • x = (a • μ • x + b • ν • y) - ν • (a • x + b • y) := by + module +``` +-/ +elab "module" : tactic => Tactic.liftMetaFinishingTactic fun g ↦ do + let l ← matchScalars g + discard <| l.mapM fun mvar ↦ AtomM.run .instances (Ring.proveEq mvar) + +end Mathlib.Tactic.Module diff --git a/Mathlib/Tactic/NormNum/DivMod.lean b/Mathlib/Tactic/NormNum/DivMod.lean index 3037be0ca7da7..821532050c549 100644 --- a/Mathlib/Tactic/NormNum/DivMod.lean +++ b/Mathlib/Tactic/NormNum/DivMod.lean @@ -147,8 +147,8 @@ theorem isInt_dvd_true : {a b : ℤ} → {a' b' c : ℤ} → | _, _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, rfl => ⟨_, rfl⟩ theorem isInt_dvd_false : {a b : ℤ} → {a' b' : ℤ} → - IsInt a a' → IsInt b b' → Int.mod b' a' != 0 → ¬a ∣ b - | _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, e => mt Int.mod_eq_zero_of_dvd (by simpa using e) + IsInt a a' → IsInt b b' → Int.emod b' a' != 0 → ¬a ∣ b + | _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, e => mt Int.emod_eq_zero_of_dvd (by simpa using e) /-- The `norm_num` extension which identifies expressions of the form `(a : ℤ) ∣ b`, such that `norm_num` successfully recognises both `a` and `b`. -/ @@ -167,7 +167,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ haveI' : Int.mul $na $c =Q $nb := ⟨⟩ return .isTrue q(isInt_dvd_true $pa $pb (.refl $nb)) else - have : Q(Int.mod $nb $na != 0) := (q(Eq.refl true) : Expr) + have : Q(Int.emod $nb $na != 0) := (q(Eq.refl true) : Expr) return .isFalse q(isInt_dvd_false $pa $pb $this) end Mathlib.Meta.NormNum diff --git a/Mathlib/Tactic/NormNum/Ineq.lean b/Mathlib/Tactic/NormNum/Ineq.lean index 987fbd80ced59..9c5a20797bcc2 100644 --- a/Mathlib/Tactic/NormNum/Ineq.lean +++ b/Mathlib/Tactic/NormNum/Ineq.lean @@ -108,12 +108,21 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ let ⟨u, α, a⟩ ← inferTypeQ' a have b : Q($α) := b let ra ← derive a; let rb ← derive b + let lα ← synthInstanceQ q(LE $α) + guard <|← withNewMCtxDepth <| isDefEq f q(LE.le (α := $α)) + core lα ra rb +where + /-- Identify (as `true` or `false`) expressions of the form `a ≤ b`, where `a` and `b` are numeric + expressions whose evaluations to `NormNum.Result` have already been computed. -/ + core {u : Level} {α : Q(Type u)} (lα : Q(LE $α)) {a b : Q($α)} + (ra : NormNum.Result a) (rb : NormNum.Result b) : MetaM (NormNum.Result q($a ≤ $b)) := do + let e := q($a ≤ $b) let rec intArm : MetaM (Result e) := do let _i ← inferOrderedRing α - guard <|← withNewMCtxDepth <| isDefEq f q(LE.le (α := $α)) haveI' : $e =Q ($a ≤ $b) := ⟨⟩ let ⟨za, na, pa⟩ ← ra.toInt q(OrderedRing.toRing) let ⟨zb, nb, pb⟩ ← rb.toInt q(OrderedRing.toRing) + assumeInstancesCommute if decide (za ≤ zb) then let r : Q(decide ($na ≤ $nb) = true) := (q(Eq.refl true) : Expr) return .isTrue q(isInt_le_true $pa $pb $r) @@ -125,10 +134,10 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ let rec ratArm : MetaM (Result e) := do -- We need a division ring with an order, and `LinearOrderedField` is the closest mathlib has. let _i ← inferLinearOrderedField α - guard <|← withNewMCtxDepth <| isDefEq f q(LE.le (α := $α)) haveI' : $e =Q ($a ≤ $b) := ⟨⟩ let ⟨qa, na, da, pa⟩ ← ra.toRat' q(Field.toDivisionRing) let ⟨qb, nb, db, pb⟩ ← rb.toRat' q(Field.toDivisionRing) + assumeInstancesCommute if decide (qa ≤ qb) then let r : Q(decide ($na * $db ≤ $nb * $da) = true) := (q(Eq.refl true) : Expr) return (.isTrue q(isRat_le_true $pa $pb $r)) @@ -144,8 +153,8 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ let _i ← inferOrderedSemiring α haveI' : $ra =Q by clear! $ra $rb; infer_instance := ⟨⟩ haveI' : $rb =Q by clear! $ra $rb; infer_instance := ⟨⟩ - guard <|← withNewMCtxDepth <| isDefEq f q(LE.le (α := $α)) haveI' : $e =Q ($a ≤ $b) := ⟨⟩ + assumeInstancesCommute if na.natLit! ≤ nb.natLit! then let r : Q(Nat.ble $na $nb = true) := (q(Eq.refl true) : Expr) return .isTrue q(isNat_le_true $pa $pb $r) @@ -163,13 +172,21 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ let ⟨u, α, a⟩ ← inferTypeQ' a have b : Q($α) := b let ra ← derive a; let rb ← derive b + let lα ← synthInstanceQ q(LT $α) + guard <|← withNewMCtxDepth <| isDefEq f q(LT.lt (α := $α)) + core lα ra rb +where + /-- Identify (as `true` or `false`) expressions of the form `a < b`, where `a` and `b` are numeric + expressions whose evaluations to `NormNum.Result` have already been computed. -/ + core {u : Level} {α : Q(Type u)} (lα : Q(LT $α)) {a b : Q($α)} + (ra : NormNum.Result a) (rb : NormNum.Result b) : MetaM (NormNum.Result q($a < $b)) := do + let e := q($a < $b) let rec intArm : MetaM (Result e) := do let _i ← inferOrderedRing α - assumeInstancesCommute - guard <|← withNewMCtxDepth <| isDefEq f q(LT.lt (α := $α)) haveI' : $e =Q ($a < $b) := ⟨⟩ let ⟨za, na, pa⟩ ← ra.toInt q(OrderedRing.toRing) let ⟨zb, nb, pb⟩ ← rb.toInt q(OrderedRing.toRing) + assumeInstancesCommute if za < zb then if let .some _i ← trySynthInstanceQ (q(@Nontrivial $α) : Q(Prop)) then let r : Q(decide ($na < $nb) = true) := (q(Eq.refl true) : Expr) @@ -184,7 +201,6 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ let _i ← inferLinearOrderedField α assumeInstancesCommute haveI' : $e =Q ($a < $b) := ⟨⟩ - guard <|← withNewMCtxDepth <| isDefEq f q(LT.lt (α := $α)) let ⟨qa, na, da, pa⟩ ← ra.toRat' q(Field.toDivisionRing) let ⟨qb, nb, db, pb⟩ ← rb.toRat' q(Field.toDivisionRing) if qa < qb then @@ -202,7 +218,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/ haveI' : $ra =Q by clear! $ra $rb; infer_instance := ⟨⟩ haveI' : $rb =Q by clear! $ra $rb; infer_instance := ⟨⟩ haveI' : $e =Q ($a < $b) := ⟨⟩ - guard <|← withNewMCtxDepth <| isDefEq f q(LT.lt (α := $α)) + assumeInstancesCommute if na.natLit! < nb.natLit! then if let .some _i ← trySynthInstanceQ q(CharZero $α) then let r : Q(Nat.ble $nb $na = false) := (q(Eq.refl false) : Expr) diff --git a/Mathlib/Tactic/Polyrith.lean b/Mathlib/Tactic/Polyrith.lean index f20d12e722d99..1b3ef56ab08c8 100644 --- a/Mathlib/Tactic/Polyrith.lean +++ b/Mathlib/Tactic/Polyrith.lean @@ -392,7 +392,6 @@ Notes: Many thanks to the Sage team and organization for allowing this use. * This tactic assumes that the user has `python3` installed and available on the path. (Test by opening a terminal and executing `python3 --version`.) - It also assumes that the `requests` library is installed: `python3 -m pip install requests`. Examples: diff --git a/Mathlib/Tactic/Positivity/Core.lean b/Mathlib/Tactic/Positivity/Core.lean index a03631e11fca8..5ea9541b1909c 100644 --- a/Mathlib/Tactic/Positivity/Core.lean +++ b/Mathlib/Tactic/Positivity/Core.lean @@ -122,7 +122,7 @@ variable {A : Type*} {e : A} lemma lt_of_le_of_ne' {a b : A} [PartialOrder A] : (a : A) ≤ b → b ≠ a → a < b := fun h₁ h₂ => lt_of_le_of_ne h₁ h₂.symm -lemma pos_of_isNat {n : ℕ} [StrictOrderedSemiring A] +lemma pos_of_isNat {n : ℕ} [OrderedSemiring A] [Nontrivial A] (h : NormNum.IsNat e n) (w : Nat.ble 1 n = true) : 0 < (e : A) := by rw [NormNum.IsNat.to_eq h rfl] apply Nat.cast_pos.2 @@ -184,11 +184,12 @@ def normNumPositivity (e : Q($α)) : MetaM (Strictness zα pα e) := catchNone d | .isBool .. => failure | .isNat _ lit p => if 0 < lit.natLit! then - let _a ← synthInstanceQ q(StrictOrderedSemiring $α) + let _a ← synthInstanceQ q(OrderedSemiring $α) + let _a ← synthInstanceQ q(Nontrivial $α) assumeInstancesCommute have p : Q(NormNum.IsNat $e $lit) := p haveI' p' : Nat.ble 1 $lit =Q true := ⟨⟩ - pure (.positive q(@pos_of_isNat $α _ _ _ $p $p')) + pure (.positive q(@pos_of_isNat $α _ _ _ _ $p $p')) else let _a ← synthInstanceQ q(OrderedSemiring $α) assumeInstancesCommute diff --git a/Mathlib/Tactic/Ring/Basic.lean b/Mathlib/Tactic/Ring/Basic.lean index 459dfa19e288a..c5ac7fd426cd8 100644 --- a/Mathlib/Tactic/Ring/Basic.lean +++ b/Mathlib/Tactic/Ring/Basic.lean @@ -307,6 +307,11 @@ theorem add_overlap_pf_zero (x : R) (e) : IsNat (a + b) (nat_lit 0) → IsNat (x ^ e * a + x ^ e * b) (nat_lit 0) | ⟨h⟩ => ⟨by simp [h, ← mul_add]⟩ +-- TODO: decide if this is a good idea globally in +-- https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/.60MonadLift.20Option.20.28OptionT.20m.29.60/near/469097834 +private local instance {m} [Pure m] : MonadLift Option (OptionT m) where + monadLift f := .mk <| pure f + /-- Given monomials `va, vb`, attempts to add them together to get another monomial. If the monomials are not compatible, returns `none`. @@ -314,7 +319,8 @@ For example, `xy + 2xy = 3xy` is a `.nonzero` overlap, while `xy + xz` returns ` and `xy + -xy = 0` is a `.zero` overlap. -/ def evalAddOverlap {a b : Q($α)} (va : ExProd sα a) (vb : ExProd sα b) : - Option (Overlap sα q($a + $b)) := + OptionT Lean.Core.CoreM (Overlap sα q($a + $b)) := do + Lean.Core.checkSystem decl_name%.toString match va, vb with | .const za ha, .const zb hb => do let ra := Result.ofRawRat za a ha; let rb := Result.ofRawRat zb b hb @@ -331,7 +337,7 @@ def evalAddOverlap {a b : Q($α)} (va : ExProd sα a) (vb : ExProd sα b) : | .zero p => pure <| .zero (q(add_overlap_pf_zero $a₁ $a₂ $p) : Expr) | .nonzero ⟨_, vc, p⟩ => pure <| .nonzero ⟨_, .mul va₁ va₂ vc, (q(add_overlap_pf $a₁ $a₂ $p) : Expr)⟩ - | _, _ => none + | _, _ => OptionT.fail theorem add_pf_zero_add (b : R) : 0 + b = b := by simp @@ -359,25 +365,26 @@ theorem add_pf_add_gt (b₁ : R) (_ : a + b₂ = c) : a + (b₁ + b₂) = b₁ + * `(a₁ + a₂) + (b₁ + b₂) = b₁ + ((a₁ + a₂) + b₂)` (if not `a₁.lt b₁`) -/ partial def evalAdd {a b : Q($α)} (va : ExSum sα a) (vb : ExSum sα b) : - Result (ExSum sα) q($a + $b) := + Lean.Core.CoreM <| Result (ExSum sα) q($a + $b) := do + Lean.Core.checkSystem decl_name%.toString match va, vb with - | .zero, vb => ⟨b, vb, q(add_pf_zero_add $b)⟩ - | va, .zero => ⟨a, va, q(add_pf_add_zero $a)⟩ + | .zero, vb => return ⟨b, vb, q(add_pf_zero_add $b)⟩ + | va, .zero => return ⟨a, va, q(add_pf_add_zero $a)⟩ | .add (a := a₁) (b := _a₂) va₁ va₂, .add (a := b₁) (b := _b₂) vb₁ vb₂ => - match evalAddOverlap sα va₁ vb₁ with + match ← (evalAddOverlap sα va₁ vb₁).run with | some (.nonzero ⟨_, vc₁, pc₁⟩) => - let ⟨_, vc₂, pc₂⟩ := evalAdd va₂ vb₂ - ⟨_, .add vc₁ vc₂, q(add_pf_add_overlap $pc₁ $pc₂)⟩ + let ⟨_, vc₂, pc₂⟩ ← evalAdd va₂ vb₂ + return ⟨_, .add vc₁ vc₂, q(add_pf_add_overlap $pc₁ $pc₂)⟩ | some (.zero pc₁) => - let ⟨c₂, vc₂, pc₂⟩ := evalAdd va₂ vb₂ - ⟨c₂, vc₂, q(add_pf_add_overlap_zero $pc₁ $pc₂)⟩ + let ⟨c₂, vc₂, pc₂⟩ ← evalAdd va₂ vb₂ + return ⟨c₂, vc₂, q(add_pf_add_overlap_zero $pc₁ $pc₂)⟩ | none => if let .lt := va₁.cmp vb₁ then - let ⟨_c, vc, (pc : Q($_a₂ + ($b₁ + $_b₂) = $_c))⟩ := evalAdd va₂ vb - ⟨_, .add va₁ vc, q(add_pf_add_lt $a₁ $pc)⟩ + let ⟨_c, vc, (pc : Q($_a₂ + ($b₁ + $_b₂) = $_c))⟩ ← evalAdd va₂ vb + return ⟨_, .add va₁ vc, q(add_pf_add_lt $a₁ $pc)⟩ else - let ⟨_c, vc, (pc : Q($a₁ + $_a₂ + $_b₂ = $_c))⟩ := evalAdd va vb₂ - ⟨_, .add vb₁ vc, q(add_pf_add_gt $b₁ $pc)⟩ + let ⟨_c, vc, (pc : Q($a₁ + $_a₂ + $_b₂ = $_c))⟩ ← evalAdd va vb₂ + return ⟨_, .add vb₁ vc, q(add_pf_add_gt $b₁ $pc)⟩ theorem one_mul (a : R) : (nat_lit 1).rawCast * a = a := by simp [Nat.rawCast] @@ -406,37 +413,38 @@ theorem mul_pp_pf_overlap {ea eb e : ℕ} (x : R) (_ : ea + eb = e) (_ : a₂ * * `(a₁ * a₂) * (b₁ * b₂) = b₁ * ((a₁ * a₂) * b₂)` (if not `a₁.lt b₁`) -/ partial def evalMulProd {a b : Q($α)} (va : ExProd sα a) (vb : ExProd sα b) : - Result (ExProd sα) q($a * $b) := + Lean.Core.CoreM <| Result (ExProd sα) q($a * $b) := do + Lean.Core.checkSystem decl_name%.toString match va, vb with | .const za ha, .const zb hb => if za = 1 then - ⟨b, .const zb hb, (q(one_mul $b) : Expr)⟩ + return ⟨b, .const zb hb, (q(one_mul $b) : Expr)⟩ else if zb = 1 then - ⟨a, .const za ha, (q(mul_one $a) : Expr)⟩ + return ⟨a, .const za ha, (q(mul_one $a) : Expr)⟩ else let ra := Result.ofRawRat za a ha; let rb := Result.ofRawRat zb b hb 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 - ⟨c, .const zc hc, pc⟩ + return ⟨c, .const zc hc, pc⟩ | .mul (x := a₁) (e := a₂) va₁ va₂ va₃, .const _ _ => - let ⟨_, vc, pc⟩ := evalMulProd va₃ vb - ⟨_, .mul va₁ va₂ vc, (q(mul_pf_left $a₁ $a₂ $pc) : Expr)⟩ + let ⟨_, vc, pc⟩ ← evalMulProd va₃ vb + return ⟨_, .mul va₁ va₂ vc, (q(mul_pf_left $a₁ $a₂ $pc) : Expr)⟩ | .const _ _, .mul (x := b₁) (e := b₂) vb₁ vb₂ vb₃ => - let ⟨_, vc, pc⟩ := evalMulProd va vb₃ - ⟨_, .mul vb₁ vb₂ vc, (q(mul_pf_right $b₁ $b₂ $pc) : Expr)⟩ - | .mul (x := xa) (e := ea) vxa vea va₂, .mul (x := xb) (e := eb) vxb veb vb₂ => Id.run do + let ⟨_, vc, pc⟩ ← evalMulProd va vb₃ + return ⟨_, .mul vb₁ vb₂ vc, (q(mul_pf_right $b₁ $b₂ $pc) : Expr)⟩ + | .mul (x := xa) (e := ea) vxa vea va₂, .mul (x := xb) (e := eb) vxb veb vb₂ => do if vxa.eq vxb then - if let some (.nonzero ⟨_, ve, pe⟩) := evalAddOverlap sℕ vea veb then - let ⟨_, vc, pc⟩ := evalMulProd va₂ vb₂ + if let some (.nonzero ⟨_, ve, pe⟩) ← (evalAddOverlap sℕ vea veb).run then + let ⟨_, vc, pc⟩ ← evalMulProd va₂ vb₂ return ⟨_, .mul vxa ve vc, (q(mul_pp_pf_overlap $xa $pe $pc) : Expr)⟩ if let .lt := (vxa.cmp vxb).then (vea.cmp veb) then - let ⟨_, vc, pc⟩ := evalMulProd va₂ vb - ⟨_, .mul vxa vea vc, (q(mul_pf_left $xa $ea $pc) : Expr)⟩ + let ⟨_, vc, pc⟩ ← evalMulProd va₂ vb + return ⟨_, .mul vxa vea vc, (q(mul_pf_left $xa $ea $pc) : Expr)⟩ else - let ⟨_, vc, pc⟩ := evalMulProd va vb₂ - ⟨_, .mul vxb veb vc, (q(mul_pf_right $xb $eb $pc) : Expr)⟩ + let ⟨_, vc, pc⟩ ← evalMulProd va vb₂ + return ⟨_, .mul vxb veb vc, (q(mul_pf_right $xb $eb $pc) : Expr)⟩ theorem mul_zero (a : R) : a * 0 = 0 := by simp @@ -449,14 +457,15 @@ theorem mul_add {d : R} (_ : (a : R) * b₁ = c₁) (_ : a * b₂ = c₂) (_ : c * `a * 0 = 0` * `a * (b₁ + b₂) = (a * b₁) + (a * b₂)` -/ -def evalMul₁ {a b : Q($α)} (va : ExProd sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a * $b) := +def evalMul₁ {a b : Q($α)} (va : ExProd sα a) (vb : ExSum sα b) : + Lean.Core.CoreM <| Result (ExSum sα) q($a * $b) := do match vb with - | .zero => ⟨_, .zero, q(mul_zero $a)⟩ + | .zero => return ⟨_, .zero, q(mul_zero $a)⟩ | .add vb₁ vb₂ => - let ⟨_, vc₁, pc₁⟩ := evalMulProd sα va vb₁ - let ⟨_, vc₂, pc₂⟩ := evalMul₁ va vb₂ - let ⟨_, vd, pd⟩ := evalAdd sα vc₁.toSum vc₂ - ⟨_, vd, q(mul_add $pc₁ $pc₂ $pd)⟩ + let ⟨_, vc₁, pc₁⟩ ← evalMulProd sα va vb₁ + let ⟨_, vc₂, pc₂⟩ ← evalMul₁ va vb₂ + let ⟨_, vd, pd⟩ ← evalAdd sα vc₁.toSum vc₂ + return ⟨_, vd, q(mul_add $pc₁ $pc₂ $pd)⟩ theorem zero_mul (b : R) : 0 * b = 0 := by simp @@ -468,14 +477,15 @@ theorem add_mul {d : R} (_ : (a₁ : R) * b = c₁) (_ : a₂ * b = c₂) (_ : c * `0 * b = 0` * `(a₁ + a₂) * b = (a₁ * b) + (a₂ * b)` -/ -def evalMul {a b : Q($α)} (va : ExSum sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a * $b) := +def evalMul {a b : Q($α)} (va : ExSum sα a) (vb : ExSum sα b) : + Lean.Core.CoreM <| Result (ExSum sα) q($a * $b) := do match va with - | .zero => ⟨_, .zero, q(zero_mul $b)⟩ + | .zero => return ⟨_, .zero, q(zero_mul $b)⟩ | .add va₁ va₂ => - let ⟨_, vc₁, pc₁⟩ := evalMul₁ sα va₁ vb - let ⟨_, vc₂, pc₂⟩ := evalMul va₂ vb - let ⟨_, vd, pd⟩ := evalAdd sα vc₁ vc₂ - ⟨_, vd, q(add_mul $pc₁ $pc₂ $pd)⟩ + let ⟨_, vc₁, pc₁⟩ ← evalMul₁ sα va₁ vb + let ⟨_, vc₂, pc₂⟩ ← evalMul va₂ vb + let ⟨_, vd, pd⟩ ← evalAdd sα vc₁ vc₂ + return ⟨_, vd, q(add_mul $pc₁ $pc₂ $pd)⟩ theorem natCast_nat (n) : ((Nat.rawCast n : ℕ) : R) = Nat.rawCast n := by simp @@ -552,11 +562,11 @@ def evalNSMul {a : Q(ℕ)} {b : Q($α)} (va : ExSum sℕ a) (vb : ExSum sα b) : if ← isDefEq sα sℕ then let ⟨_, va'⟩ := va.cast have _b : Q(ℕ) := b - let ⟨(_c : Q(ℕ)), vc, (pc : Q($a * $_b = $_c))⟩ := evalMul sα va' vb + let ⟨(_c : Q(ℕ)), vc, (pc : Q($a * $_b = $_c))⟩ ← evalMul sα va' vb pure ⟨_, vc, (q(smul_nat $pc) : Expr)⟩ else let ⟨_, va', pa'⟩ ← va.evalNatCast sα - let ⟨_, vc, pc⟩ := evalMul sα va' vb + let ⟨_, vc, pc⟩ ← evalMul sα va' vb pure ⟨_, vc, (q(smul_eq_cast $pa' $pc) : Expr)⟩ theorem neg_one_mul {R} [Ring R] {a b : R} (_ : (Int.negOfNat (nat_lit 1)).rawCast * a = b) : @@ -570,7 +580,9 @@ theorem neg_mul {R} [Ring R] (a₁ : R) (a₂) {a₃ b : R} * `-c = (-c)` (for `c` coefficient) * `-(a₁ * a₂) = a₁ * -a₂` -/ -def evalNegProd {a : Q($α)} (rα : Q(Ring $α)) (va : ExProd sα a) : Result (ExProd sα) q(-$a) := +def evalNegProd {a : Q($α)} (rα : Q(Ring $α)) (va : ExProd sα a) : + Lean.Core.CoreM <| Result (ExProd sα) q(-$a) := do + Lean.Core.checkSystem decl_name%.toString match va with | .const za ha => let lit : Q(ℕ) := mkRawNatLit 1 @@ -581,10 +593,10 @@ def evalNegProd {a : Q($α)} (rα : Q(Ring $α)) (va : ExProd sα a) : Result (E q(CommSemiring.toSemiring) rm ra).get! let ⟨zb, hb⟩ := rb.toRatNZ.get! let ⟨b, (pb : Q((Int.negOfNat (nat_lit 1)).rawCast * $a = $b))⟩ := rb.toRawEq - ⟨b, .const zb hb, (q(neg_one_mul (R := $α) $pb) : Expr)⟩ + return ⟨b, .const zb hb, (q(neg_one_mul (R := $α) $pb) : Expr)⟩ | .mul (x := a₁) (e := a₂) va₁ va₂ va₃ => - let ⟨_, vb, pb⟩ := evalNegProd rα va₃ - ⟨_, .mul va₁ va₂ vb, (q(neg_mul $a₁ $a₂ $pb) : Expr)⟩ + let ⟨_, vb, pb⟩ ← evalNegProd rα va₃ + return ⟨_, .mul va₁ va₂ vb, (q(neg_mul $a₁ $a₂ $pb) : Expr)⟩ theorem neg_zero {R} [Ring R] : -(0 : R) = 0 := by simp @@ -597,13 +609,14 @@ theorem neg_add {R} [Ring R] {a₁ a₂ b₁ b₂ : R} * `-0 = 0` (for `c` coefficient) * `-(a₁ + a₂) = -a₁ + -a₂` -/ -def evalNeg {a : Q($α)} (rα : Q(Ring $α)) (va : ExSum sα a) : Result (ExSum sα) q(-$a) := +def evalNeg {a : Q($α)} (rα : Q(Ring $α)) (va : ExSum sα a) : + Lean.Core.CoreM <| Result (ExSum sα) q(-$a) := do match va with - | .zero => ⟨_, .zero, (q(neg_zero (R := $α)) : Expr)⟩ + | .zero => return ⟨_, .zero, (q(neg_zero (R := $α)) : Expr)⟩ | .add va₁ va₂ => - let ⟨_, vb₁, pb₁⟩ := evalNegProd sα rα va₁ - let ⟨_, vb₂, pb₂⟩ := evalNeg rα va₂ - ⟨_, .add vb₁ vb₂, (q(neg_add $pb₁ $pb₂) : Expr)⟩ + let ⟨_, vb₁, pb₁⟩ ← evalNegProd sα rα va₁ + let ⟨_, vb₂, pb₂⟩ ← evalNeg rα va₂ + return ⟨_, .add vb₁ vb₂, (q(neg_add $pb₁ $pb₂) : Expr)⟩ theorem sub_pf {R} [Ring R] {a b c d : R} (_ : -b = c) (_ : a + c = d) : a - b = d := by subst_vars; simp [sub_eq_add_neg] @@ -613,10 +626,11 @@ theorem sub_pf {R} [Ring R] {a b c d : R} * `a - b = a + -b` -/ def evalSub {α : Q(Type u)} (sα : Q(CommSemiring $α)) {a b : Q($α)} - (rα : Q(Ring $α)) (va : ExSum sα a) (vb : ExSum sα b) : Result (ExSum sα) q($a - $b) := - let ⟨_c, vc, pc⟩ := evalNeg sα rα vb - let ⟨d, vd, (pd : Q($a + $_c = $d))⟩ := evalAdd sα va vc - ⟨d, vd, (q(sub_pf $pc $pd) : Expr)⟩ + (rα : Q(Ring $α)) (va : ExSum sα a) (vb : ExSum sα b) : + Lean.Core.CoreM <| Result (ExSum sα) q($a - $b) := do + let ⟨_c, vc, pc⟩ ← evalNeg sα rα vb + let ⟨d, vd, (pd : Q($a + $_c = $d))⟩ ← evalAdd sα va vc + return ⟨d, vd, (q(sub_pf $pc $pd) : Expr)⟩ theorem pow_prod_atom (a : R) (b) : a ^ b = (a + 0) ^ b * (nat_lit 1).rawCast := by simp @@ -718,22 +732,23 @@ into a sum of monomials. * `x ^ (2*n) = x ^ n * x ^ n` * `x ^ (2*n+1) = x ^ n * x ^ n * x` -/ -partial def evalPowNat {a : Q($α)} (va : ExSum sα a) (n : Q(ℕ)) : Result (ExSum sα) q($a ^ $n) := +partial def evalPowNat {a : Q($α)} (va : ExSum sα a) (n : Q(ℕ)) : + Lean.Core.CoreM <| Result (ExSum sα) q($a ^ $n) := do let nn := n.natLit! if nn = 1 then - ⟨_, va, (q(pow_one $a) : Expr)⟩ + return ⟨_, va, (q(pow_one $a) : Expr)⟩ else let nm := nn >>> 1 have m : Q(ℕ) := mkRawNatLit nm if nn &&& 1 = 0 then - let ⟨_, vb, pb⟩ := evalPowNat va m - let ⟨_, vc, pc⟩ := evalMul sα vb vb - ⟨_, vc, (q(pow_bit0 $pb $pc) : Expr)⟩ + let ⟨_, vb, pb⟩ ← evalPowNat va m + let ⟨_, vc, pc⟩ ← evalMul sα vb vb + return ⟨_, vc, (q(pow_bit0 $pb $pc) : Expr)⟩ else - let ⟨_, vb, pb⟩ := evalPowNat va m - let ⟨_, vc, pc⟩ := evalMul sα vb vb - let ⟨_, vd, pd⟩ := evalMul sα vc va - ⟨_, vd, (q(pow_bit1 $pb $pc $pd) : Expr)⟩ + let ⟨_, vb, pb⟩ ← evalPowNat va m + let ⟨_, vc, pc⟩ ← evalMul sα vb vb + let ⟨_, vd, pd⟩ ← evalMul sα vc va + return ⟨_, vd, (q(pow_bit1 $pb $pc $pd) : Expr)⟩ theorem one_pow (b : ℕ) : ((nat_lit 1).rawCast : R) ^ b = (nat_lit 1).rawCast := by simp @@ -750,10 +765,11 @@ theorem mul_pow {ea₁ b c₁ : ℕ} {xa₁ : R} In all other cases we use `evalPowProdAtom`. -/ def evalPowProd {a : Q($α)} {b : Q(ℕ)} (va : ExProd sα a) (vb : ExProd sℕ b) : - Result (ExProd sα) q($a ^ $b) := - let res : Option (Result (ExProd sα) q($a ^ $b)) := do + Lean.Core.CoreM <| Result (ExProd sα) q($a ^ $b) := do + Lean.Core.checkSystem decl_name%.toString + let res : OptionT Lean.Core.CoreM (Result (ExProd sα) q($a ^ $b)) := do match va, vb with - | .const 1, _ => some ⟨_, va, (q(one_pow (R := $α) $b) : Expr)⟩ + | .const 1, _ => return ⟨_, va, (q(one_pow (R := $α) $b) : Expr)⟩ | .const za ha, .const zb hb => assert! 0 ≤ zb let ra := Result.ofRawRat za a ha @@ -763,13 +779,13 @@ def evalPowProd {a : Q($α)} {b : Q(ℕ)} (va : ExProd sα a) (vb : ExProd sℕ q(CommSemiring.toSemiring) ra let ⟨zc, hc⟩ ← rc.toRatNZ let ⟨c, pc⟩ := rc.toRawEq - some ⟨c, .const zc hc, pc⟩ - | .mul vxa₁ vea₁ va₂, vb => do - let ⟨_, vc₁, pc₁⟩ := evalMulProd sℕ vea₁ vb - let ⟨_, vc₂, pc₂⟩ := evalPowProd va₂ vb - some ⟨_, .mul vxa₁ vc₁ vc₂, q(mul_pow $pc₁ $pc₂)⟩ - | _, _ => none - res.getD (evalPowProdAtom sα va vb) + return ⟨c, .const zc hc, pc⟩ + | .mul vxa₁ vea₁ va₂, vb => + let ⟨_, vc₁, pc₁⟩ ← evalMulProd sℕ vea₁ vb + let ⟨_, vc₂, pc₂⟩ ← evalPowProd va₂ vb + return ⟨_, .mul vxa₁ vc₁ vc₂, q(mul_pow $pc₁ $pc₂)⟩ + | _, _ => OptionT.fail + return (← res.run).getD (evalPowProdAtom sα va vb) /-- The result of `extractCoeff` is a numeral and a proof that the original expression @@ -827,24 +843,25 @@ theorem pow_nat {b c k : ℕ} {d e : R} (_ : b = c * k) (_ : a ^ c = d) (_ : d ^ Otherwise `a ^ b` is just encoded as `a ^ b * 1 + 0` using `evalPowAtom`. -/ partial def evalPow₁ {a : Q($α)} {b : Q(ℕ)} (va : ExSum sα a) (vb : ExProd sℕ b) : - Result (ExSum sα) q($a ^ $b) := + Lean.Core.CoreM <| Result (ExSum sα) q($a ^ $b) := do match va, vb with | va, .const 1 => haveI : $b =Q Nat.rawCast (nat_lit 1) := ⟨⟩ - ⟨_, va, q(pow_one_cast $a)⟩ + return ⟨_, va, q(pow_one_cast $a)⟩ | .zero, vb => match vb.evalPos with - | some p => ⟨_, .zero, q(zero_pow (R := $α) $p)⟩ - | none => evalPowAtom sα (.sum .zero) vb + | some p => return ⟨_, .zero, q(zero_pow (R := $α) $p)⟩ + | none => return evalPowAtom sα (.sum .zero) vb | ExSum.add va .zero, vb => -- TODO: using `.add` here takes a while to compile? - let ⟨_, vc, pc⟩ := evalPowProd sα va vb - ⟨_, vc.toSum, q(single_pow $pc)⟩ + let ⟨_, vc, pc⟩ ← evalPowProd sα va vb + return ⟨_, vc.toSum, q(single_pow $pc)⟩ | va, vb => if vb.coeff > 1 then let ⟨k, _, vc, pc⟩ := extractCoeff vb - let ⟨_, vd, pd⟩ := evalPow₁ va vc - let ⟨_, ve, pe⟩ := evalPowNat sα vd k - ⟨_, ve, q(pow_nat $pc $pd $pe)⟩ - else evalPowAtom sα (.sum va) vb + let ⟨_, vd, pd⟩ ← evalPow₁ va vc + let ⟨_, ve, pe⟩ ← evalPowNat sα vd k + return ⟨_, ve, q(pow_nat $pc $pd $pe)⟩ + else + return evalPowAtom sα (.sum va) vb theorem pow_zero (a : R) : a ^ 0 = (nat_lit 1).rawCast + 0 := by simp @@ -858,17 +875,17 @@ theorem pow_add {b₁ b₂ : ℕ} {d : R} * `a ^ (b₁ + b₂) = a ^ b₁ * a ^ b₂` -/ def evalPow {a : Q($α)} {b : Q(ℕ)} (va : ExSum sα a) (vb : ExSum sℕ b) : - Result (ExSum sα) q($a ^ $b) := + Lean.Core.CoreM <| Result (ExSum sα) q($a ^ $b) := do match vb with - | .zero => ⟨_, (ExProd.mkNat sα 1).2.toSum, q(pow_zero $a)⟩ + | .zero => return ⟨_, (ExProd.mkNat sα 1).2.toSum, q(pow_zero $a)⟩ | .add vb₁ vb₂ => - let ⟨_, vc₁, pc₁⟩ := evalPow₁ sα va vb₁ - let ⟨_, vc₂, pc₂⟩ := evalPow va vb₂ - let ⟨_, vd, pd⟩ := evalMul sα vc₁ vc₂ - ⟨_, vd, q(pow_add $pc₁ $pc₂ $pd)⟩ + let ⟨_, vc₁, pc₁⟩ ← evalPow₁ sα va vb₁ + let ⟨_, vc₂, pc₂⟩ ← evalPow va vb₂ + let ⟨_, vd, pd⟩ ← evalMul sα vc₁ vc₂ + return ⟨_, vd, q(pow_add $pc₁ $pc₂ $pd)⟩ /-- This cache contains data required by the `ring` tactic during execution. -/ -structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) := +structure Cache {α : Q(Type u)} (sα : Q(CommSemiring $α)) where /-- A ring instance on `α`, if available. -/ rα : Option Q(Ring $α) /-- A division ring instance on `α`, if available. -/ @@ -968,6 +985,7 @@ def evalInvAtom (a : Q($α)) : AtomM (Result (ExBase sα) q($a⁻¹)) := do -/ def ExProd.evalInv {a : Q($α)} (czα : Option Q(CharZero $α)) (va : ExProd sα a) : AtomM (Result (ExProd sα) q($a⁻¹)) := do + Lean.Core.checkSystem decl_name%.toString match va with | .const c hc => let ra := Result.ofRawRat c a hc @@ -982,7 +1000,7 @@ def ExProd.evalInv {a : Q($α)} (czα : Option Q(CharZero $α)) (va : ExProd sα | .mul (x := a₁) (e := _a₂) _va₁ va₂ va₃ => do let ⟨_b₁, vb₁, pb₁⟩ ← evalInvAtom sα dα a₁ let ⟨_b₃, vb₃, pb₃⟩ ← va₃.evalInv czα - let ⟨c, vc, (pc : Q($_b₃ * ($_b₁ ^ $_a₂ * Nat.rawCast 1) = $c))⟩ := + let ⟨c, vc, (pc : Q($_b₃ * ($_b₁ ^ $_a₂ * Nat.rawCast 1) = $c))⟩ ← evalMulProd sα vb₃ (vb₁.toProd va₂) pure ⟨c, vc, (q(inv_mul $pb₁ $pb₃ $pc) : Expr)⟩ @@ -996,7 +1014,7 @@ def ExSum.evalInv {a : Q($α)} (czα : Option Q(CharZero $α)) (va : ExSum sα a match va with | ExSum.zero => pure ⟨_, .zero, (q(inv_zero (R := $α)) : Expr)⟩ | ExSum.add va ExSum.zero => do - let ⟨_, vb, pb⟩ ← va.evalInv dα czα + let ⟨_, vb, pb⟩ ← va.evalInv sα dα czα pure ⟨_, vb.toSum, (q(inv_single $pb) : Expr)⟩ | va => do let ⟨_, vb, pb⟩ ← evalInvAtom sα dα a @@ -1014,7 +1032,7 @@ theorem div_pf {R} [DivisionRing R] {a b c d : R} (_ : b⁻¹ = c) (_ : a * c = def evalDiv {a b : Q($α)} (rα : Q(DivisionRing $α)) (czα : Option Q(CharZero $α)) (va : ExSum sα a) (vb : ExSum sα b) : AtomM (Result (ExSum sα) q($a / $b)) := do let ⟨_c, vc, pc⟩ ← vb.evalInv sα rα czα - let ⟨d, vd, (pd : Q($a * $_c = $d))⟩ := evalMul sα va vc + let ⟨d, vd, (pd : Q($a * $_c = $d))⟩ ← evalMul sα va vc pure ⟨d, vd, (q(div_pf $pc $pd) : Expr)⟩ theorem add_congr (_ : a = a') (_ : b = b') (_ : a' + b' = c) : (a + b : R) = c := by @@ -1089,14 +1107,14 @@ partial def eval {u : Lean.Level} {α : Q(Type u)} (sα : Q(CommSemiring $α)) | ~q($a + $b) => let ⟨_, va, pa⟩ ← eval sα c a let ⟨_, vb, pb⟩ ← eval sα c b - let ⟨c, vc, p⟩ := evalAdd sα va vb + let ⟨c, vc, p⟩ ← evalAdd sα va vb pure ⟨c, vc, (q(add_congr $pa $pb $p) : Expr)⟩ | _ => els | ``HMul.hMul, _, _ | ``Mul.mul, _, _ => match e with | ~q($a * $b) => let ⟨_, va, pa⟩ ← eval sα c a let ⟨_, vb, pb⟩ ← eval sα c b - let ⟨c, vc, p⟩ := evalMul sα va vb + let ⟨c, vc, p⟩ ← evalMul sα va vb pure ⟨c, vc, (q(mul_congr $pa $pb $p) : Expr)⟩ | _ => els | ``HSMul.hSMul, _, _ => match e with @@ -1110,19 +1128,20 @@ partial def eval {u : Lean.Level} {α : Q(Type u)} (sα : Q(CommSemiring $α)) | ~q($a ^ $b) => let ⟨_, va, pa⟩ ← eval sα c a let ⟨_, vb, pb⟩ ← eval sℕ .nat b - let ⟨c, vc, p⟩ := evalPow sα va vb + let ⟨c, vc, p⟩ ← evalPow sα va vb pure ⟨c, vc, (q(pow_congr $pa $pb $p) : Expr)⟩ | _ => els | ``Neg.neg, some rα, _ => match e with | ~q(-$a) => let ⟨_, va, pa⟩ ← eval sα c a - let ⟨b, vb, p⟩ := evalNeg sα rα va + let ⟨b, vb, p⟩ ← evalNeg sα rα va pure ⟨b, vb, (q(neg_congr $pa $p) : Expr)⟩ + | _ => els | ``HSub.hSub, some rα, _ | ``Sub.sub, some rα, _ => match e with | ~q($a - $b) => do let ⟨_, va, pa⟩ ← eval sα c a let ⟨_, vb, pb⟩ ← eval sα c b - let ⟨c, vc, p⟩ := evalSub sα rα va vb + let ⟨c, vc, p⟩ ← evalSub sα rα va vb pure ⟨c, vc, (q(sub_congr $pa $pb $p) : Expr)⟩ | _ => els | ``Inv.inv, _, some dα => match e with @@ -1130,6 +1149,7 @@ partial def eval {u : Lean.Level} {α : Q(Type u)} (sα : Q(CommSemiring $α)) let ⟨_, va, pa⟩ ← eval sα c a let ⟨b, vb, p⟩ ← va.evalInv sα dα c.czα pure ⟨b, vb, (q(inv_congr $pa $p) : Expr)⟩ + | _ => els | ``HDiv.hDiv, _, some dα | ``Div.div, _, some dα => match e with | ~q($a / $b) => do let ⟨_, va, pa⟩ ← eval sα c a diff --git a/Mathlib/Tactic/Ring/Compare.lean b/Mathlib/Tactic/Ring/Compare.lean new file mode 100644 index 0000000000000..5868ee2ee1706 --- /dev/null +++ b/Mathlib/Tactic/Ring/Compare.lean @@ -0,0 +1,239 @@ +/- +Copyright (c) 2024 Heather Macbeth. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Heather Macbeth +-/ +import Mathlib.Tactic.Ring.Basic +import Mathlib.Tactic.NormNum.Ineq + +/-! +# Automation for proving inequalities in commutative (semi)rings + +This file provides automation for proving certain kinds of inequalities in commutative semirings: +goals of the form `A ≤ B` and `A < B` for which the ring-normal forms of `A` and `B` differ by a +nonnegative (resp. positive) constant. + +For example, `⊢ x + 3 + y < y + x + 4` is in scope because the normal forms of the LHS and RHS are, +respectively, `3 + (x + y)` and `4 + (x + y)`, which differ by an additive constant. + +## Main declarations + +* `Mathlib.Tactic.Ring.proveLE`: prove goals of the form `A ≤ B` (subject to the scope constraints + described) +* `Mathlib.Tactic.Ring.proveLT`: prove goals of the form `A < B` (subject to the scope constraints + described) + +## Implementation notes + +The automation is provided in the `MetaM` monad; that is, these functions are not user-facing. It +would not be hard to provide user-facing versions (see the test file), but the scope of this +automation is rather specialized and might be confusing to users. It is also subsumed by `linarith`. +-/ + +namespace Mathlib.Tactic.Ring + +open Lean Qq Meta + +/-! Rather than having the metaprograms `Mathlib.Tactic.Ring.evalLE` and +`Mathlib.Tactic.Ring.evalLT` perform all type class inference at the point of use, we record in +advance, as `abbrev`s, a few type class deductions which will certainly be necessary. They add no +new information (they can already be proved by `inferInstance`). + +This helps in speeding up the metaprograms in this file substantially -- about a 50% reduction in +heartbeat count in representative test cases -- since otherwise a substantial fraction of their +runtime is devoted to type class inference. -/ + +section Typeclass + +/-- `OrderedCommSemiring` implies `CommSemiring`. -/ +abbrev cs_of_ocs (α : Type*) [OrderedCommSemiring α] : CommSemiring α := inferInstance + +/-- `OrderedCommSemiring` implies `AddMonoidWithOne`. -/ +abbrev amwo_of_ocs (α : Type*) [OrderedCommSemiring α] : AddMonoidWithOne α := inferInstance + +/-- `OrderedCommSemiring` implies `LE`. -/ +abbrev le_of_ocs (α : Type*) [OrderedCommSemiring α] : LE α := inferInstance + +/-- `StrictOrderedCommSemiring` implies `CommSemiring`. -/ +abbrev cs_of_socs (α : Type*) [StrictOrderedCommSemiring α] : CommSemiring α := inferInstance + +/-- `StrictOrderedCommSemiring` implies `AddMonoidWithOne`. -/ +abbrev amwo_of_socs (α : Type*) [StrictOrderedCommSemiring α] : AddMonoidWithOne α := inferInstance + +/-- `StrictOrderedCommSemiring` implies `LT`. -/ +abbrev lt_of_socs (α : Type*) [StrictOrderedCommSemiring α] : LT α := inferInstance + +end Typeclass + +/-! The lemmas like `add_le_add_right` in the root namespace are stated under minimal type classes, +typically just `[CovariantClass α α (swap (· + ·)) (· ≤ ·)]` or similar. Here we restate these +lemmas under stronger type class assumptions (`[OrderedCommSemiring α]` or similar), which helps in +speeding up the metaprograms in this file (`Mathlib.Tactic.Ring.proveLT` and +`Mathlib.Tactic.Ring.proveLE`) substantially -- about a 50% reduction in heartbeat count in +representative test cases -- since otherwise a substantial fraction of their runtime is devoted to +type class inference. + +These metaprograms at least require `CommSemiring`, `LE`/`LT`, and all +`CovariantClass`/`ContravariantClass` permutations for addition, and in their main use case (in +`linear_combination`) the `Preorder` type class is also required, so it is rather little loss of +generality simply to require `OrderedCommSemiring`/`StrictOrderedCommSemiring`. -/ + +section Lemma + +theorem add_le_add_right {α : Type*} [OrderedCommSemiring α] {b c : α} (bc : b ≤ c) (a : α) : + b + a ≤ c + a := + _root_.add_le_add_right bc a + +theorem add_le_of_nonpos_left {α : Type*} [OrderedCommSemiring α] (a : α) {b : α} (h : b ≤ 0) : + b + a ≤ a := + _root_.add_le_of_nonpos_left h + +theorem le_add_of_nonneg_left {α : Type*} [OrderedCommSemiring α] (a : α) {b : α} (h : 0 ≤ b) : + a ≤ b + a := + _root_.le_add_of_nonneg_left h + +theorem add_lt_add_right {α : Type*} [StrictOrderedCommSemiring α] {b c : α} (bc : b < c) (a : α) : + b + a < c + a := + _root_.add_lt_add_right bc a + +theorem add_lt_of_neg_left {α : Type*} [StrictOrderedCommSemiring α] (a : α) {b : α} (h : b < 0) : + b + a < a := + _root_.add_lt_of_neg_left a h + +theorem lt_add_of_pos_left {α : Type*} [StrictOrderedCommSemiring α] (a : α) {b : α} (h : 0 < b) : + a < b + a := + _root_.lt_add_of_pos_left a h + +end Lemma + +/-- Inductive type carrying the two kinds of errors which can arise in the metaprograms +`Mathlib.Tactic.Ring.evalLE` and `Mathlib.Tactic.Ring.evalLT`. -/ +inductive ExceptType | tooSmall | notComparable +export ExceptType (tooSmall notComparable) + +/-- In a commutative semiring, given `Ring.ExSum` objects `va`, `vb` which differ by a positive +(additive) constant, construct a proof of `$a < $b`, where `a` (resp. `b`) is the expression in the +semiring to which `va` (resp. `vb`) evaluates. -/ +def evalLE {v : Level} {α : Q(Type v)} (_ : Q(OrderedCommSemiring $α)) {a b : Q($α)} + (va : Ring.ExSum q(cs_of_ocs $α) a) (vb : Ring.ExSum q(cs_of_ocs $α) b) : + MetaM (Except ExceptType Q($a ≤ $b)) := do + let lα : Q(LE $α) := q(le_of_ocs $α) + assumeInstancesCommute + let ⟨_, pz⟩ ← NormNum.mkOfNat α q(amwo_of_ocs $α) (mkRawNatLit 0) + let rz : NormNum.Result q((0:$α)) := + NormNum.Result.isNat q(amwo_of_ocs $α) (mkRawNatLit 0) (q(NormNum.isNat_ofNat $α $pz):) + match va, vb with + /- `0 ≤ 0` -/ + | .zero, .zero => pure <| .ok (q(le_refl (0:$α)):) + /- For numerals `ca` and `cb`, `ca + x ≤ cb + x` if `ca ≤ cb` -/ + | .add (b := a') (.const (e := xa) ca hypa) va', .add (.const (e := xb) cb hypb) vb' => do + unless va'.eq vb' do return .error notComparable + let rxa := NormNum.Result.ofRawRat ca xa hypa + let rxb := NormNum.Result.ofRawRat cb xb hypb + let NormNum.Result.isTrue pf ← NormNum.evalLE.core lα rxa rxb | return .error tooSmall + pure <| .ok (q(add_le_add_right (a := $a') $pf):) + /- For a numeral `ca ≤ 0`, `ca + x ≤ x` -/ + | .add (.const (e := xa) ca hypa) va', _ => do + unless va'.eq vb do return .error notComparable + let rxa := NormNum.Result.ofRawRat ca xa hypa + let NormNum.Result.isTrue pf ← NormNum.evalLE.core lα rxa rz | return .error tooSmall + pure <| .ok (q(add_le_of_nonpos_left (a := $b) $pf):) + /- For a numeral `0 ≤ cb`, `x ≤ cb + x` -/ + | _, .add (.const (e := xb) cb hypb) vb' => do + unless va.eq vb' do return .error notComparable + let rxb := NormNum.Result.ofRawRat cb xb hypb + let NormNum.Result.isTrue pf ← NormNum.evalLE.core lα rz rxb | return .error tooSmall + pure <| .ok (q(le_add_of_nonneg_left (a := $a) $pf):) + | _, _ => return .error notComparable + +/-- In a commutative semiring, given `Ring.ExSum` objects `va`, `vb` which differ by a positive +(additive) constant, construct a proof of `$a < $b`, where `a` (resp. `b`) is the expression in the +semiring to which `va` (resp. `vb`) evaluates. -/ +def evalLT {v : Level} {α : Q(Type v)} (_ : Q(StrictOrderedCommSemiring $α)) {a b : Q($α)} + (va : Ring.ExSum q(cs_of_socs $α) a) (vb : Ring.ExSum q(cs_of_socs $α) b) : + MetaM (Except ExceptType Q($a < $b)) := do + let lα : Q(LT $α) := q(lt_of_socs $α) + assumeInstancesCommute + let ⟨_, pz⟩ ← NormNum.mkOfNat α q(amwo_of_socs $α) (mkRawNatLit 0) + let rz : NormNum.Result q((0:$α)) := + NormNum.Result.isNat q(amwo_of_socs $α) (mkRawNatLit 0) (q(NormNum.isNat_ofNat $α $pz):) + match va, vb with + /- `0 < 0` -/ + | .zero, .zero => return .error tooSmall + /- For numerals `ca` and `cb`, `ca + x < cb + x` if `ca < cb` -/ + | .add (b := a') (.const (e := xa) ca hypa) va', .add (.const (e := xb) cb hypb) vb' => do + unless va'.eq vb' do return .error notComparable + let rxa := NormNum.Result.ofRawRat ca xa hypa + let rxb := NormNum.Result.ofRawRat cb xb hypb + let NormNum.Result.isTrue pf ← NormNum.evalLT.core lα rxa rxb | return .error tooSmall + pure <| .ok (q(add_lt_add_right $pf $a'):) + /- For a numeral `ca < 0`, `ca + x < x` -/ + | .add (.const (e := xa) ca hypa) va', _ => do + unless va'.eq vb do return .error notComparable + let rxa := NormNum.Result.ofRawRat ca xa hypa + let NormNum.Result.isTrue pf ← NormNum.evalLT.core lα rxa rz | return .error tooSmall + have pf : Q($xa < 0) := pf + pure <| .ok (q(add_lt_of_neg_left $b $pf):) + /- For a numeral `0 < cb`, `x < cb + x` -/ + | _, .add (.const (e := xb) cb hypb) vb' => do + unless va.eq vb' do return .error notComparable + let rxb := NormNum.Result.ofRawRat cb xb hypb + let NormNum.Result.isTrue pf ← NormNum.evalLT.core lα rz rxb | return .error tooSmall + pure <| .ok (q(lt_add_of_pos_left $a $pf):) + | _, _ => return .error notComparable + +theorem le_congr {α : Type*} [LE α] {a b c d : α} (h1 : a = b) (h2 : b ≤ c) (h3 : d = c) : + a ≤ d := by + rwa [h1, h3] + +theorem lt_congr {α : Type*} [LT α] {a b c d : α} (h1 : a = b) (h2 : b < c) (h3 : d = c) : + a < d := by + rwa [h1, h3] + +/-- Prove goals of the form `A ≤ B` in an ordered commutative semiring, if the ring-normal forms of +`A` and `B` differ by a nonnegative (additive) constant. -/ +def proveLE (g : MVarId) : MetaM Unit := do + let some (α, e₁, e₂) := (← whnfR <|← instantiateMVars <|← g.getType).le? + | throwError "ring failed: not of the form `A ≤ B`" + let .sort u ← whnf (← inferType α) | unreachable! + let v ← try u.dec catch _ => throwError "not a type{indentExpr α}" + have α : Q(Type v) := α + let sα ← synthInstanceQ q(OrderedCommSemiring $α) + assumeInstancesCommute + have e₁ : Q($α) := e₁; have e₂ : Q($α) := e₂ + let c ← mkCache q(cs_of_ocs $α) + let (⟨a, va, pa⟩, ⟨b, vb, pb⟩) + ← AtomM.run .instances do pure (← eval q(cs_of_ocs $α) c e₁, ← eval q(cs_of_ocs $α) c e₂) + match ← evalLE sα va vb with + | .ok p => g.assign q(le_congr $pa $p $pb) + | .error e => + let g' ← mkFreshExprMVar (← (← ringCleanupRef.get) q($a ≤ $b)) + match e with + | notComparable => + throwError "ring failed, ring expressions not equal up to an additive constant\n{g'.mvarId!}" + | tooSmall => throwError "comparison failed, LHS is larger\n{g'.mvarId!}" + +/-- Prove goals of the form `A < B` in an ordered commutative semiring, if the ring-normal forms of +`A` and `B` differ by a positive (additive) constant. -/ +def proveLT (g : MVarId) : MetaM Unit := do + let some (α, e₁, e₂) := (← whnfR <|← instantiateMVars <|← g.getType).lt? + | throwError "ring failed: not of the form `A < B`" + let .sort u ← whnf (← inferType α) | unreachable! + let v ← try u.dec catch _ => throwError "not a type{indentExpr α}" + have α : Q(Type v) := α + let sα ← synthInstanceQ q(StrictOrderedCommSemiring $α) + assumeInstancesCommute + have e₁ : Q($α) := e₁; have e₂ : Q($α) := e₂ + let c ← mkCache q(cs_of_socs $α) + let (⟨a, va, pa⟩, ⟨b, vb, pb⟩) + ← AtomM.run .instances do pure (← eval q(cs_of_socs $α) c e₁, ← eval q(cs_of_socs $α) c e₂) + match ← evalLT sα va vb with + | .ok p => g.assign q(lt_congr $pa $p $pb) + | .error e => + let g' ← mkFreshExprMVar (← (← ringCleanupRef.get) q($a < $b)) + match e with + | notComparable => + throwError "ring failed, ring expressions not equal up to an additive constant\n{g'.mvarId!}" + | tooSmall => throwError "comparison failed, LHS is at least as large\n{g'.mvarId!}" + +end Mathlib.Tactic.Ring diff --git a/Mathlib/Tactic/Ring/RingNF.lean b/Mathlib/Tactic/Ring/RingNF.lean index 4ac168ff6ec41..c538ee4c12311 100644 --- a/Mathlib/Tactic/Ring/RingNF.lean +++ b/Mathlib/Tactic/Ring/RingNF.lean @@ -147,7 +147,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 - r'.mkEqTrans (← Simp.main r'.expr ctx' (methods := ← Lean.Meta.Simp.mkDefaultMethods)).1 + r'.mkEqTrans (← Simp.main r'.expr ctx' (methods := Lean.Meta.Simp.mkDefaultMethodsCore {})).1 let nctx := { ctx, simp } let rec /-- The recursive context. -/ diff --git a/Mathlib/Tactic/Says.lean b/Mathlib/Tactic/Says.lean index 87f93ae495ba1..29bd33ed183cf 100644 --- a/Mathlib/Tactic/Says.lean +++ b/Mathlib/Tactic/Says.lean @@ -40,7 +40,7 @@ register_option says.verify : Bool := register_option says.no_verify_in_CI : Bool := { defValue := false group := "says" - descr := "Disable reverification, even if `the `CI` environment variable is set." } + descr := "Disable reverification, even if the `CI` environment variable is set." } open Parser Tactic diff --git a/Mathlib/Tactic/ToExpr.lean b/Mathlib/Tactic/ToExpr.lean index b02e21d2b44bb..8997800729532 100644 --- a/Mathlib/Tactic/ToExpr.lean +++ b/Mathlib/Tactic/ToExpr.lean @@ -50,8 +50,6 @@ end override namespace Mathlib open Lean -deriving instance ToExpr for Int - set_option autoImplicit true in deriving instance ToExpr for ULift diff --git a/Mathlib/Tactic/WLOG.lean b/Mathlib/Tactic/WLOG.lean index c996e5552b6df..461949d04ab7b 100644 --- a/Mathlib/Tactic/WLOG.lean +++ b/Mathlib/Tactic/WLOG.lean @@ -86,7 +86,8 @@ def _root_.Lean.MVarId.wlog (goal : MVarId) (h : Option Name) (P : Expr) let hGoal := HExpr.mvarId! /- Begin the "reduction goal" which will contain hypotheses `H` and `¬h`. For now, it only contains `H`. Keep track of that hypothesis' FVarId. -/ - let (HFVarId, reductionGoal) ← goal.assertHypotheses #[⟨H, HType, HExpr⟩] + let (HFVarId, reductionGoal) ← + goal.assertHypotheses #[{ userName := H, type := HType, value := HExpr }] let HFVarId := HFVarId[0]! /- Clear the reverted fvars from the branch that will contain `h` as a hypothesis. -/ let hGoal ← hGoal.tryClearMany revertedFVars diff --git a/Mathlib/Tactic/Widget/Calc.lean b/Mathlib/Tactic/Widget/Calc.lean index bbcba1e9996ae..5e39f560b44b2 100644 --- a/Mathlib/Tactic/Widget/Calc.lean +++ b/Mathlib/Tactic/Widget/Calc.lean @@ -17,7 +17,7 @@ new calc steps with holes specified by selected sub-expressions in the goal. -/ section code_action -open Std CodeAction +open Batteries.CodeAction open Lean Server RequestM /-- Code action to create a `calc` tactic from the current goal. -/ diff --git a/Mathlib/Tactic/Widget/InteractiveUnfold.lean b/Mathlib/Tactic/Widget/InteractiveUnfold.lean index b88ea0416d05d..7d3eae135546f 100644 --- a/Mathlib/Tactic/Widget/InteractiveUnfold.lean +++ b/Mathlib/Tactic/Widget/InteractiveUnfold.lean @@ -225,7 +225,7 @@ elab stx:"unfold?" : tactic => do /-- `#unfold? e` gives all unfolds of `e`. In tactic mode, use `unfold?` instead. -/ -syntax (name := unfoldCommand) "#unfold?" term : command +syntax (name := unfoldCommand) "#unfold? " term : command open Elab /-- Elaborate a `#unfold?` command. -/ diff --git a/Mathlib/Testing/SlimCheck/Functions.lean b/Mathlib/Testing/SlimCheck/Functions.lean index 12325734b9e55..80acb2790dfaf 100644 --- a/Mathlib/Testing/SlimCheck/Functions.lean +++ b/Mathlib/Testing/SlimCheck/Functions.lean @@ -330,7 +330,7 @@ theorem applyId_mem_iff [DecidableEq α] {xs ys : List α} (h₀ : List.Nodup xs specialize xs_ih h₅ h₃ h₄ h₆ simp only [Ne.symm h, xs_ih, List.mem_cons] suffices val ∈ ys by tauto - erw [← Option.mem_def, List.mem_dlookup_iff] at h₃ + rw [← Option.mem_def, List.mem_dlookup_iff] at h₃ · simp only [Prod.toSigma, List.mem_map, heq_iff_eq, Prod.exists] at h₃ rcases h₃ with ⟨a, b, h₃, h₄, h₅⟩ apply (List.of_mem_zip h₃).2 @@ -363,7 +363,7 @@ theorem applyId_injective [DecidableEq α] {xs ys : List α} (h₀ : List.Nodup · symm; rw [h] rw [← List.applyId_zip_eq] <;> assumption · rw [← h₁.length_eq] - rw [List.getElem?_eq_some] at hx + rw [List.getElem?_eq_some_iff] at hx cases' hx with hx hx' exact hx · rw [← applyId_mem_iff h₀ h₁] at hx hy diff --git a/Mathlib/Testing/SlimCheck/Testable.lean b/Mathlib/Testing/SlimCheck/Testable.lean index e4ece33e569d8..af3278d4fc34d 100644 --- a/Mathlib/Testing/SlimCheck/Testable.lean +++ b/Mathlib/Testing/SlimCheck/Testable.lean @@ -423,7 +423,7 @@ end Testable section PrintableProp -variable {α : Type*} {x y : α} +variable {α : Type*} instance Eq.printableProp [Repr α] {x y : α} : PrintableProp (x = y) where printProp := s!"{repr x} = {repr y}" diff --git a/Mathlib/Topology/AlexandrovDiscrete.lean b/Mathlib/Topology/AlexandrovDiscrete.lean index b03c9b2cb45eb..455d1c1792743 100644 --- a/Mathlib/Topology/AlexandrovDiscrete.lean +++ b/Mathlib/Topology/AlexandrovDiscrete.lean @@ -114,8 +114,6 @@ lemma closure_sUnion (S : Set (Set α)) : closure (⋃₀ S) = ⋃ s ∈ S, clos end AlexandrovDiscrete -variable {s t : Set α} {a x y : α} - lemma Inducing.alexandrovDiscrete [AlexandrovDiscrete α] {f : β → α} (h : Inducing f) : AlexandrovDiscrete β where isOpen_sInter S hS := by @@ -141,7 +139,7 @@ lemma alexandrovDiscrete_iSup {t : ι → TopologicalSpace α} (_ : ∀ i, @Alex section variable [TopologicalSpace α] [TopologicalSpace β] [AlexandrovDiscrete α] [AlexandrovDiscrete β] - {s t : Set α} {a x y : α} + {s t : Set α} {a : α} @[simp] lemma isOpen_exterior : IsOpen (exterior s) := by rw [exterior_def]; exact isOpen_sInter fun _ ↦ And.left diff --git a/Mathlib/Topology/Algebra/Category/ProfiniteGrp.lean b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean similarity index 58% rename from Mathlib/Topology/Algebra/Category/ProfiniteGrp.lean rename to Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean index 7f613f00bfb58..803016fe59879 100644 --- a/Mathlib/Topology/Algebra/Category/ProfiniteGrp.lean +++ b/Mathlib/Topology/Algebra/Category/ProfiniteGrp/Basic.lean @@ -4,10 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jujian Zhang, Nailin Guan, Yuyang Zhao -/ import Mathlib.Algebra.Category.Grp.FiniteGrp +import Mathlib.Topology.Algebra.ClosedSubgroup import Mathlib.Topology.Algebra.ContinuousMonoidHom import Mathlib.Topology.Category.Profinite.Basic - - /-! # Category of Profinite Groups @@ -24,9 +23,11 @@ disconnected. * `ofFiniteGrp` : A `FiniteGrp` when given the discrete topology can be considered as a profinite group. +* `ofClosedSubgroup` : A closed subgroup of a profinite group is profinite. + -/ -universe u +universe u v open CategoryTheory Topology @@ -161,4 +162,100 @@ instance : HasForget₂ ProfiniteGrp Grp where map := fun f => f.toMonoidHom } +/-- A closed subgroup of a profinite group is profinite. -/ +def ofClosedSubgroup {G : ProfiniteGrp} (H : ClosedSubgroup G) : ProfiniteGrp := + letI : CompactSpace H := inferInstance + of H.1 + +/-- The functor mapping a profinite group to its underlying profinite space. -/ +def profiniteGrpToProfinite : ProfiniteGrp ⥤ Profinite where + obj G := G.toProfinite + map f := ⟨f, by continuity⟩ + +instance : profiniteGrpToProfinite.Faithful := { + map_injective := fun {_ _} _ _ h => + ConcreteCategory.hom_ext_iff.mpr (congrFun (congrArg ContinuousMap.toFun h)) } + +end ProfiniteGrp + +/-! +# Limits in the category of profinite groups + +In this section, we construct limits in the category of profinite groups. + +* `ProfiniteGrp.limitCone` : The explicit limit cone in `ProfiniteGrp`. + +* `ProfiniteGrp.limitConeIsLimit`: `ProfiniteGrp.limitCone` is a limit cone. + +-/ + +section Limits + +namespace ProfiniteGrp + +section + +variable {J : Type v} [SmallCategory J] (F : J ⥤ ProfiniteGrp.{max v u}) + +/-- Auxiliary construction to obtain the group structure on the limit of profinite groups. -/ +def limitConePtAux : Subgroup (Π j : J, F.obj j) where + carrier := {x | ∀ ⦃i j : J⦄ (π : i ⟶ j), F.map π (x i) = x j} + mul_mem' hx hy _ _ π := by simp only [Pi.mul_apply, map_mul, hx π, hy π] + one_mem' := by simp only [Set.mem_setOf_eq, Pi.one_apply, map_one, implies_true] + inv_mem' h _ _ π := by simp only [Pi.inv_apply, map_inv, h π] + +instance : Group (Profinite.limitCone (F ⋙ profiniteGrpToProfinite.{max v u})).pt := + inferInstanceAs (Group (limitConePtAux F)) + +instance : TopologicalGroup (Profinite.limitCone (F ⋙ profiniteGrpToProfinite.{max v u})).pt := + inferInstanceAs (TopologicalGroup (limitConePtAux F)) + +/-- The explicit limit cone in `ProfiniteGrp`. -/ +abbrev limitCone : Limits.Cone F where + pt := ofProfinite (Profinite.limitCone (F ⋙ profiniteGrpToProfinite.{max v u})).pt + π := + { app := fun j => { + toFun := fun x => x.1 j + map_one' := rfl + map_mul' := fun x y => rfl + continuous_toFun := by + exact (continuous_apply j).comp (continuous_iff_le_induced.mpr fun U a => a) } + naturality := fun i j f => by + simp only [Functor.const_obj_obj, Functor.comp_obj, + Functor.const_obj_map, Category.id_comp, Functor.comp_map] + congr + exact funext fun x => (x.2 f).symm } + +/-- `ProfiniteGrp.limitCone` is a limit cone. -/ +def limitConeIsLimit : Limits.IsLimit (limitCone F) where + lift cone := { + ((Profinite.limitConeIsLimit (F ⋙ profiniteGrpToProfinite)).lift + (profiniteGrpToProfinite.mapCone cone)) with + map_one' := Subtype.ext (funext fun j ↦ map_one (cone.π.app j)) + -- TODO: investigate whether it's possible to set up `ext` lemmas for the `TopCat`-related + -- categories so that `by ext j; exact map_one (cone.π.app j)` works here, similarly below. + map_mul' := fun _ _ ↦ Subtype.ext (funext fun j ↦ map_mul (cone.π.app j) _ _) } + uniq cone m h := by + apply profiniteGrpToProfinite.map_injective + simpa using (Profinite.limitConeIsLimit (F ⋙ profiniteGrpToProfinite)).uniq + (profiniteGrpToProfinite.mapCone cone) (profiniteGrpToProfinite.map m) + (fun j ↦ congrArg profiniteGrpToProfinite.map (h j)) + +instance : Limits.HasLimit F where + exists_limit := Nonempty.intro + { cone := limitCone F + isLimit := limitConeIsLimit F } + +/-- The abbreviation for the limit of `ProfiniteGrp`s. -/ +abbrev limit : ProfiniteGrp := (ProfiniteGrp.limitCone F).pt + +end + +instance : Limits.PreservesLimits profiniteGrpToProfinite.{u} where + preservesLimitsOfShape := { + preservesLimit := fun {F} ↦ CategoryTheory.Limits.preservesLimitOfPreservesLimitCone + (limitConeIsLimit F) (Profinite.limitConeIsLimit (F ⋙ profiniteGrpToProfinite)) } + end ProfiniteGrp + +end Limits diff --git a/Mathlib/Topology/Algebra/ClosedSubgroup.lean b/Mathlib/Topology/Algebra/ClosedSubgroup.lean new file mode 100644 index 0000000000000..302f09738270a --- /dev/null +++ b/Mathlib/Topology/Algebra/ClosedSubgroup.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2024 Nailin Guan. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Nailin Guan +-/ + +import Mathlib.Topology.Algebra.Group.Basic +import Mathlib.Algebra.Group.Subgroup.Basic +import Mathlib.GroupTheory.Index + +/-! +# Closed subgroups of a topological group + +This files builds the SemilatticeInf `ClosedSubgroup G` of closed subgroups in a +topological group `G`, and its additive version `ClosedAddSubgroup`. + +# Main definitions and results + +* `normalCore_isClosed` : The `normalCore` of a closed subgroup is closed. + +* `finindex_closedSubgroup_isOpen` : A closed subgroup with finite index is open. + +-/ + +section + +universe u v + +/-- The type of closed subgroups of a topological group. -/ +@[ext] +structure ClosedSubgroup (G : Type u) [Group G] [TopologicalSpace G] extends Subgroup G where + isClosed' : IsClosed carrier + +/-- The type of closed subgroups of an additive topological group. -/ +@[ext] +structure ClosedAddSubgroup (G : Type u) [AddGroup G] [TopologicalSpace G] extends + AddSubgroup G where + isClosed' : IsClosed carrier + +attribute [to_additive] ClosedSubgroup + +attribute [coe] ClosedSubgroup.toSubgroup ClosedAddSubgroup.toAddSubgroup + +namespace ClosedSubgroup + +variable (G : Type u) [Group G] [TopologicalSpace G] + +variable {G} in +@[to_additive] +theorem toSubgroup_injective : Function.Injective + (ClosedSubgroup.toSubgroup : ClosedSubgroup G → Subgroup G) := + fun A B h ↦ by + ext + rw [h] + +@[to_additive] +instance : SetLike (ClosedSubgroup G) G where + coe U := U.1 + coe_injective' _ _ h := toSubgroup_injective <| SetLike.ext' h + +@[to_additive] +instance : SubgroupClass (ClosedSubgroup G) G where + mul_mem := Subsemigroup.mul_mem' _ + one_mem U := U.one_mem' + inv_mem := Subgroup.inv_mem' _ + +@[to_additive] +instance : Coe (ClosedSubgroup G) (Subgroup G) where + coe := toSubgroup + +@[to_additive] +instance instInfClosedSubgroup : Inf (ClosedSubgroup G) := + ⟨fun U V ↦ ⟨U ⊓ V, U.isClosed'.inter V.isClosed'⟩⟩ + +@[to_additive] +instance instSemilatticeInfClosedSubgroup : SemilatticeInf (ClosedSubgroup G) := + SetLike.coe_injective.semilatticeInf ((↑) : ClosedSubgroup G → Set G) fun _ _ ↦ rfl + +@[to_additive] +instance [CompactSpace G] (H : ClosedSubgroup G) : CompactSpace H := + isCompact_iff_compactSpace.mp (IsClosed.isCompact H.isClosed') + +end ClosedSubgroup + +open scoped Pointwise + +namespace Subgroup + +variable {G : Type u} [Group G] [TopologicalSpace G] [ContinuousMul G] + +lemma normalCore_isClosed (H : Subgroup G) (h : IsClosed (H : Set G)) : + IsClosed (H.normalCore : Set G) := by + rw [normalCore_eq_iInf_conjAct] + push_cast + apply isClosed_iInter + intro g + convert IsClosed.preimage (TopologicalGroup.continuous_conj (ConjAct.ofConjAct g⁻¹)) h + exact Set.ext (fun t ↦ Set.mem_smul_set_iff_inv_smul_mem) + +@[to_additive] +lemma isOpen_of_isClosed_of_finiteIndex (H : Subgroup G) [H.FiniteIndex] + (h : IsClosed (H : Set G)) : IsOpen (H : Set G) := by + apply isClosed_compl_iff.mp + convert isClosed_iUnion_of_finite <| fun (x : {x : (G ⧸ H) // x ≠ QuotientGroup.mk 1}) + ↦ IsClosed.smul h (Quotient.out' x.1) + ext x + refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩ + · have : QuotientGroup.mk 1 ≠ QuotientGroup.mk (s := H) x := by + apply QuotientGroup.eq.not.mpr + simpa only [inv_one, one_mul, ne_eq] + simp only [ne_eq, Set.mem_iUnion] + use ⟨QuotientGroup.mk (s := H) x, this.symm⟩, + (Quotient.out' (QuotientGroup.mk (s := H) x))⁻¹ * x + simp only [SetLike.mem_coe, smul_eq_mul, mul_inv_cancel_left, and_true] + exact QuotientGroup.eq.mp <| QuotientGroup.out_eq' (QuotientGroup.mk (s := H) x) + · rcases h with ⟨S,⟨y,hS⟩,mem⟩ + simp only [← hS] at mem + rcases mem with ⟨h,hh,eq⟩ + simp only [Set.mem_compl_iff, SetLike.mem_coe] + by_contra mH + simp only [← eq, ne_eq, smul_eq_mul] at mH + absurd y.2.symm + rw [← QuotientGroup.out_eq' y.1, QuotientGroup.eq] + simp only [inv_one, ne_eq, one_mul, (Subgroup.mul_mem_cancel_right H hh).mp mH] + +end Subgroup + +end diff --git a/Mathlib/Topology/Algebra/ConstMulAction.lean b/Mathlib/Topology/Algebra/ConstMulAction.lean index 482927bb1d468..7f721b2b8dbdd 100644 --- a/Mathlib/Topology/Algebra/ConstMulAction.lean +++ b/Mathlib/Topology/Algebra/ConstMulAction.lean @@ -79,7 +79,7 @@ theorem Filter.Tendsto.const_smul {f : β → α} {l : Filter β} {a : α} (hf : (c : M) : Tendsto (fun x => c • f x) l (𝓝 (c • a)) := ((continuous_const_smul _).tendsto _).comp hf -variable [TopologicalSpace β] {f : β → M} {g : β → α} {b : β} {s : Set β} +variable [TopologicalSpace β] {g : β → α} {b : β} {s : Set β} @[to_additive] nonrec theorem ContinuousWithinAt.const_smul (hg : ContinuousWithinAt g s b) (c : M) : @@ -451,6 +451,11 @@ theorem isOpenMap_quotient_mk'_mul [ContinuousConstSMul Γ T] : rw [isOpen_coinduced, MulAction.quotient_preimage_image_eq_union_mul U] exact isOpen_iUnion fun γ => isOpenMap_smul γ U hU +@[to_additive] +theorem MulAction.isOpenQuotientMap_quotientMk [ContinuousConstSMul Γ T] : + IsOpenQuotientMap (Quotient.mk (MulAction.orbitRel Γ T)) := + ⟨surjective_quot_mk _, continuous_quot_mk, isOpenMap_quotient_mk'_mul⟩ + /-- The quotient by a discontinuous group action of a locally compact t2 space is t2. -/ @[to_additive "The quotient by a discontinuous group action of a locally compact t2 space is t2."] diff --git a/Mathlib/Topology/Algebra/ContinuousAffineMap.lean b/Mathlib/Topology/Algebra/ContinuousAffineMap.lean index 39cb34e5d4264..0c94ea673275e 100644 --- a/Mathlib/Topology/Algebra/ContinuousAffineMap.lean +++ b/Mathlib/Topology/Algebra/ContinuousAffineMap.lean @@ -4,7 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.LinearAlgebra.AffineSpace.AffineMap -import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Topology.Algebra.Module.Basic /-! diff --git a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean index de9f0789c24cb..4e852f064519b 100644 --- a/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean +++ b/Mathlib/Topology/Algebra/ContinuousMonoidHom.lean @@ -5,7 +5,7 @@ Authors: Thomas Browning -/ import Mathlib.Topology.Algebra.Equicontinuity import Mathlib.Topology.Algebra.Group.Compact -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Topology.UniformSpace.Ascoli /-! @@ -30,49 +30,45 @@ variable (F A B C D E : Type*) [Monoid A] [Monoid B] [Monoid C] [Monoid D] [Comm /-- The type of continuous additive monoid homomorphisms from `A` to `B`. When possible, instead of parametrizing results over `(f : ContinuousAddMonoidHom A B)`, -you should parametrize over `(F : Type*) [ContinuousAddMonoidHomClass F A B] (f : F)`. +you should parametrize +over `(F : Type*) [FunLike F A B] [ContinuousMapClass F A B] [AddMonoidHomClass F A B] (f : F)`. -When you extend this structure, make sure to extend `ContinuousAddMonoidHomClass`. -/ +When you extend this structure, +make sure to extend `ContinuousMapClass` and/or `AddMonoidHomClass`, if needed. -/ structure ContinuousAddMonoidHom (A B : Type*) [AddMonoid A] [AddMonoid B] [TopologicalSpace A] - [TopologicalSpace B] extends A →+ B where - /-- Proof of continuity of the Hom. -/ - continuous_toFun : @Continuous A B _ _ toFun + [TopologicalSpace B] extends A →+ B, C(A, B) /-- The type of continuous monoid homomorphisms from `A` to `B`. When possible, instead of parametrizing results over `(f : ContinuousMonoidHom A B)`, -you should parametrize over `(F : Type*) [ContinuousMonoidHomClass F A B] (f : F)`. +you should parametrize +over `(F : Type*) [FunLike F A B] [ContinuousMapClass F A B] [MonoidHomClass F A B] (f : F)`. -When you extend this structure, make sure to extend `ContinuousAddMonoidHomClass`. -/ +When you extend this structure, +make sure to extend `ContinuousMapClass` and/or `MonoidHomClass`, if needed. -/ @[to_additive "The type of continuous additive monoid homomorphisms from `A` to `B`."] -structure ContinuousMonoidHom extends A →* B where - /-- Proof of continuity of the Hom. -/ - continuous_toFun : @Continuous A B _ _ toFun +structure ContinuousMonoidHom extends A →* B, C(A, B) section /-- `ContinuousAddMonoidHomClass F A B` states that `F` is a type of continuous additive monoid homomorphisms. -You should also extend this typeclass when you extend `ContinuousAddMonoidHom`. -/ --- Porting note: Changed A B to outParam to help synthesizing order -class ContinuousAddMonoidHomClass (A B : outParam Type*) [AddMonoid A] [AddMonoid B] +Deprecated and changed from a `class` to a `structure`. +Use `[AddMonoidHomClass F A B] [ContinuousMapClass F A B]` instead. -/ +structure ContinuousAddMonoidHomClass (A B : outParam Type*) [AddMonoid A] [AddMonoid B] [TopologicalSpace A] [TopologicalSpace B] [FunLike F A B] - extends AddMonoidHomClass F A B : Prop where - /-- Proof of the continuity of the map. -/ - map_continuous (f : F) : Continuous f + extends AddMonoidHomClass F A B, ContinuousMapClass F A B : Prop /-- `ContinuousMonoidHomClass F A B` states that `F` is a type of continuous monoid homomorphisms. -You should also extend this typeclass when you extend `ContinuousMonoidHom`. -/ --- Porting note: Changed A B to outParam to help synthesizing order -@[to_additive] -class ContinuousMonoidHomClass (A B : outParam Type*) [Monoid A] [Monoid B] +Deprecated and changed from a `class` to a `structure`. +Use `[MonoidHomClass F A B] [ContinuousMapClass F A B]` instead. -/ +@[to_additive (attr := deprecated (since := "2024-10-08"))] +structure ContinuousMonoidHomClass (A B : outParam Type*) [Monoid A] [Monoid B] [TopologicalSpace A] [TopologicalSpace B] [FunLike F A B] - extends MonoidHomClass F A B : Prop where - /-- Proof of the continuity of the map. -/ - map_continuous (f : F) : Continuous f + extends MonoidHomClass F A B, ContinuousMapClass F A B : Prop end @@ -82,18 +78,18 @@ add_decl_doc ContinuousMonoidHom.toMonoidHom /-- Reinterpret a `ContinuousAddMonoidHom` as an `AddMonoidHom`. -/ add_decl_doc ContinuousAddMonoidHom.toAddMonoidHom --- See note [lower instance priority] -@[to_additive] -instance (priority := 100) ContinuousMonoidHomClass.toContinuousMapClass - [FunLike F A B] [ContinuousMonoidHomClass F A B] : ContinuousMapClass F A B := - { ‹ContinuousMonoidHomClass F A B› with } +/-- Reinterpret a `ContinuousMonoidHom` as a `ContinuousMap`. -/ +add_decl_doc ContinuousMonoidHom.toContinuousMap + +/-- Reinterpret a `ContinuousAddMonoidHom` as a `ContinuousMap`. -/ +add_decl_doc ContinuousAddMonoidHom.toContinuousMap namespace ContinuousMonoidHom variable {A B C D E} @[to_additive] -instance funLike : FunLike (ContinuousMonoidHom A B) A B where +instance instFunLike : FunLike (ContinuousMonoidHom A B) A B where coe f := f.toFun coe_injective' f g h := by obtain ⟨⟨⟨ _ , _ ⟩, _⟩, _⟩ := f @@ -101,53 +97,61 @@ instance funLike : FunLike (ContinuousMonoidHom A B) A B where congr @[to_additive] -instance ContinuousMonoidHomClass : ContinuousMonoidHomClass (ContinuousMonoidHom A B) A B where +instance instMonoidHomClass : MonoidHomClass (ContinuousMonoidHom A B) A B where map_mul f := f.map_mul' map_one f := f.map_one' + +@[to_additive] +instance instContinuousMapClass : ContinuousMapClass (ContinuousMonoidHom A B) A B where map_continuous f := f.continuous_toFun @[to_additive (attr := ext)] theorem ext {f g : ContinuousMonoidHom A B} (h : ∀ x, f x = g x) : f = g := DFunLike.ext _ _ h -/-- Reinterpret a `ContinuousMonoidHom` as a `ContinuousMap`. -/ -@[to_additive "Reinterpret a `ContinuousAddMonoidHom` as a `ContinuousMap`."] -def toContinuousMap (f : ContinuousMonoidHom A B) : C(A, B) := - { f with } - @[to_additive] theorem toContinuousMap_injective : Injective (toContinuousMap : _ → C(A, B)) := fun f g h => ext <| by convert DFunLike.ext_iff.1 h --- Porting note: Removed simps because given definition is not a constructor application -/-- Construct a `ContinuousMonoidHom` from a `Continuous` `MonoidHom`. -/ -@[to_additive "Construct a `ContinuousAddMonoidHom` from a `Continuous` `AddMonoidHom`."] -def mk' (f : A →* B) (hf : Continuous f) : ContinuousMonoidHom A B := - { f with continuous_toFun := (hf : Continuous f.toFun)} +@[deprecated (since := "2024-10-08")] protected alias mk' := mk + +@[deprecated (since := "2024-10-08")] +protected alias _root_.ContinuousAddMonoidHom.mk' := ContinuousAddMonoidHom.mk + +set_option linter.existingAttributeWarning false in +attribute [to_additive existing] ContinuousMonoidHom.mk' /-- Composition of two continuous homomorphisms. -/ @[to_additive (attr := simps!) "Composition of two continuous homomorphisms."] def comp (g : ContinuousMonoidHom B C) (f : ContinuousMonoidHom A B) : ContinuousMonoidHom A C := - mk' (g.toMonoidHom.comp f.toMonoidHom) (g.continuous_toFun.comp f.continuous_toFun) + ⟨g.toMonoidHom.comp f.toMonoidHom, (map_continuous g).comp (map_continuous f)⟩ /-- Product of two continuous homomorphisms on the same space. -/ -@[to_additive (attr := simps!) "Product of two continuous homomorphisms on the same space."] +@[to_additive (attr := simps!) prod "Product of two continuous homomorphisms on the same space."] def prod (f : ContinuousMonoidHom A B) (g : ContinuousMonoidHom A C) : ContinuousMonoidHom A (B × C) := - mk' (f.toMonoidHom.prod g.toMonoidHom) (f.continuous_toFun.prod_mk g.continuous_toFun) + ⟨f.toMonoidHom.prod g.toMonoidHom, f.continuous_toFun.prod_mk g.continuous_toFun⟩ /-- Product of two continuous homomorphisms on different spaces. -/ -@[to_additive (attr := simps!) "Product of two continuous homomorphisms on different spaces."] -def prod_map (f : ContinuousMonoidHom A C) (g : ContinuousMonoidHom B D) : +@[to_additive (attr := simps!) prodMap + "Product of two continuous homomorphisms on different spaces."] +def prodMap (f : ContinuousMonoidHom A C) (g : ContinuousMonoidHom B D) : ContinuousMonoidHom (A × B) (C × D) := - mk' (f.toMonoidHom.prodMap g.toMonoidHom) (f.continuous_toFun.prod_map g.continuous_toFun) + ⟨f.toMonoidHom.prodMap g.toMonoidHom, f.continuous_toFun.prodMap g.continuous_toFun⟩ + +@[deprecated (since := "2024-10-05")] alias prod_map := prodMap +@[deprecated (since := "2024-10-05")] +alias _root_.ContinuousAddMonoidHom.sum_map := ContinuousAddMonoidHom.prodMap + +set_option linter.existingAttributeWarning false in +attribute [to_additive existing] prod_map variable (A B C D E) /-- The trivial continuous homomorphism. -/ @[to_additive (attr := simps!) "The trivial continuous homomorphism."] def one : ContinuousMonoidHom A B := - mk' 1 continuous_const + ⟨1, continuous_const⟩ @[to_additive] instance : Inhabited (ContinuousMonoidHom A B) := @@ -156,19 +160,19 @@ instance : Inhabited (ContinuousMonoidHom A B) := /-- The identity continuous homomorphism. -/ @[to_additive (attr := simps!) "The identity continuous homomorphism."] def id : ContinuousMonoidHom A A := - mk' (MonoidHom.id A) continuous_id + ⟨.id A, continuous_id⟩ /-- The continuous homomorphism given by projection onto the first factor. -/ @[to_additive (attr := simps!) "The continuous homomorphism given by projection onto the first factor."] def fst : ContinuousMonoidHom (A × B) A := - mk' (MonoidHom.fst A B) continuous_fst + ⟨MonoidHom.fst A B, continuous_fst⟩ /-- The continuous homomorphism given by projection onto the second factor. -/ @[to_additive (attr := simps!) "The continuous homomorphism given by projection onto the second factor."] def snd : ContinuousMonoidHom (A × B) B := - mk' (MonoidHom.snd A B) continuous_snd + ⟨MonoidHom.snd A B, continuous_snd⟩ /-- The continuous homomorphism given by inclusion of the first factor. -/ @[to_additive (attr := simps!) @@ -195,12 +199,12 @@ def swap : ContinuousMonoidHom (A × B) (B × A) := /-- The continuous homomorphism given by multiplication. -/ @[to_additive (attr := simps!) "The continuous homomorphism given by addition."] def mul : ContinuousMonoidHom (E × E) E := - mk' mulMonoidHom continuous_mul + ⟨mulMonoidHom, continuous_mul⟩ /-- The continuous homomorphism given by inversion. -/ @[to_additive (attr := simps!) "The continuous homomorphism given by negation."] def inv : ContinuousMonoidHom E E := - mk' invMonoidHom continuous_inv + ⟨invMonoidHom, continuous_inv⟩ variable {A B C D E} @@ -208,7 +212,7 @@ variable {A B C D E} @[to_additive (attr := simps!) "Coproduct of two continuous homomorphisms to the same space."] def coprod (f : ContinuousMonoidHom A E) (g : ContinuousMonoidHom B E) : ContinuousMonoidHom (A × B) E := - (mul E).comp (f.prod_map g) + (mul E).comp (f.prodMap g) @[to_additive] instance : CommGroup (ContinuousMonoidHom A E) where @@ -265,7 +269,7 @@ instance [T2Space B] : T2Space (ContinuousMonoidHom A B) := instance : TopologicalGroup (ContinuousMonoidHom A E) := let hi := inducing_toContinuousMap A E let hc := hi.continuous - { continuous_mul := hi.continuous_iff.mpr (continuous_mul.comp (Continuous.prod_map hc hc)) + { continuous_mul := hi.continuous_iff.mpr (continuous_mul.comp (Continuous.prodMap hc hc)) continuous_inv := hi.continuous_iff.mpr (continuous_inv.comp hc) } @[to_additive] @@ -280,7 +284,7 @@ theorem continuous_comp [LocallyCompactSpace B] : Continuous fun f : ContinuousMonoidHom A B × ContinuousMonoidHom B C => f.2.comp f.1 := (inducing_toContinuousMap A C).continuous_iff.2 <| ContinuousMap.continuous_comp'.comp - ((inducing_toContinuousMap A B).prod_map (inducing_toContinuousMap B C)).continuous + ((inducing_toContinuousMap A B).prodMap (inducing_toContinuousMap B C)).continuous @[to_additive] theorem continuous_comp_left (f : ContinuousMonoidHom A B) : diff --git a/Mathlib/Topology/Algebra/Field.lean b/Mathlib/Topology/Algebra/Field.lean index 0b7ccfdded133..c897f0bb8fa18 100644 --- a/Mathlib/Topology/Algebra/Field.lean +++ b/Mathlib/Topology/Algebra/Field.lean @@ -101,7 +101,7 @@ open Topology theorem IsLocalMin.inv {f : α → β} {a : α} (h1 : IsLocalMin f a) (h2 : ∀ᶠ z in 𝓝 a, 0 < f z) : IsLocalMax f⁻¹ a := by - filter_upwards [h1, h2] with z h3 h4 using(inv_le_inv h4 h2.self_of_nhds).mpr h3 + filter_upwards [h1, h2] with z h3 h4 using(inv_le_inv₀ h4 h2.self_of_nhds).mpr h3 end LocalExtr diff --git a/Mathlib/Topology/Algebra/Group/Basic.lean b/Mathlib/Topology/Algebra/Group/Basic.lean index 056e62ee57db1..49c268a901a0c 100644 --- a/Mathlib/Topology/Algebra/Group/Basic.lean +++ b/Mathlib/Topology/Algebra/Group/Basic.lean @@ -7,6 +7,7 @@ import Mathlib.GroupTheory.GroupAction.ConjAct import Mathlib.GroupTheory.GroupAction.Quotient import Mathlib.Topology.Algebra.Monoid import Mathlib.Topology.Algebra.Constructions +import Mathlib.Topology.Maps.OpenQuotient import Mathlib.Algebra.Order.Archimedean.Basic import Mathlib.GroupTheory.QuotientGroup.Basic @@ -535,7 +536,7 @@ end OrderedCommGroup @[to_additive] instance [TopologicalSpace H] [Group H] [TopologicalGroup H] : TopologicalGroup (G × H) where - continuous_inv := continuous_inv.prod_map continuous_inv + continuous_inv := continuous_inv.prodMap continuous_inv @[to_additive] instance Pi.topologicalGroup {C : β → Type*} [∀ b, TopologicalSpace (C b)] [∀ b, Group (C b)] @@ -862,16 +863,24 @@ instance [CompactSpace G] (N : Subgroup G) : CompactSpace (G ⧸ N) := theorem quotientMap_mk (N : Subgroup G) : QuotientMap (mk : G → G ⧸ N) := quotientMap_quot_mk -variable [TopologicalGroup G] (N : Subgroup G) +@[to_additive] +theorem continuous_mk {N : Subgroup G} : Continuous (mk : G → G ⧸ N) := + continuous_quot_mk + +section ContinuousMul + +variable [ContinuousMul G] {N : Subgroup G} + +@[to_additive] +theorem isOpenMap_coe : IsOpenMap ((↑) : G → G ⧸ N) := isOpenMap_quotient_mk'_mul @[to_additive] -theorem isOpenMap_coe : IsOpenMap ((↑) : G → G ⧸ N) := - isOpenMap_quotient_mk'_mul +theorem isOpenQuotientMap_mk : IsOpenQuotientMap (mk : G → G ⧸ N) := + MulAction.isOpenQuotientMap_quotientMk @[to_additive (attr := simp)] theorem dense_preimage_mk {s : Set (G ⧸ N)} : Dense ((↑) ⁻¹' s : Set G) ↔ Dense s := - letI := leftRel N -- `Dense.quotient` assumes `[Setoid G]` - ⟨fun h ↦ h.quotient.mono <| image_preimage_subset _ _, fun h ↦ h.preimage <| isOpenMap_coe _⟩ + isOpenQuotientMap_mk.dense_preimage_iff @[to_additive] theorem dense_image_mk {s : Set G} : @@ -879,27 +888,18 @@ theorem dense_image_mk {s : Set G} : rw [← dense_preimage_mk, preimage_image_mk_eq_mul] @[to_additive] -instance instTopologicalGroup [N.Normal] : TopologicalGroup (G ⧸ N) where - continuous_mul := by - have cont : Continuous (((↑) : G → G ⧸ N) ∘ fun p : G × G ↦ p.fst * p.snd) := - continuous_quot_mk.comp continuous_mul - have quot : QuotientMap fun p : G × G ↦ ((p.1 : G ⧸ N), (p.2 : G ⧸ N)) := by - apply IsOpenMap.to_quotientMap - · exact (QuotientGroup.isOpenMap_coe N).prod (QuotientGroup.isOpenMap_coe N) - · exact continuous_quot_mk.prod_map continuous_quot_mk - · exact (surjective_quot_mk _).prodMap (surjective_quot_mk _) - exact quot.continuous_iff.2 cont - continuous_inv := continuous_inv.quotient_map' _ +instance instContinuousSMul : ContinuousSMul G (G ⧸ N) where + continuous_smul := by + rw [← (IsOpenQuotientMap.id.prodMap isOpenQuotientMap_mk).continuous_comp_iff] + exact continuous_mk.comp continuous_mul -@[to_additive (attr := deprecated (since := "2024-08-05"))] -theorem _root_.topologicalGroup_quotient [N.Normal] : TopologicalGroup (G ⧸ N) := - instTopologicalGroup N +variable (N) /-- Neighborhoods in the quotient are precisely the map of neighborhoods in the prequotient. -/ @[to_additive "Neighborhoods in the quotient are precisely the map of neighborhoods in the prequotient."] theorem nhds_eq (x : G) : 𝓝 (x : G ⧸ N) = Filter.map (↑) (𝓝 x) := - le_antisymm ((QuotientGroup.isOpenMap_coe N).nhds_le x) continuous_quot_mk.continuousAt + (isOpenQuotientMap_mk.map_nhds_eq _).symm @[to_additive] instance instFirstCountableTopology [FirstCountableTopology G] : @@ -911,6 +911,21 @@ theorem nhds_one_isCountablyGenerated [FirstCountableTopology G] [N.Normal] : (𝓝 (1 : G ⧸ N)).IsCountablyGenerated := inferInstance +end ContinuousMul + +variable [TopologicalGroup G] (N : Subgroup G) + +@[to_additive] +instance instTopologicalGroup [N.Normal] : TopologicalGroup (G ⧸ N) where + continuous_mul := by + rw [← (isOpenQuotientMap_mk.prodMap isOpenQuotientMap_mk).continuous_comp_iff] + exact continuous_mk.comp continuous_mul + continuous_inv := continuous_inv.quotient_map' _ + +@[to_additive (attr := deprecated (since := "2024-08-05"))] +theorem _root_.topologicalGroup_quotient [N.Normal] : TopologicalGroup (G ⧸ N) := + instTopologicalGroup N + end QuotientGroup /-- A typeclass saying that `p : G × G ↦ p.1 - p.2` is a continuous function. This property @@ -1411,7 +1426,7 @@ theorem Subgroup.properlyDiscontinuousSMul_opposite_of_tendsto_cofinite (S : Sub (hS : Tendsto S.subtype cofinite (cocompact G)) : ProperlyDiscontinuousSMul S.op G := { finite_disjoint_inter_image := by intro K L hK hL - have : Continuous fun p : G × G => (p.1⁻¹, p.2) := continuous_inv.prod_map continuous_id + have : Continuous fun p : G × G => (p.1⁻¹, p.2) := continuous_inv.prodMap continuous_id have H : Set.Finite _ := hS ((hK.prod hL).image (continuous_mul.comp this)).compl_mem_cocompact simp only [preimage_compl, compl_compl, coeSubtype, comp_apply] at H @@ -1612,7 +1627,7 @@ instance [LocallyCompactSpace G] (N : Subgroup G) : LocallyCompactSpace (G ⧸ N obtain ⟨y, rfl⟩ : ∃ y, π y = x := Quot.exists_rep x have : π ⁻¹' n ∈ 𝓝 y := preimage_nhds_coinduced hn rcases local_compact_nhds this with ⟨s, s_mem, hs, s_comp⟩ - exact ⟨π '' s, (QuotientGroup.isOpenMap_coe N).image_mem_nhds s_mem, mapsTo'.mp hs, + exact ⟨π '' s, QuotientGroup.isOpenMap_coe.image_mem_nhds s_mem, mapsTo'.mp hs, s_comp.image C⟩ end diff --git a/Mathlib/Topology/Algebra/Group/Compact.lean b/Mathlib/Topology/Algebra/Group/Compact.lean index 57b0155e2e6a8..b479c867ca91f 100644 --- a/Mathlib/Topology/Algebra/Group/Compact.lean +++ b/Mathlib/Topology/Algebra/Group/Compact.lean @@ -4,24 +4,18 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Johannes Hölzl, Mario Carneiro, Patrick Massot -/ import Mathlib.Topology.Algebra.Group.Basic -import Mathlib.Topology.CompactOpen import Mathlib.Topology.Sets.Compacts /-! # Additional results on topological groups -Two results on topological groups that have been separated out as they require more substantial -imports developing either positive compacts or the compact open topology. - +A result on topological groups that has been separated out +as it requires more substantial imports developing positive compacts. -/ -universe u v w x - -variable {α : Type u} {β : Type v} {G : Type w} {H : Type x} -section - -variable [TopologicalSpace G] [Group G] [TopologicalGroup G] +universe u +variable {G : Type u} [TopologicalSpace G] [Group G] [TopologicalGroup G] /-- Every topological group in which there exists a compact set with nonempty interior is locally compact. -/ @@ -32,21 +26,3 @@ theorem TopologicalSpace.PositiveCompacts.locallyCompactSpace_of_group (K : PositiveCompacts G) : LocallyCompactSpace G := let ⟨_x, hx⟩ := K.interior_nonempty K.isCompact.locallyCompactSpace_of_mem_nhds_of_group (mem_interior_iff_mem_nhds.1 hx) - -end - -section Quotient - -variable [Group G] [TopologicalSpace G] [TopologicalGroup G] {Γ : Subgroup G} - -@[to_additive] -instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where - continuous_smul := by - let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2 - change Continuous F - have H : Continuous (F ∘ fun p : G × G => (p.1, QuotientGroup.mk p.2)) := by - change Continuous fun p : G × G => QuotientGroup.mk (p.1 * p.2) - exact continuous_coinduced_rng.comp continuous_mul - exact QuotientMap.continuous_lift_prod_right quotientMap_quotient_mk' H - -end Quotient diff --git a/Mathlib/Topology/Algebra/GroupCompletion.lean b/Mathlib/Topology/Algebra/GroupCompletion.lean index 234486fbb1753..5935b46b343e8 100644 --- a/Mathlib/Topology/Algebra/GroupCompletion.lean +++ b/Mathlib/Topology/Algebra/GroupCompletion.lean @@ -136,8 +136,8 @@ instance : SubNegMonoid (Completion α) := zsmul_succ' := fun n a ↦ Completion.induction_on a (isClosed_eq continuous_map <| continuous_map₂ continuous_map continuous_id) fun a ↦ - show Int.ofNat n.succ • (a : Completion α) = _ by - rw [← coe_smul, show Int.ofNat n.succ • a = Int.ofNat n • a + a from + show (n.succ : ℤ) • (a : Completion α) = _ by + rw [← coe_smul, show (n.succ : ℤ) • a = (n : ℤ) • a + a from SubNegMonoid.zsmul_succ' n a, coe_add, coe_smul] zsmul_neg' := fun n a ↦ Completion.induction_on a @@ -181,8 +181,8 @@ theorem continuous_toCompl : Continuous (toCompl : α → Completion α) := variable (α) -theorem denseInducing_toCompl : DenseInducing (toCompl : α → Completion α) := - denseInducing_coe +theorem isDenseInducing_toCompl : IsDenseInducing (toCompl : α → Completion α) := + isDenseInducing_coe variable {α} diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean index c68372a5f2ce0..b47e95b56f4ad 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Constructions.lean @@ -146,7 +146,35 @@ end ContinuousMul section CompleteSpace -variable [CommGroup α] [UniformSpace α] [UniformGroup α] [CompleteSpace α] +variable [CommGroup α] [UniformSpace α] [UniformGroup α] + +@[to_additive] +theorem HasProd.of_sigma {γ : β → Type*} {f : (Σ b : β, γ b) → α} {g : β → α} {a : α} + (hf : ∀ b, HasProd (fun c ↦ f ⟨b, c⟩) (g b)) (hg : HasProd g a) + (h : CauchySeq (fun (s : Finset (Σ b : β, γ b)) ↦ ∏ i ∈ s, f i)) : + HasProd f a := by + classical + apply le_nhds_of_cauchy_adhp h + simp only [← mapClusterPt_def, mapClusterPt_iff, frequently_atTop, ge_iff_le, le_eq_subset] + intro u hu s + rcases mem_nhds_iff.1 hu with ⟨v, vu, v_open, hv⟩ + obtain ⟨t0, st0, ht0⟩ : ∃ t0, ∏ i ∈ t0, g i ∈ v ∧ s.image Sigma.fst ⊆ t0 := by + have A : ∀ᶠ t0 in (atTop : Filter (Finset β)), ∏ i ∈ t0, g i ∈ v := hg (v_open.mem_nhds hv) + exact (A.and (Ici_mem_atTop _)).exists + have L : Tendsto (fun t : Finset (Σb, γ b) ↦ ∏ p ∈ t.filter fun p ↦ p.1 ∈ t0, f p) atTop + (𝓝 <| ∏ b ∈ t0, g b) := by + simp only [← sigma_preimage_mk, prod_sigma] + refine tendsto_finset_prod _ fun b _ ↦ ?_ + change + Tendsto (fun t ↦ (fun t ↦ ∏ s ∈ t, f ⟨b, s⟩) (preimage t (Sigma.mk b) _)) atTop (𝓝 (g b)) + exact (hf b).comp (tendsto_finset_preimage_atTop_atTop (sigma_mk_injective)) + have : ∃ t, ∏ p ∈ t.filter (fun p ↦ p.1 ∈ t0), f p ∈ v ∧ s ⊆ t := + ((Tendsto.eventually_mem L (v_open.mem_nhds st0)).and (Ici_mem_atTop _)).exists + obtain ⟨t, tv, st⟩ := this + refine ⟨t.filter (fun p ↦ p.1 ∈ t0), fun x hx ↦ ?_, vu tv⟩ + simpa only [mem_filter, st hx, true_and] using ht0 (mem_image_of_mem Sigma.fst hx) + +variable [CompleteSpace α] @[to_additive] theorem Multipliable.sigma_factor {γ : β → Type*} {f : (Σb : β, γ b) → α} diff --git a/Mathlib/Topology/Algebra/InfiniteSum/GroupCompletion.lean b/Mathlib/Topology/Algebra/InfiniteSum/GroupCompletion.lean index 52b2b087f1a48..078edbe10ffe4 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/GroupCompletion.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/GroupCompletion.lean @@ -17,13 +17,13 @@ variable {α β : Type*} [AddCommGroup α] [UniformSpace α] [UniformAddGroup α /-- A function `f` has a sum in an uniform additive group `α` if and only if it has that sum in the completion of `α`. -/ theorem hasSum_iff_hasSum_compl (f : β → α) (a : α) : - HasSum (toCompl ∘ f) a ↔ HasSum f a := (denseInducing_toCompl α).hasSum_iff f a + HasSum (toCompl ∘ f) a ↔ HasSum f a := (isDenseInducing_toCompl α).hasSum_iff f a /-- A function `f` is summable in a uniform additive group `α` if and only if it is summable in `Completion α` and its sum in `Completion α` lies in the range of `toCompl : α →+ Completion α`. -/ theorem summable_iff_summable_compl_and_tsum_mem (f : β → α) : Summable f ↔ Summable (toCompl ∘ f) ∧ ∑' i, toCompl (f i) ∈ Set.range toCompl := - (denseInducing_toCompl α).summable_iff_tsum_comp_mem_range f + (isDenseInducing_toCompl α).summable_iff_tsum_comp_mem_range f /-- A function `f` is summable in a uniform additive group `α` if and only if the net of its partial sums is Cauchy and its sum in `Completion α` lies in the range of `toCompl : α →+ Completion α`. diff --git a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean index 53773dace6081..88fad0d581136 100644 --- a/Mathlib/Topology/Algebra/InfiniteSum/Order.lean +++ b/Mathlib/Topology/Algebra/InfiniteSum/Order.lean @@ -40,7 +40,7 @@ variable [OrderedCommMonoid α] [TopologicalSpace α] [OrderClosedTopology α] { theorem hasProd_le (h : ∀ i, f i ≤ g i) (hf : HasProd f a₁) (hg : HasProd g a₂) : a₁ ≤ a₂ := le_of_tendsto_of_tendsto' hf hg fun _ ↦ prod_le_prod' fun i _ ↦ h i -@[to_additive (attr := mono)] +@[to_additive] theorem hasProd_mono (hf : HasProd f a₁) (hg : HasProd g a₂) (h : f ≤ g) : a₁ ≤ a₂ := hasProd_le h hf hg diff --git a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean index 0391d939b2f46..1b43517bdbae1 100644 --- a/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Alternating/Basic.lean @@ -447,9 +447,8 @@ end Semiring section Ring -variable {R M M' N N' ι : Type*} [Ring R] [AddCommGroup M] [Module R M] [TopologicalSpace M] - [AddCommGroup M'] [Module R M'] [TopologicalSpace M'] [AddCommGroup N] [Module R N] - [TopologicalSpace N] [AddCommGroup N'] [Module R N'] [TopologicalSpace N'] {n : ℕ} +variable {R M N ι : Type*} [Ring R] [AddCommGroup M] [Module R M] [TopologicalSpace M] + [AddCommGroup N] [Module R N] [TopologicalSpace N] (f g : M [⋀^ι]→L[R] N) @[simp] @@ -489,10 +488,9 @@ end Ring section CommSemiring -variable {R M M' N N' ι : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] - [TopologicalSpace M] [AddCommMonoid M'] [Module R M'] [TopologicalSpace M'] [AddCommMonoid N] - [Module R N] [TopologicalSpace N] [AddCommMonoid N'] [Module R N'] [TopologicalSpace N'] {n : ℕ} - (f g : M [⋀^ι]→L[R] N) +variable {R M N ι : Type*} [CommSemiring R] [AddCommMonoid M] [Module R M] + [TopologicalSpace M] [AddCommMonoid N] [Module R N] [TopologicalSpace N] + (f : M [⋀^ι]→L[R] N) theorem map_piecewise_smul [DecidableEq ι] (c : ι → R) (m : ι → M) (s : Finset ι) : f (s.piecewise (fun i => c i • m i) m) = (∏ i ∈ s, c i) • f m := @@ -561,7 +559,7 @@ end Module section SMulRight -variable {R A M N ι : Type*} [CommSemiring R] [AddCommMonoid M] [AddCommMonoid N] [Module R M] +variable {R M N ι : Type*} [CommSemiring R] [AddCommMonoid M] [AddCommMonoid N] [Module R M] [Module R N] [TopologicalSpace R] [TopologicalSpace M] [TopologicalSpace N] [ContinuousSMul R N] (f : M [⋀^ι]→L[R] R) (z : N) @@ -603,7 +601,7 @@ namespace ContinuousMultilinearMap variable {R M N ι : Type*} [Semiring R] [AddCommMonoid M] [Module R M] [TopologicalSpace M] [AddCommGroup N] [Module R N] [TopologicalSpace N] [TopologicalAddGroup N] [Fintype ι] - [DecidableEq ι] (f g : ContinuousMultilinearMap R (fun _ : ι => M) N) + [DecidableEq ι] (f : ContinuousMultilinearMap R (fun _ : ι => M) N) /-- Alternatization of a continuous multilinear map. -/ @[simps (config := .lemmasOnly) apply_toContinuousMultilinearMap] diff --git a/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean b/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean index 988d2a453721f..32efbbd5a39c7 100644 --- a/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean +++ b/Mathlib/Topology/Algebra/Module/Alternating/Topology.lean @@ -24,6 +24,22 @@ namespace ContinuousAlternatingMap variable {𝕜 E F ι : Type*} [NormedField 𝕜] [AddCommGroup E] [Module 𝕜 E] [TopologicalSpace E] [AddCommGroup F] [Module 𝕜 F] +section IsClosedRange + +variable [TopologicalSpace F] [TopologicalAddGroup F] + +instance instTopologicalSpace : TopologicalSpace (E [⋀^ι]→L[𝕜] F) := + .induced toContinuousMultilinearMap inferInstance + +lemma isClosed_range_toContinuousMultilinearMap [ContinuousSMul 𝕜 E] [T2Space F] : + IsClosed (Set.range (toContinuousMultilinearMap : (E [⋀^ι]→L[𝕜] F) → + ContinuousMultilinearMap 𝕜 (fun _ : ι ↦ E) F)) := by + simp only [range_toContinuousMultilinearMap, setOf_forall] + repeat refine isClosed_iInter fun _ ↦ ?_ + exact isClosed_singleton.preimage (ContinuousMultilinearMap.continuous_eval_const _) + +end IsClosedRange + section UniformAddGroup variable [UniformSpace F] [UniformAddGroup F] @@ -31,14 +47,17 @@ variable [UniformSpace F] [UniformAddGroup F] instance instUniformSpace : UniformSpace (E [⋀^ι]→L[𝕜] F) := .comap toContinuousMultilinearMap inferInstance -lemma uniformEmbedding_toContinuousMultilinearMap : - UniformEmbedding (toContinuousMultilinearMap : (E [⋀^ι]→L[𝕜] F) → _) where +lemma isUniformEmbedding_toContinuousMultilinearMap : + IsUniformEmbedding (toContinuousMultilinearMap : (E [⋀^ι]→L[𝕜] F) → _) where inj := toContinuousMultilinearMap_injective comap_uniformity := rfl +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toContinuousMultilinearMap := isUniformEmbedding_toContinuousMultilinearMap + lemma uniformContinuous_toContinuousMultilinearMap : UniformContinuous (toContinuousMultilinearMap : (E [⋀^ι]→L[𝕜] F) → _) := - uniformEmbedding_toContinuousMultilinearMap.uniformContinuous + isUniformEmbedding_toContinuousMultilinearMap.uniformContinuous theorem uniformContinuous_coe_fun [ContinuousSMul 𝕜 E] : UniformContinuous (DFunLike.coe : (E [⋀^ι]→L[𝕜] F) → (ι → E) → F) := @@ -50,13 +69,13 @@ theorem uniformContinuous_eval_const [ContinuousSMul 𝕜 E] (x : ι → E) : uniformContinuous_pi.1 uniformContinuous_coe_fun x instance instUniformAddGroup : UniformAddGroup (E [⋀^ι]→L[𝕜] F) := - uniformEmbedding_toContinuousMultilinearMap.uniformAddGroup + isUniformEmbedding_toContinuousMultilinearMap.uniformAddGroup (toContinuousMultilinearMapLinear (R := ℕ)) instance instUniformContinuousConstSMul {M : Type*} [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜 M F] [ContinuousConstSMul M F] : UniformContinuousConstSMul M (E [⋀^ι]→L[𝕜] F) := - uniformEmbedding_toContinuousMultilinearMap.uniformContinuousConstSMul fun _ _ ↦ rfl + isUniformEmbedding_toContinuousMultilinearMap.uniformContinuousConstSMul fun _ _ ↦ rfl section CompleteSpace @@ -67,11 +86,8 @@ theorem completeSpace (h : RestrictGenTopology {s : Set (ι → E) | IsVonNBound CompleteSpace (E [⋀^ι]→L[𝕜] F) := by have := ContinuousMultilinearMap.completeSpace (F := F) h rw [completeSpace_iff_isComplete_range - uniformEmbedding_toContinuousMultilinearMap.toUniformInducing, range_toContinuousMultilinearMap] - simp only [setOf_forall] - apply IsClosed.isComplete - repeat refine isClosed_iInter fun _ ↦ ?_ - exact isClosed_singleton.preimage (ContinuousMultilinearMap.continuous_eval_const _) + isUniformEmbedding_toContinuousMultilinearMap.isUniformInducing] + apply isClosed_range_toContinuousMultilinearMap.isComplete instance instCompleteSpace [TopologicalAddGroup E] [SequentialSpace (ι → E)] : CompleteSpace (E [⋀^ι]→L[𝕜] F) := @@ -84,15 +100,18 @@ section RestrictScalars variable (𝕜' : Type*) [NontriviallyNormedField 𝕜'] [NormedAlgebra 𝕜' 𝕜] [Module 𝕜' E] [IsScalarTower 𝕜' 𝕜 E] [Module 𝕜' F] [IsScalarTower 𝕜' 𝕜 F] [ContinuousSMul 𝕜 E] -theorem uniformEmbedding_restrictScalars : - UniformEmbedding (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := by - rw [← uniformEmbedding_toContinuousMultilinearMap.of_comp_iff] - exact (ContinuousMultilinearMap.uniformEmbedding_restrictScalars 𝕜').comp - uniformEmbedding_toContinuousMultilinearMap +theorem isUniformEmbedding_restrictScalars : + IsUniformEmbedding (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := by + rw [← isUniformEmbedding_toContinuousMultilinearMap.of_comp_iff] + exact (ContinuousMultilinearMap.isUniformEmbedding_restrictScalars 𝕜').comp + isUniformEmbedding_toContinuousMultilinearMap + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_restrictScalars := isUniformEmbedding_restrictScalars theorem uniformContinuous_restrictScalars : UniformContinuous (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := - (uniformEmbedding_restrictScalars 𝕜').uniformContinuous + (isUniformEmbedding_restrictScalars 𝕜').uniformContinuous end RestrictScalars @@ -100,14 +119,11 @@ end UniformAddGroup variable [TopologicalSpace F] [TopologicalAddGroup F] -instance instTopologicalSpace : TopologicalSpace (E [⋀^ι]→L[𝕜] F) := - .induced toContinuousMultilinearMap inferInstance - lemma embedding_toContinuousMultilinearMap : Embedding (toContinuousMultilinearMap : (E [⋀^ι]→L[𝕜] F → _)) := letI := TopologicalAddGroup.toUniformSpace F haveI := comm_topologicalAddGroup_is_uniform (G := F) - uniformEmbedding_toContinuousMultilinearMap.embedding + isUniformEmbedding_toContinuousMultilinearMap.embedding @[continuity, fun_prop] lemma continuous_toContinuousMultilinearMap : @@ -138,6 +154,11 @@ theorem hasBasis_nhds_zero : variable [ContinuousSMul 𝕜 E] +lemma closedEmbedding_toContinuousMultilinearMap [T2Space F] : + ClosedEmbedding (toContinuousMultilinearMap : + (E [⋀^ι]→L[𝕜] F) → ContinuousMultilinearMap 𝕜 (fun _ : ι ↦ E) F) := + ⟨embedding_toContinuousMultilinearMap, isClosed_range_toContinuousMultilinearMap⟩ + @[continuity, fun_prop] theorem continuous_eval_const (x : ι → E) : Continuous fun p : E [⋀^ι]→L[𝕜] F ↦ p x := @@ -164,7 +185,7 @@ theorem embedding_restrictScalars : Embedding (restrictScalars 𝕜' : E [⋀^ι]→L[𝕜] F → E [⋀^ι]→L[𝕜'] F) := letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform - (uniformEmbedding_restrictScalars _).embedding + (isUniformEmbedding_restrictScalars _).embedding @[continuity, fun_prop] theorem continuous_restrictScalars : diff --git a/Mathlib/Topology/Algebra/Module/Basic.lean b/Mathlib/Topology/Algebra/Module/Basic.lean index ce5bbbc74d460..a1479380641d5 100644 --- a/Mathlib/Topology/Algebra/Module/Basic.lean +++ b/Mathlib/Topology/Algebra/Module/Basic.lean @@ -7,7 +7,6 @@ Authors: Jan-David Salchow, Sébastien Gouëzel, Jean Lo, Yury Kudryashov, Fréd import Mathlib.Topology.Algebra.Ring.Basic import Mathlib.Topology.Algebra.MulAction import Mathlib.Topology.Algebra.UniformGroup -import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Topology.UniformSpace.UniformEmbedding import Mathlib.Algebra.Algebra.Defs import Mathlib.LinearAlgebra.Projection @@ -1817,8 +1816,8 @@ theorem trans_toLinearEquiv (e₁ : M₁ ≃SL[σ₁₂] M₂) (e₂ : M₂ ≃S def prod [Module R₁ M₂] [Module R₁ M₃] [Module R₁ M₄] (e : M₁ ≃L[R₁] M₂) (e' : M₃ ≃L[R₁] M₄) : (M₁ × M₃) ≃L[R₁] M₂ × M₄ := { e.toLinearEquiv.prod e'.toLinearEquiv with - continuous_toFun := e.continuous_toFun.prod_map e'.continuous_toFun - continuous_invFun := e.continuous_invFun.prod_map e'.continuous_invFun } + continuous_toFun := e.continuous_toFun.prodMap e'.continuous_toFun + continuous_invFun := e.continuous_invFun.prodMap e'.continuous_invFun } @[simp, norm_cast] theorem prod_apply [Module R₁ M₂] [Module R₁ M₃] [Module R₁ M₄] (e : M₁ ≃L[R₁] M₂) @@ -1942,22 +1941,27 @@ protected theorem preimage_symm_preimage (e : M₁ ≃SL[σ₁₂] M₂) (s : Se e ⁻¹' (e.symm ⁻¹' s) = s := e.symm.symm_preimage_preimage s -protected theorem uniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] [UniformSpace E₂] +lemma isUniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] [UniformSpace E₂] [AddCommGroup E₁] [AddCommGroup E₂] [Module R₁ E₁] [Module R₂ E₂] [UniformAddGroup E₁] - [UniformAddGroup E₂] (e : E₁ ≃SL[σ₁₂] E₂) : UniformEmbedding e := - e.toLinearEquiv.toEquiv.uniformEmbedding e.toContinuousLinearMap.uniformContinuous + [UniformAddGroup E₂] (e : E₁ ≃SL[σ₁₂] E₂) : IsUniformEmbedding e := + e.toLinearEquiv.toEquiv.isUniformEmbedding e.toContinuousLinearMap.uniformContinuous e.symm.toContinuousLinearMap.uniformContinuous -protected theorem _root_.LinearEquiv.uniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding + +protected theorem _root_.LinearEquiv.isUniformEmbedding {E₁ E₂ : Type*} [UniformSpace E₁] [UniformSpace E₂] [AddCommGroup E₁] [AddCommGroup E₂] [Module R₁ E₁] [Module R₂ E₂] [UniformAddGroup E₁] [UniformAddGroup E₂] (e : E₁ ≃ₛₗ[σ₁₂] E₂) - (h₁ : Continuous e) (h₂ : Continuous e.symm) : UniformEmbedding e := - ContinuousLinearEquiv.uniformEmbedding + (h₁ : Continuous e) (h₂ : Continuous e.symm) : IsUniformEmbedding e := + ContinuousLinearEquiv.isUniformEmbedding ({ e with continuous_toFun := h₁ continuous_invFun := h₂ } : E₁ ≃SL[σ₁₂] E₂) +@[deprecated (since := "2024-10-01")] +alias _root_.LinearEquiv.uniformEmbedding := _root_.LinearEquiv.isUniformEmbedding + /-- Create a `ContinuousLinearEquiv` from two `ContinuousLinearMap`s that are inverse of each other. -/ def equivOfInverse (f₁ : M₁ →SL[σ₁₂] M₂) (f₂ : M₂ →SL[σ₂₁] M₁) (h₁ : Function.LeftInverse f₂ f₁) @@ -2375,21 +2379,20 @@ variable {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [TopologicalSpace instance _root_.QuotientModule.Quotient.topologicalSpace : TopologicalSpace (M ⧸ S) := inferInstanceAs (TopologicalSpace (Quotient S.quotientRel)) -theorem isOpenMap_mkQ [TopologicalAddGroup M] : IsOpenMap S.mkQ := - QuotientAddGroup.isOpenMap_coe S.toAddSubgroup +theorem isOpenMap_mkQ [ContinuousAdd M] : IsOpenMap S.mkQ := + QuotientAddGroup.isOpenMap_coe + +theorem isOpenQuotientMap_mkQ [ContinuousAdd M] : IsOpenQuotientMap S.mkQ := + QuotientAddGroup.isOpenQuotientMap_mk instance topologicalAddGroup_quotient [TopologicalAddGroup M] : TopologicalAddGroup (M ⧸ S) := inferInstanceAs <| TopologicalAddGroup (M ⧸ S.toAddSubgroup) instance continuousSMul_quotient [TopologicalSpace R] [TopologicalAddGroup M] [ContinuousSMul R M] : - ContinuousSMul R (M ⧸ S) := by - constructor - have quot : QuotientMap fun au : R × M => (au.1, S.mkQ au.2) := - IsOpenMap.to_quotientMap (IsOpenMap.id.prod S.isOpenMap_mkQ) - (continuous_id.prod_map continuous_quot_mk) - (Function.surjective_id.prodMap <| surjective_quot_mk _) - rw [quot.continuous_iff] - exact continuous_quot_mk.comp continuous_smul + ContinuousSMul R (M ⧸ S) where + continuous_smul := by + rw [← (IsOpenQuotientMap.id.prodMap S.isOpenQuotientMap_mkQ).continuous_comp_iff] + exact continuous_quot_mk.comp continuous_smul instance t3_quotient_of_isClosed [TopologicalAddGroup M] [IsClosed (S : Set M)] : T3Space (M ⧸ S) := diff --git a/Mathlib/Topology/Algebra/Module/Cardinality.lean b/Mathlib/Topology/Algebra/Module/Cardinality.lean index c45fb8205558f..b5c7c62b830cd 100644 --- a/Mathlib/Topology/Algebra/Module/Cardinality.lean +++ b/Mathlib/Topology/Algebra/Module/Cardinality.lean @@ -77,7 +77,7 @@ lemma cardinal_eq_of_mem_nhds_zero simp_rw [← inv_pow] apply tendsto_pow_atTop_nhds_zero_of_norm_lt_one rw [norm_inv] - exact inv_lt_one hc + exact inv_lt_one_of_one_lt₀ hc exact Tendsto.smul_const this x rw [zero_smul] at this filter_upwards [this hs] with n (hn : (c ^ n)⁻¹ • x ∈ s) diff --git a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean index aa4aeffcdfcb1..39d280cac3ba7 100644 --- a/Mathlib/Topology/Algebra/Module/CharacterSpace.lean +++ b/Mathlib/Topology/Algebra/Module/CharacterSpace.lean @@ -5,7 +5,7 @@ Authors: Frédéric Dupuis -/ import Mathlib.Topology.Algebra.Module.WeakDual import Mathlib.Algebra.Algebra.Spectrum -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Data.Set.Lattice /-! diff --git a/Mathlib/Topology/Algebra/Module/FiniteDimension.lean b/Mathlib/Topology/Algebra/Module/FiniteDimension.lean index 8b1c1ca19d66a..2cf817161d306 100644 --- a/Mathlib/Topology/Algebra/Module/FiniteDimension.lean +++ b/Mathlib/Topology/Algebra/Module/FiniteDimension.lean @@ -47,7 +47,7 @@ universe u v w x noncomputable section -open Set FiniteDimensional TopologicalSpace Filter +open Filter Module Set TopologicalSpace section Field @@ -106,7 +106,7 @@ theorem unique_topology_of_t2 {t : TopologicalSpace 𝕜} (h₁ : @TopologicalAd -- For that, we use that `𝓑` is balanced : since `‖ξ₀‖ < ε < ‖ξ‖`, we have `‖ξ₀ / ξ‖ ≤ 1`, -- hence `ξ₀ = (ξ₀ / ξ) • ξ ∈ 𝓑` because `ξ ∈ 𝓑`. refine (balancedCore_balanced _).smul_mem ?_ hξ - rw [norm_mul, norm_inv, mul_inv_le_iff (norm_pos_iff.mpr hξ0), mul_one] + rw [norm_mul, norm_inv, mul_inv_le_iff₀ (norm_pos_iff.mpr hξ0), one_mul] exact (hξ₀ε.trans h).le · -- Finally, to show `𝓣₀ ≤ 𝓣`, we simply argue that `id = (fun x ↦ x • 1)` is continuous from -- `(𝕜, 𝓣₀)` to `(𝕜, 𝓣)` because `(•) : (𝕜, 𝓣₀) × (𝕜, 𝓣) → (𝕜, 𝓣)` is continuous. @@ -197,22 +197,22 @@ private theorem continuous_equivFun_basis_aux [T2Space E] {ι : Type v} [Fintype induction' hn : Fintype.card ι with n IH generalizing ι E · rw [Fintype.card_eq_zero_iff] at hn exact continuous_of_const fun x y => funext hn.elim - · haveI : FiniteDimensional 𝕜 E := of_fintype_basis ξ + · haveI : FiniteDimensional 𝕜 E := .of_fintype_basis ξ -- first step: thanks to the induction hypothesis, any n-dimensional subspace is equivalent -- to a standard space of dimension n, hence it is complete and therefore closed. have H₁ : ∀ s : Submodule 𝕜 E, finrank 𝕜 s = n → IsClosed (s : Set E) := by intro s s_dim letI : UniformAddGroup s := s.toAddSubgroup.uniformAddGroup let b := Basis.ofVectorSpace 𝕜 s - have U : UniformEmbedding b.equivFun.symm.toEquiv := by + have U : IsUniformEmbedding b.equivFun.symm.toEquiv := by have : Fintype.card (Basis.ofVectorSpaceIndex 𝕜 s) = n := by rw [← s_dim] exact (finrank_eq_card_basis b).symm have : Continuous b.equivFun := IH b this exact - b.equivFun.symm.uniformEmbedding b.equivFun.symm.toLinearMap.continuous_on_pi this + b.equivFun.symm.isUniformEmbedding b.equivFun.symm.toLinearMap.continuous_on_pi this have : IsComplete (s : Set E) := - completeSpace_coe_iff_isComplete.1 ((completeSpace_congr U).1 (by infer_instance)) + completeSpace_coe_iff_isComplete.1 ((completeSpace_congr U).1 inferInstance) exact this.isClosed -- second step: any linear form is continuous, as its kernel is closed by the first step have H₂ : ∀ f : E →ₗ[𝕜] 𝕜, Continuous f := by @@ -264,7 +264,7 @@ continuous (see `LinearMap.continuous_of_finiteDimensional`), which in turn impl norms are equivalent in finite dimensions. -/ theorem continuous_equivFun_basis [T2Space E] {ι : Type*} [Finite ι] (ξ : Basis ι 𝕜 E) : Continuous ξ.equivFun := - haveI : FiniteDimensional 𝕜 E := of_fintype_basis ξ + haveI : FiniteDimensional 𝕜 E := .of_fintype_basis ξ ξ.equivFun.toLinearMap.continuous_of_finiteDimensional namespace LinearMap @@ -490,8 +490,8 @@ variable (𝕜 E : Type*) [NontriviallyNormedField 𝕜] include 𝕜 in theorem FiniteDimensional.complete [FiniteDimensional 𝕜 E] : CompleteSpace E := by set e := ContinuousLinearEquiv.ofFinrankEq (@finrank_fin_fun 𝕜 _ _ (finrank 𝕜 E)).symm - have : UniformEmbedding e.toLinearEquiv.toEquiv.symm := e.symm.uniformEmbedding - exact (completeSpace_congr this).1 (by infer_instance) + have : IsUniformEmbedding e.toEquiv.symm := e.symm.isUniformEmbedding + exact (completeSpace_congr this).1 inferInstance variable {𝕜 E} diff --git a/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean b/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean index a403ef7dca6bd..baf4b78201f9a 100644 --- a/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean +++ b/Mathlib/Topology/Algebra/Module/Multilinear/Topology.lean @@ -65,18 +65,21 @@ section UniformAddGroup variable [UniformSpace F] [UniformAddGroup F] -lemma uniformEmbedding_toUniformOnFun : - UniformEmbedding (toUniformOnFun : ContinuousMultilinearMap 𝕜 E F → _) where +lemma isUniformEmbedding_toUniformOnFun : + IsUniformEmbedding (toUniformOnFun : ContinuousMultilinearMap 𝕜 E F → _) where inj := DFunLike.coe_injective comap_uniformity := rfl +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toUniformOnFun := isUniformEmbedding_toUniformOnFun + lemma embedding_toUniformOnFun : Embedding (toUniformOnFun : ContinuousMultilinearMap 𝕜 E F → _) := - uniformEmbedding_toUniformOnFun.embedding + isUniformEmbedding_toUniformOnFun.embedding theorem uniformContinuous_coe_fun [∀ i, ContinuousSMul 𝕜 (E i)] : UniformContinuous (DFunLike.coe : ContinuousMultilinearMap 𝕜 E F → (Π i, E i) → F) := (UniformOnFun.uniformContinuous_toFun isVonNBounded_covers).comp - uniformEmbedding_toUniformOnFun.uniformContinuous + isUniformEmbedding_toUniformOnFun.uniformContinuous theorem uniformContinuous_eval_const [∀ i, ContinuousSMul 𝕜 (E i)] (x : Π i, E i) : UniformContinuous fun f : ContinuousMultilinearMap 𝕜 E F ↦ f x := @@ -85,13 +88,13 @@ theorem uniformContinuous_eval_const [∀ i, ContinuousSMul 𝕜 (E i)] (x : Π instance instUniformAddGroup : UniformAddGroup (ContinuousMultilinearMap 𝕜 E F) := let φ : ContinuousMultilinearMap 𝕜 E F →+ (Π i, E i) →ᵤ[{s | IsVonNBounded 𝕜 s}] F := { toFun := toUniformOnFun, map_add' := fun _ _ ↦ rfl, map_zero' := rfl } - uniformEmbedding_toUniformOnFun.uniformAddGroup φ + isUniformEmbedding_toUniformOnFun.uniformAddGroup φ instance instUniformContinuousConstSMul {M : Type*} [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜 M F] [ContinuousConstSMul M F] : UniformContinuousConstSMul M (ContinuousMultilinearMap 𝕜 E F) := haveI := uniformContinuousConstSMul_of_continuousConstSMul M F - uniformEmbedding_toUniformOnFun.uniformContinuousConstSMul fun _ _ ↦ rfl + isUniformEmbedding_toUniformOnFun.uniformContinuousConstSMul fun _ _ ↦ rfl section CompleteSpace @@ -104,7 +107,7 @@ theorem completeSpace (h : RestrictGenTopology {s : Set (Π i, E i) | IsVonNBoun have H : ∀ {m : Π i, E i}, Continuous fun f : (Π i, E i) →ᵤ[{s | IsVonNBounded 𝕜 s}] F ↦ toFun _ f m := (uniformContinuous_eval (isVonNBounded_covers) _).continuous - rw [completeSpace_iff_isComplete_range uniformEmbedding_toUniformOnFun.toUniformInducing, + rw [completeSpace_iff_isComplete_range isUniformEmbedding_toUniformOnFun.isUniformInducing, range_toUniformOnFun] simp only [setOf_and, setOf_forall] apply_rules [IsClosed.isComplete, IsClosed.inter] @@ -126,19 +129,22 @@ variable (𝕜' : Type*) [NontriviallyNormedField 𝕜'] [NormedAlgebra 𝕜' [∀ i, Module 𝕜' (E i)] [∀ i, IsScalarTower 𝕜' 𝕜 (E i)] [Module 𝕜' F] [IsScalarTower 𝕜' 𝕜 F] [∀ i, ContinuousSMul 𝕜 (E i)] -theorem uniformEmbedding_restrictScalars : - UniformEmbedding +theorem isUniformEmbedding_restrictScalars : + IsUniformEmbedding (restrictScalars 𝕜' : ContinuousMultilinearMap 𝕜 E F → ContinuousMultilinearMap 𝕜' E F) := by letI : NontriviallyNormedField 𝕜 := ⟨let ⟨x, hx⟩ := @NontriviallyNormedField.non_trivial 𝕜' _; ⟨algebraMap 𝕜' 𝕜 x, by simpa⟩⟩ - rw [← uniformEmbedding_toUniformOnFun.of_comp_iff] - convert uniformEmbedding_toUniformOnFun using 4 with s + rw [← isUniformEmbedding_toUniformOnFun.of_comp_iff] + convert isUniformEmbedding_toUniformOnFun using 4 with s exact ⟨fun h ↦ h.extend_scalars _, fun h ↦ h.restrict_scalars _⟩ +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_restrictScalars := isUniformEmbedding_restrictScalars + theorem uniformContinuous_restrictScalars : UniformContinuous (restrictScalars 𝕜' : ContinuousMultilinearMap 𝕜 E F → ContinuousMultilinearMap 𝕜' E F) := - (uniformEmbedding_restrictScalars 𝕜').uniformContinuous + (isUniformEmbedding_restrictScalars 𝕜').uniformContinuous end RestrictScalars @@ -207,7 +213,7 @@ theorem embedding_restrictScalars : (restrictScalars 𝕜' : ContinuousMultilinearMap 𝕜 E F → ContinuousMultilinearMap 𝕜' E F) := letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform - (uniformEmbedding_restrictScalars _).embedding + (isUniformEmbedding_restrictScalars _).embedding @[continuity, fun_prop] theorem continuous_restrictScalars : diff --git a/Mathlib/Topology/Algebra/Module/StrongTopology.lean b/Mathlib/Topology/Algebra/Module/StrongTopology.lean index 437453ea31e0d..8e988265fd745 100644 --- a/Mathlib/Topology/Algebra/Module/StrongTopology.lean +++ b/Mathlib/Topology/Algebra/Module/StrongTopology.lean @@ -55,7 +55,8 @@ uniform convergence, bounded convergence -/ -open scoped Topology UniformConvergence +open scoped Topology UniformConvergence Uniformity +open Filter Set Function Bornology section General @@ -92,7 +93,7 @@ instance instTopologicalSpace [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 (DFunLike.coe : (UniformConvergenceCLM σ F 𝔖) → (E →ᵤ[𝔖] F)) theorem topologicalSpace_eq [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : - instTopologicalSpace σ F 𝔖 = TopologicalSpace.induced DFunLike.coe + instTopologicalSpace σ F 𝔖 = TopologicalSpace.induced (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe) (UniformOnFun.topologicalSpace E F 𝔖) := by rw [instTopologicalSpace] congr @@ -103,12 +104,13 @@ that this has nice definitional properties. -/ instance instUniformSpace [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : UniformSpace (UniformConvergenceCLM σ F 𝔖) := UniformSpace.replaceTopology - ((UniformOnFun.uniformSpace E F 𝔖).comap - (DFunLike.coe : (UniformConvergenceCLM σ F 𝔖) → (E →ᵤ[𝔖] F))) + ((UniformOnFun.uniformSpace E F 𝔖).comap (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe)) (by rw [UniformConvergenceCLM.instTopologicalSpace, UniformAddGroup.toUniformSpace_eq]; rfl) theorem uniformSpace_eq [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : - instUniformSpace σ F 𝔖 = UniformSpace.comap DFunLike.coe (UniformOnFun.uniformSpace E F 𝔖) := by + instUniformSpace σ F 𝔖 = + UniformSpace.comap (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe) + (UniformOnFun.uniformSpace E F 𝔖) := by rw [instUniformSpace, UniformSpace.replaceTopology_eq] @[simp] @@ -117,23 +119,31 @@ theorem uniformity_toTopologicalSpace_eq [UniformSpace F] [UniformAddGroup F] ( UniformConvergenceCLM.instTopologicalSpace σ F 𝔖 := rfl -theorem uniformEmbedding_coeFn [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : - UniformEmbedding (α := UniformConvergenceCLM σ F 𝔖) (β := E →ᵤ[𝔖] F) DFunLike.coe := +theorem isUniformEmbedding_coeFn [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : + IsUniformEmbedding (α := UniformConvergenceCLM σ F 𝔖) (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe) := ⟨⟨rfl⟩, DFunLike.coe_injective⟩ +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coeFn := isUniformEmbedding_coeFn + theorem embedding_coeFn [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : Embedding (X := UniformConvergenceCLM σ F 𝔖) (Y := E →ᵤ[𝔖] F) (UniformOnFun.ofFun 𝔖 ∘ DFunLike.coe) := - UniformEmbedding.embedding (uniformEmbedding_coeFn _ _ _) + IsUniformEmbedding.embedding (isUniformEmbedding_coeFn _ _ _) instance instAddCommGroup [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) : AddCommGroup (UniformConvergenceCLM σ F 𝔖) := ContinuousLinearMap.addCommGroup +@[simp] +theorem coe_zero [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) : + ⇑(0 : UniformConvergenceCLM σ F 𝔖) = 0 := + rfl + instance instUniformAddGroup [UniformSpace F] [UniformAddGroup F] (𝔖 : Set (Set E)) : UniformAddGroup (UniformConvergenceCLM σ F 𝔖) := by let φ : (UniformConvergenceCLM σ F 𝔖) →+ E →ᵤ[𝔖] F := ⟨⟨(DFunLike.coe : (UniformConvergenceCLM σ F 𝔖) → E →ᵤ[𝔖] F), rfl⟩, fun _ _ => rfl⟩ - exact (uniformEmbedding_coeFn _ _ _).uniformAddGroup φ + exact (isUniformEmbedding_coeFn _ _ _).uniformAddGroup φ instance instTopologicalAddGroup [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) : TopologicalAddGroup (UniformConvergenceCLM σ F 𝔖) := by @@ -142,7 +152,7 @@ instance instTopologicalAddGroup [TopologicalSpace F] [TopologicalAddGroup F] infer_instance theorem t2Space [TopologicalSpace F] [TopologicalAddGroup F] [T2Space F] - (𝔖 : Set (Set E)) (h𝔖 : ⋃₀ 𝔖 = Set.univ) : T2Space (UniformConvergenceCLM σ F 𝔖) := by + (𝔖 : Set (Set E)) (h𝔖 : ⋃₀ 𝔖 = univ) : T2Space (UniformConvergenceCLM σ F 𝔖) := by letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform haveI : T2Space (E →ᵤ[𝔖] F) := UniformOnFun.t2Space_of_covering h𝔖 @@ -158,7 +168,7 @@ instance instModule (R : Type*) [Semiring R] [Module R F] [SMulCommClass 𝕜₂ theorem continuousSMul [RingHomSurjective σ] [RingHomIsometric σ] [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousSMul 𝕜₂ F] (𝔖 : Set (Set E)) - (h𝔖₃ : ∀ S ∈ 𝔖, Bornology.IsVonNBounded 𝕜₁ S) : + (h𝔖₃ : ∀ S ∈ 𝔖, IsVonNBounded 𝕜₁ S) : ContinuousSMul 𝕜₂ (UniformConvergenceCLM σ F 𝔖) := by letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform @@ -185,11 +195,66 @@ theorem hasBasis_nhds_zero [TopologicalSpace F] [TopologicalAddGroup F] { f : UniformConvergenceCLM σ F 𝔖 | ∀ x ∈ SV.1, f x ∈ SV.2 } := hasBasis_nhds_zero_of_basis σ F 𝔖 h𝔖₁ h𝔖₂ (𝓝 0).basis_sets +theorem nhds_zero_eq_of_basis [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) + {ι : Type*} {p : ι → Prop} {b : ι → Set F} (h : (𝓝 0 : Filter F).HasBasis p b) : + 𝓝 (0 : UniformConvergenceCLM σ F 𝔖) = + ⨅ (s : Set E) (_ : s ∈ 𝔖) (i : ι) (_ : p i), + 𝓟 {f : UniformConvergenceCLM σ F 𝔖 | MapsTo f s (b i)} := by + letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F + haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform + rw [(embedding_coeFn σ F 𝔖).toInducing.nhds_eq_comap, + UniformOnFun.nhds_eq_of_basis _ _ h.uniformity_of_nhds_zero] + simp [MapsTo] + +theorem nhds_zero_eq [TopologicalSpace F] [TopologicalAddGroup F] (𝔖 : Set (Set E)) : + 𝓝 (0 : UniformConvergenceCLM σ F 𝔖) = + ⨅ s ∈ 𝔖, ⨅ t ∈ 𝓝 (0 : F), + 𝓟 {f : UniformConvergenceCLM σ F 𝔖 | MapsTo f s t} := + nhds_zero_eq_of_basis _ _ _ (𝓝 0).basis_sets + +variable {F} in +theorem eventually_nhds_zero_mapsTo [TopologicalSpace F] [TopologicalAddGroup F] + {𝔖 : Set (Set E)} {s : Set E} (hs : s ∈ 𝔖) {U : Set F} (hu : U ∈ 𝓝 0) : + ∀ᶠ f : UniformConvergenceCLM σ F 𝔖 in 𝓝 0, MapsTo f s U := by + rw [nhds_zero_eq] + apply_rules [mem_iInf_of_mem, mem_principal_self] + +variable {σ F} in +theorem isVonNBounded_image2_apply {R : Type*} [SeminormedRing R] + [TopologicalSpace F] [TopologicalAddGroup F] + [Module R F] [ContinuousConstSMul R F] [SMulCommClass 𝕜₂ R F] + {𝔖 : Set (Set E)} {S : Set (UniformConvergenceCLM σ F 𝔖)} (hS : IsVonNBounded R S) + {s : Set E} (hs : s ∈ 𝔖) : IsVonNBounded R (Set.image2 (fun f x ↦ f x) S s) := by + intro U hU + filter_upwards [hS (eventually_nhds_zero_mapsTo σ hs hU)] with c hc + rw [image2_subset_iff] + intro f hf x hx + rcases hc hf with ⟨g, hg, rfl⟩ + exact smul_mem_smul_set (hg hx) + +variable {σ F} in +/-- A set `S` of continuous linear maps with topology of uniform convergence on sets `s ∈ 𝔖` +is von Neumann bounded iff for any `s ∈ 𝔖`, +the set `{f x | (f ∈ S) (x ∈ s)}` is von Neumann bounded. -/ +theorem isVonNBounded_iff {R : Type*} [NormedDivisionRing R] + [TopologicalSpace F] [TopologicalAddGroup F] + [Module R F] [ContinuousConstSMul R F] [SMulCommClass 𝕜₂ R F] + {𝔖 : Set (Set E)} {S : Set (UniformConvergenceCLM σ F 𝔖)} : + IsVonNBounded R S ↔ ∀ s ∈ 𝔖, IsVonNBounded R (Set.image2 (fun f x ↦ f x) S s) := by + refine ⟨fun hS s hs ↦ isVonNBounded_image2_apply hS hs, fun h ↦ ?_⟩ + simp_rw [isVonNBounded_iff_absorbing_le, nhds_zero_eq, le_iInf_iff, le_principal_iff] + intro s hs U hU + rw [Filter.mem_absorbing, Absorbs] + filter_upwards [h s hs hU, eventually_ne_cobounded 0] with c hc hc₀ f hf + rw [mem_smul_set_iff_inv_smul_mem₀ hc₀] + intro x hx + simpa only [mem_smul_set_iff_inv_smul_mem₀ hc₀] using hc (mem_image2_of_mem hf hx) + instance instUniformContinuousConstSMul (M : Type*) [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] [UniformSpace F] [UniformAddGroup F] [UniformContinuousConstSMul M F] (𝔖 : Set (Set E)) : UniformContinuousConstSMul M (UniformConvergenceCLM σ F 𝔖) := - (uniformEmbedding_coeFn σ F 𝔖).toUniformInducing.uniformContinuousConstSMul fun _ _ ↦ by rfl + (isUniformEmbedding_coeFn σ F 𝔖).isUniformInducing.uniformContinuousConstSMul fun _ _ ↦ by rfl instance instContinuousConstSMul (M : Type*) [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] @@ -240,7 +305,7 @@ variable {𝕜₁ 𝕜₂ 𝕜₃ : Type*} [NormedField 𝕜₁] [NormedField the operator norm when `E` and `F` are normed spaces. -/ instance topologicalSpace [TopologicalSpace F] [TopologicalAddGroup F] : TopologicalSpace (E →SL[σ] F) := - UniformConvergenceCLM.instTopologicalSpace σ F { S | Bornology.IsVonNBounded 𝕜₁ S } + UniformConvergenceCLM.instTopologicalSpace σ F { S | IsVonNBounded 𝕜₁ S } instance topologicalAddGroup [TopologicalSpace F] [TopologicalAddGroup F] : TopologicalAddGroup (E →SL[σ] F) := @@ -248,10 +313,10 @@ instance topologicalAddGroup [TopologicalSpace F] [TopologicalAddGroup F] : instance continuousSMul [RingHomSurjective σ] [RingHomIsometric σ] [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousSMul 𝕜₂ F] : ContinuousSMul 𝕜₂ (E →SL[σ] F) := - UniformConvergenceCLM.continuousSMul σ F { S | Bornology.IsVonNBounded 𝕜₁ S } fun _ hs => hs + UniformConvergenceCLM.continuousSMul σ F { S | IsVonNBounded 𝕜₁ S } fun _ hs => hs instance uniformSpace [UniformSpace F] [UniformAddGroup F] : UniformSpace (E →SL[σ] F) := - UniformConvergenceCLM.instUniformSpace σ F { S | Bornology.IsVonNBounded 𝕜₁ S } + UniformConvergenceCLM.instUniformSpace σ F { S | IsVonNBounded 𝕜₁ S } instance uniformAddGroup [UniformSpace F] [UniformAddGroup F] : UniformAddGroup (E →SL[σ] F) := UniformConvergenceCLM.instUniformAddGroup σ F _ @@ -260,25 +325,29 @@ instance [TopologicalSpace F] [TopologicalAddGroup F] [ContinuousSMul 𝕜₁ E] T2Space (E →SL[σ] F) := UniformConvergenceCLM.t2Space σ F _ (Set.eq_univ_of_forall fun x => - Set.mem_sUnion_of_mem (Set.mem_singleton x) (Bornology.isVonNBounded_singleton x)) + Set.mem_sUnion_of_mem (Set.mem_singleton x) (isVonNBounded_singleton x)) protected theorem hasBasis_nhds_zero_of_basis [TopologicalSpace F] [TopologicalAddGroup F] {ι : Type*} {p : ι → Prop} {b : ι → Set F} (h : (𝓝 0 : Filter F).HasBasis p b) : - (𝓝 (0 : E →SL[σ] F)).HasBasis (fun Si : Set E × ι => Bornology.IsVonNBounded 𝕜₁ Si.1 ∧ p Si.2) + (𝓝 (0 : E →SL[σ] F)).HasBasis (fun Si : Set E × ι => IsVonNBounded 𝕜₁ Si.1 ∧ p Si.2) fun Si => { f : E →SL[σ] F | ∀ x ∈ Si.1, f x ∈ b Si.2 } := - UniformConvergenceCLM.hasBasis_nhds_zero_of_basis σ F { S | Bornology.IsVonNBounded 𝕜₁ S } - ⟨∅, Bornology.isVonNBounded_empty 𝕜₁ E⟩ - (directedOn_of_sup_mem fun _ _ => Bornology.IsVonNBounded.union) h + UniformConvergenceCLM.hasBasis_nhds_zero_of_basis σ F { S | IsVonNBounded 𝕜₁ S } + ⟨∅, isVonNBounded_empty 𝕜₁ E⟩ + (directedOn_of_sup_mem fun _ _ => IsVonNBounded.union) h protected theorem hasBasis_nhds_zero [TopologicalSpace F] [TopologicalAddGroup F] : (𝓝 (0 : E →SL[σ] F)).HasBasis - (fun SV : Set E × Set F => Bornology.IsVonNBounded 𝕜₁ SV.1 ∧ SV.2 ∈ (𝓝 0 : Filter F)) + (fun SV : Set E × Set F => IsVonNBounded 𝕜₁ SV.1 ∧ SV.2 ∈ (𝓝 0 : Filter F)) fun SV => { f : E →SL[σ] F | ∀ x ∈ SV.1, f x ∈ SV.2 } := ContinuousLinearMap.hasBasis_nhds_zero_of_basis (𝓝 0).basis_sets -theorem uniformEmbedding_toUniformOnFun [UniformSpace F] [UniformAddGroup F] : - UniformEmbedding fun f : E →SL[σ] F ↦ UniformOnFun.ofFun {s | Bornology.IsVonNBounded 𝕜₁ s} f := - UniformConvergenceCLM.uniformEmbedding_coeFn .. +theorem isUniformEmbedding_toUniformOnFun [UniformSpace F] [UniformAddGroup F] : + IsUniformEmbedding + fun f : E →SL[σ] F ↦ UniformOnFun.ofFun {s | Bornology.IsVonNBounded 𝕜₁ s} f := + UniformConvergenceCLM.isUniformEmbedding_coeFn .. + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toUniformOnFun := isUniformEmbedding_toUniformOnFun instance uniformContinuousConstSMul {M : Type*} [Monoid M] [DistribMulAction M F] [SMulCommClass 𝕜₂ M F] @@ -291,6 +360,51 @@ instance continuousConstSMul {M : Type*} [Monoid M] [DistribMulAction M F] [SMul ContinuousConstSMul M (E →SL[σ] F) := UniformConvergenceCLM.instContinuousConstSMul σ F _ _ +protected theorem nhds_zero_eq_of_basis [TopologicalSpace F] [TopologicalAddGroup F] + {ι : Type*} {p : ι → Prop} {b : ι → Set F} (h : (𝓝 0 : Filter F).HasBasis p b) : + 𝓝 (0 : E →SL[σ] F) = + ⨅ (s : Set E) (_ : IsVonNBounded 𝕜₁ s) (i : ι) (_ : p i), + 𝓟 {f : E →SL[σ] F | MapsTo f s (b i)} := + UniformConvergenceCLM.nhds_zero_eq_of_basis _ _ _ h + +protected theorem nhds_zero_eq [TopologicalSpace F] [TopologicalAddGroup F] : + 𝓝 (0 : E →SL[σ] F) = + ⨅ (s : Set E) (_ : IsVonNBounded 𝕜₁ s) (U : Set F) (_ : U ∈ 𝓝 0), + 𝓟 {f : E →SL[σ] F | MapsTo f s U} := + UniformConvergenceCLM.nhds_zero_eq .. + +/-- If `s` is a von Neumann bounded set and `U` is a neighbourhood of zero, +then sufficiently small continuous linear maps map `s` to `U`. -/ +theorem eventually_nhds_zero_mapsTo [TopologicalSpace F] [TopologicalAddGroup F] + {s : Set E} (hs : IsVonNBounded 𝕜₁ s) {U : Set F} (hu : U ∈ 𝓝 0) : + ∀ᶠ f : E →SL[σ] F in 𝓝 0, MapsTo f s U := + UniformConvergenceCLM.eventually_nhds_zero_mapsTo _ hs hu + +/-- If `S` is a von Neumann bounded set of continuous linear maps `f : E →SL[σ] F` +and `s` is a von Neumann bounded set in the domain, +then the set `{f x | (f ∈ S) (x ∈ s)}` is von Neumann bounded. + +See also `isVonNBounded_iff` for an `Iff` version with stronger typeclass assumptions. -/ +theorem isVonNBounded_image2_apply {R : Type*} [SeminormedRing R] + [TopologicalSpace F] [TopologicalAddGroup F] + [Module R F] [ContinuousConstSMul R F] [SMulCommClass 𝕜₂ R F] + {S : Set (E →SL[σ] F)} (hS : IsVonNBounded R S) {s : Set E} (hs : IsVonNBounded 𝕜₁ s) : + IsVonNBounded R (Set.image2 (fun f x ↦ f x) S s) := + UniformConvergenceCLM.isVonNBounded_image2_apply hS hs + +/-- A set `S` of continuous linear maps is von Neumann bounded +iff for any von Neumann bounded set `s`, +the set `{f x | (f ∈ S) (x ∈ s)}` is von Neumann bounded. + +For the forward implication with weaker typeclass assumptions, see `isVonNBounded_image2_apply`. -/ +theorem isVonNBounded_iff {R : Type*} [NormedDivisionRing R] + [TopologicalSpace F] [TopologicalAddGroup F] + [Module R F] [ContinuousConstSMul R F] [SMulCommClass 𝕜₂ R F] + {S : Set (E →SL[σ] F)} : + IsVonNBounded R S ↔ + ∀ s, IsVonNBounded 𝕜₁ s → IsVonNBounded R (Set.image2 (fun f x ↦ f x) S s) := + UniformConvergenceCLM.isVonNBounded_iff + variable (G) [TopologicalSpace F] [TopologicalSpace G] /-- Pre-composition by a *fixed* continuous linear map as a continuous linear map. @@ -362,15 +476,18 @@ variable [UniformSpace F] [UniformAddGroup F] [Module 𝕜 F] (𝕜' : Type*) [NontriviallyNormedField 𝕜'] [NormedAlgebra 𝕜' 𝕜] [Module 𝕜' E] [IsScalarTower 𝕜' 𝕜 E] [Module 𝕜' F] [IsScalarTower 𝕜' 𝕜 F] -theorem uniformEmbedding_restrictScalars : - UniformEmbedding (restrictScalars 𝕜' : (E →L[𝕜] F) → (E →L[𝕜'] F)) := by - rw [← uniformEmbedding_toUniformOnFun.of_comp_iff] - convert uniformEmbedding_toUniformOnFun using 4 with s +theorem isUniformEmbedding_restrictScalars : + IsUniformEmbedding (restrictScalars 𝕜' : (E →L[𝕜] F) → (E →L[𝕜'] F)) := by + rw [← isUniformEmbedding_toUniformOnFun.of_comp_iff] + convert isUniformEmbedding_toUniformOnFun using 4 with s exact ⟨fun h ↦ h.extend_scalars _, fun h ↦ h.restrict_scalars _⟩ +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_restrictScalars := isUniformEmbedding_restrictScalars + theorem uniformContinuous_restrictScalars : UniformContinuous (restrictScalars 𝕜' : (E →L[𝕜] F) → (E →L[𝕜'] F)) := - (uniformEmbedding_restrictScalars 𝕜').uniformContinuous + (isUniformEmbedding_restrictScalars 𝕜').uniformContinuous end UniformSpace @@ -382,7 +499,7 @@ theorem embedding_restrictScalars : Embedding (restrictScalars 𝕜' : (E →L[𝕜] F) → (E →L[𝕜'] F)) := letI : UniformSpace F := TopologicalAddGroup.toUniformSpace F haveI : UniformAddGroup F := comm_topologicalAddGroup_is_uniform - (uniformEmbedding_restrictScalars _).embedding + (isUniformEmbedding_restrictScalars _).embedding @[continuity, fun_prop] theorem continuous_restrictScalars : diff --git a/Mathlib/Topology/Algebra/Monoid.lean b/Mathlib/Topology/Algebra/Monoid.lean index c2bebad5ed312..126c6636dd313 100644 --- a/Mathlib/Topology/Algebra/Monoid.lean +++ b/Mathlib/Topology/Algebra/Monoid.lean @@ -7,8 +7,8 @@ import Mathlib.Algebra.BigOperators.Finprod import Mathlib.Order.Filter.Pointwise import Mathlib.Topology.Algebra.MulAction import Mathlib.Algebra.BigOperators.Pi -import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Algebra.Group.ULift +import Mathlib.Topology.ContinuousMap.Defs /-! # Theory of topological monoids @@ -75,7 +75,7 @@ instance ContinuousMul.to_continuousSMul : ContinuousSMul M M := instance ContinuousMul.to_continuousSMul_op : ContinuousSMul Mᵐᵒᵖ M := ⟨show Continuous ((fun p : M × M => p.1 * p.2) ∘ Prod.swap ∘ Prod.map MulOpposite.unop id) from continuous_mul.comp <| - continuous_swap.comp <| Continuous.prod_map MulOpposite.continuous_unop continuous_id⟩ + continuous_swap.comp <| Continuous.prodMap MulOpposite.continuous_unop continuous_id⟩ @[to_additive] theorem ContinuousMul.induced {α : Type*} {β : Type*} {F : Type*} [FunLike F α β] [MulOneClass α] diff --git a/Mathlib/Topology/Algebra/MulAction.lean b/Mathlib/Topology/Algebra/MulAction.lean index b17c9a9e4bb1a..91dc843aa0507 100644 --- a/Mathlib/Topology/Algebra/MulAction.lean +++ b/Mathlib/Topology/Algebra/MulAction.lean @@ -132,13 +132,13 @@ action is."] instance ContinuousSMul.op [SMul Mᵐᵒᵖ X] [IsCentralScalar M X] : ContinuousSMul Mᵐᵒᵖ X := ⟨by suffices Continuous fun p : M × X => MulOpposite.op p.fst • p.snd from - this.comp (MulOpposite.continuous_unop.prod_map continuous_id) + this.comp (MulOpposite.continuous_unop.prodMap continuous_id) simpa only [op_smul_eq_smul] using (continuous_smul : Continuous fun p : M × X => _)⟩ @[to_additive] instance MulOpposite.continuousSMul : ContinuousSMul M Xᵐᵒᵖ := ⟨MulOpposite.continuous_op.comp <| - continuous_smul.comp <| continuous_id.prod_map MulOpposite.continuous_unop⟩ + continuous_smul.comp <| continuous_id.prodMap MulOpposite.continuous_unop⟩ @[to_additive] protected theorem Specializes.smul {a b : M} {x y : X} (h₁ : a ⤳ b) (h₂ : x ⤳ y) : diff --git a/Mathlib/Topology/Algebra/Nonarchimedean/Basic.lean b/Mathlib/Topology/Algebra/Nonarchimedean/Basic.lean index 6550bf2652504..227a2f3aaef68 100644 --- a/Mathlib/Topology/Algebra/Nonarchimedean/Basic.lean +++ b/Mathlib/Topology/Algebra/Nonarchimedean/Basic.lean @@ -75,7 +75,7 @@ the cartesian product of two nonarchimedean groups contains the cartesian produc an open neighborhood in each group."] theorem prod_subset {U} (hU : U ∈ 𝓝 (1 : G × K)) : ∃ (V : OpenSubgroup G) (W : OpenSubgroup K), (V : Set G) ×ˢ (W : Set K) ⊆ U := by - erw [nhds_prod_eq, Filter.mem_prod_iff] at hU + rw [nhds_prod_eq, Filter.mem_prod_iff] at hU rcases hU with ⟨U₁, hU₁, U₂, hU₂, h⟩ cases' is_nonarchimedean _ hU₁ with V hV cases' is_nonarchimedean _ hU₂ with W hW diff --git a/Mathlib/Topology/Algebra/Nonarchimedean/Completion.lean b/Mathlib/Topology/Algebra/Nonarchimedean/Completion.lean index 8d88cf4ee0a0a..c5dd61852fecd 100644 --- a/Mathlib/Topology/Algebra/Nonarchimedean/Completion.lean +++ b/Mathlib/Topology/Algebra/Nonarchimedean/Completion.lean @@ -51,7 +51,7 @@ instance {G : Type*} [AddGroup G] [UniformSpace G] [UniformAddGroup G] [Nonarchi `0` in `Completion G`. This follows from the fact that `toCompl : G → Completion G` is dense inducing and `W` is a neighborhood of `0` in `G`. -/ apply isOpen_of_mem_nhds (g := 0) - apply (denseInducing_toCompl _).closure_image_mem_nhds + apply (isDenseInducing_toCompl _).closure_image_mem_nhds exact mem_nhds_zero W use ⟨_, this⟩ /- Finally, it remains to show that `V ⊆ U`. It suffices to show that `V ⊆ C`, which diff --git a/Mathlib/Topology/Algebra/OpenSubgroup.lean b/Mathlib/Topology/Algebra/OpenSubgroup.lean index 59ea6ac40a94a..99c3a4c276f10 100644 --- a/Mathlib/Topology/Algebra/OpenSubgroup.lean +++ b/Mathlib/Topology/Algebra/OpenSubgroup.lean @@ -1,7 +1,7 @@ /- Copyright (c) 2019 Johan Commelin. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. -Authors: Johan Commelin +Authors: Johan Commelin, Nailin Guan -/ import Mathlib.RingTheory.Ideal.Basic import Mathlib.Topology.Algebra.Ring.Basic @@ -135,8 +135,8 @@ instance : Inhabited (OpenSubgroup G) := @[to_additive] theorem isClosed [ContinuousMul G] (U : OpenSubgroup G) : IsClosed (U : Set G) := by apply isOpen_compl_iff.1 - refine isOpen_iff_forall_mem_open.2 fun x hx => ⟨(fun y => y * x⁻¹) ⁻¹' U, ?_, ?_, ?_⟩ - · refine fun u hux hu => hx ?_ + refine isOpen_iff_forall_mem_open.2 fun x hx ↦ ⟨(fun y ↦ y * x⁻¹) ⁻¹' U, ?_, ?_, ?_⟩ + · refine fun u hux hu ↦ hx ?_ simp only [Set.mem_preimage, SetLike.mem_coe] at hux hu ⊢ convert U.mul_mem (U.inv_mem hux) hu simp @@ -170,7 +170,7 @@ end @[to_additive] instance instInfOpenSubgroup : Inf (OpenSubgroup G) := - ⟨fun U V => ⟨U ⊓ V, U.isOpen.inter V.isOpen⟩⟩ + ⟨fun U V ↦ ⟨U ⊓ V, U.isOpen.inter V.isOpen⟩⟩ @[to_additive (attr := simp, norm_cast)] theorem coe_inf : (↑(U ⊓ V) : Set G) = (U : Set G) ∩ V := @@ -194,7 +194,7 @@ instance instPartialOrderOpenSubgroup : PartialOrder (OpenSubgroup G) := inferIn -- Porting note: we override `toPartialorder` to get better `le` @[to_additive] instance instSemilatticeInfOpenSubgroup : SemilatticeInf (OpenSubgroup G) := - { SetLike.coe_injective.semilatticeInf ((↑) : OpenSubgroup G → Set G) fun _ _ => rfl with + { SetLike.coe_injective.semilatticeInf ((↑) : OpenSubgroup G → Set G) fun _ _ ↦ rfl with toInf := instInfOpenSubgroup toPartialOrder := instPartialOrderOpenSubgroup } @@ -245,9 +245,9 @@ variable {G : Type*} [Group G] [TopologicalSpace G] @[to_additive] theorem isOpen_of_mem_nhds [ContinuousMul G] (H : Subgroup G) {g : G} (hg : (H : Set G) ∈ 𝓝 g) : IsOpen (H : Set G) := by - refine isOpen_iff_mem_nhds.2 fun x hx => ?_ + refine isOpen_iff_mem_nhds.2 fun x hx ↦ ?_ have hg' : g ∈ H := SetLike.mem_coe.1 (mem_of_mem_nhds hg) - have : Filter.Tendsto (fun y => y * (x⁻¹ * g)) (𝓝 x) (𝓝 g) := + have : Filter.Tendsto (fun y ↦ y * (x⁻¹ * g)) (𝓝 x) (𝓝 g) := (continuous_id.mul continuous_const).tendsto' _ _ (mul_inv_cancel_left _ _) simpa only [SetLike.mem_coe, Filter.mem_map', H.mul_mem_cancel_right (H.mul_mem (H.inv_mem hx) hg')] using this hg @@ -327,7 +327,7 @@ variable {G : Type*} [Group G] [TopologicalSpace G] [ContinuousMul G] @[to_additive] instance : Sup (OpenSubgroup G) := - ⟨fun U V => ⟨U ⊔ V, Subgroup.isOpen_mono (le_sup_left : U.1 ≤ U.1 ⊔ V.1) U.isOpen⟩⟩ + ⟨fun U V ↦ ⟨U ⊔ V, Subgroup.isOpen_mono (le_sup_left : U.1 ≤ U.1 ⊔ V.1) U.isOpen⟩⟩ @[to_additive (attr := simp, norm_cast)] theorem toSubgroup_sup (U V : OpenSubgroup G) : (↑(U ⊔ V) : Subgroup G) = ↑U ⊔ ↑V := rfl @@ -336,7 +336,7 @@ theorem toSubgroup_sup (U V : OpenSubgroup G) : (↑(U ⊔ V) : Subgroup G) = @[to_additive] instance : Lattice (OpenSubgroup G) := { instSemilatticeInfOpenSubgroup, - toSubgroup_injective.semilatticeSup ((↑) : OpenSubgroup G → Subgroup G) fun _ _ => rfl with + toSubgroup_injective.semilatticeSup ((↑) : OpenSubgroup G → Subgroup G) fun _ _ ↦ rfl with toPartialOrder := instPartialOrderOpenSubgroup } end OpenSubgroup @@ -364,3 +364,92 @@ theorem isOpen_of_isOpen_subideal {U I : Ideal R} (h : U ≤ I) (hU : IsOpen (U @Submodule.isOpen_mono R R _ _ _ _ Semiring.toModule _ _ h hU end Ideal + +/-! +# Open normal subgroups of a topological group + +This section builds the lattice `OpenNormalSubgroup G` of open subgroups in a topological group `G`, +and its additive version `OpenNormalAddSubgroup`. + +-/ + +section + +universe u + +/-- The type of open normal subgroups of a topological group. -/ +@[ext] +structure OpenNormalSubgroup (G : Type u) [Group G] [TopologicalSpace G] + extends OpenSubgroup G where + isNormal' : toSubgroup.Normal := by infer_instance + +/-- The type of open normal subgroups of a topological additive group. -/ +@[ext] +structure OpenNormalAddSubgroup (G : Type u) [AddGroup G] [TopologicalSpace G] + extends OpenAddSubgroup G where + isNormal' : toAddSubgroup.Normal := by infer_instance + +attribute [to_additive] OpenNormalSubgroup + +namespace OpenNormalSubgroup + +variable {G : Type u} [Group G] [TopologicalSpace G] + +@[to_additive] +instance (H : OpenNormalSubgroup G) : H.toSubgroup.Normal := H.isNormal' + +@[to_additive] +theorem toSubgroup_injective : Function.Injective + (fun H ↦ H.toOpenSubgroup.toSubgroup : OpenNormalSubgroup G → Subgroup G) := + fun A B h ↦ by + ext + dsimp at h + rw [h] + +@[to_additive] +instance : SetLike (OpenNormalSubgroup G) G where + coe U := U.1 + coe_injective' _ _ h := toSubgroup_injective <| SetLike.ext' h + +@[to_additive] +instance : SubgroupClass (OpenNormalSubgroup G) G where + mul_mem := Subsemigroup.mul_mem' _ + one_mem U := U.one_mem' + inv_mem := Subgroup.inv_mem' _ + +@[to_additive] +instance : Coe (OpenNormalSubgroup G) (Subgroup G) where + coe H := H.toOpenSubgroup.toSubgroup + +@[to_additive] +instance instPartialOrderOpenNormalSubgroup : PartialOrder (OpenNormalSubgroup G) := inferInstance + +@[to_additive] +instance instInfOpenNormalSubgroup : Inf (OpenNormalSubgroup G) := + ⟨fun U V ↦ ⟨U.toOpenSubgroup ⊓ V.toOpenSubgroup, + Subgroup.normal_inf_normal U.toSubgroup V.toSubgroup⟩⟩ + +@[to_additive] +instance instSemilatticeInfOpenNormalSubgroup : SemilatticeInf (OpenNormalSubgroup G) := + SetLike.coe_injective.semilatticeInf ((↑) : OpenNormalSubgroup G → Set G) fun _ _ ↦ rfl + +@[to_additive] +instance [ContinuousMul G] : Sup (OpenNormalSubgroup G) := + ⟨fun U V ↦ ⟨U.toOpenSubgroup ⊔ V.toOpenSubgroup, + Subgroup.sup_normal U.toOpenSubgroup.1 V.toOpenSubgroup.1⟩⟩ + +@[to_additive] +instance instSemilatticeSupOpenNormalSubgroup [ContinuousMul G] : + SemilatticeSup (OpenNormalSubgroup G) := + toSubgroup_injective.semilatticeSup + (fun (H : OpenNormalSubgroup G) ↦ ↑H.toOpenSubgroup) (fun _ _ ↦ rfl) + +@[to_additive] +instance [ContinuousMul G] : Lattice (OpenNormalSubgroup G) := + { instSemilatticeInfOpenNormalSubgroup, + instSemilatticeSupOpenNormalSubgroup with + toPartialOrder := instPartialOrderOpenNormalSubgroup} + +end OpenNormalSubgroup + +end diff --git a/Mathlib/Topology/Algebra/Order/Field.lean b/Mathlib/Topology/Algebra/Order/Field.lean index 9779411cedf57..b80ccdfcef320 100644 --- a/Mathlib/Topology/Algebra/Order/Field.lean +++ b/Mathlib/Topology/Algebra/Order/Field.lean @@ -195,10 +195,10 @@ instance (priority := 100) LinearOrderedSemifield.toHasContinuousInv₀ {𝕜} · obtain ⟨x', h₀, hxx', h₁⟩ : ∃ x', 0 < x' ∧ x ≤ x' ∧ x' < 1 := ⟨max x (1 / 2), one_half_pos.trans_le (le_max_right _ _), le_max_left _ _, max_lt hx one_half_lt_one⟩ - filter_upwards [Ioo_mem_nhds one_pos (one_lt_inv h₀ h₁)] with y hy - exact hxx'.trans_lt <| inv_inv x' ▸ inv_lt_inv_of_lt hy.1 hy.2 - · filter_upwards [Ioi_mem_nhds (inv_lt_one hx)] with y hy - simpa only [inv_inv] using inv_lt_inv_of_lt (inv_pos.2 <| one_pos.trans hx) hy + filter_upwards [Ioo_mem_nhds one_pos ((one_lt_inv₀ h₀).2 h₁)] with y hy + exact hxx'.trans_lt <| lt_inv_of_lt_inv₀ hy.1 hy.2 + · filter_upwards [Ioi_mem_nhds (inv_lt_one_of_one_lt₀ hx)] with y hy + exact inv_lt_of_inv_lt₀ (by positivity) hy instance (priority := 100) LinearOrderedField.toTopologicalDivisionRing : TopologicalDivisionRing 𝕜 := ⟨⟩ diff --git a/Mathlib/Topology/Algebra/Order/Floor.lean b/Mathlib/Topology/Algebra/Order/Floor.lean index 3877c5331e7bf..bde8ae91b5715 100644 --- a/Mathlib/Topology/Algebra/Order/Floor.lean +++ b/Mathlib/Topology/Algebra/Order/Floor.lean @@ -3,9 +3,8 @@ Copyright (c) 2020 Anatole Dedecker. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Anatole Dedecker -/ -import Mathlib.Algebra.Order.Floor +import Mathlib.Order.Filter.AtTopBot.Floor import Mathlib.Topology.Algebra.Order.Group -import Mathlib.Topology.Order.Basic /-! # Topological facts about `Int.floor`, `Int.ceil` and `Int.fract` @@ -27,8 +26,36 @@ This file proves statements about limits and continuity of functions involving ` open Filter Function Int Set Topology +namespace FloorSemiring + +open scoped Nat + +variable {K : Type*} [LinearOrderedField K] [FloorSemiring K] [TopologicalSpace K] [OrderTopology K] + +theorem tendsto_mul_pow_div_factorial_sub_atTop (a c : K) (d : ℕ) : + Tendsto (fun n ↦ a * c ^ n / (n - d)!) atTop (𝓝 0) := by + rw [tendsto_order] + constructor + all_goals + intro ε hε + filter_upwards [eventually_mul_pow_lt_factorial_sub (a * ε⁻¹) c d] with n h + rw [mul_right_comm, ← div_eq_mul_inv] at h + · rw [div_lt_iff_of_neg hε] at h + rwa [lt_div_iff₀' (Nat.cast_pos.mpr (Nat.factorial_pos _))] + · rw [div_lt_iff₀ hε] at h + rwa [div_lt_iff₀' (Nat.cast_pos.mpr (Nat.factorial_pos _))] + +theorem tendsto_pow_div_factorial_atTop (c : K) : + Tendsto (fun n ↦ c ^ n / n !) atTop (𝓝 0) := by + convert tendsto_mul_pow_div_factorial_sub_atTop 1 c 0 + rw [one_mul] + +end FloorSemiring + variable {α β γ : Type*} [LinearOrderedRing α] [FloorRing α] +-- TODO: move to `Mathlib.Order.Filter.AtTopBot.Floor` + theorem tendsto_floor_atTop : Tendsto (floor : α → ℤ) atTop atTop := floor_mono.tendsto_atTop_atTop fun b => ⟨(b + 1 : ℤ), by rw [floor_intCast]; exact (lt_add_one _).le⟩ @@ -179,7 +206,7 @@ theorem ContinuousOn.comp_fract' {f : β → α → γ} (h : ContinuousOn (uncur (tendsto_id.prod_map (tendsto_fract_right _))).mono_right (le_of_eq ?_) <;> simp [nhdsWithin_prod_eq, nhdsWithin_univ] · replace ht : t ≠ ⌊t⌋ := fun ht' => ht ⟨_, ht'⟩ - refine (h.continuousAt ?_).comp (continuousAt_id.prod_map (continuousAt_fract ht)) + refine (h.continuousAt ?_).comp (continuousAt_id.prodMap (continuousAt_fract ht)) exact prod_mem_nhds univ_mem (Icc_mem_nhds (fract_pos.2 ht) (fract_lt_one _)) theorem ContinuousOn.comp_fract {s : β → α} {f : β → α → γ} diff --git a/Mathlib/Topology/Algebra/Polynomial.lean b/Mathlib/Topology/Algebra/Polynomial.lean index fb827c4965390..663b8bd81dc20 100644 --- a/Mathlib/Topology/Algebra/Polynomial.lean +++ b/Mathlib/Topology/Algebra/Polynomial.lean @@ -191,8 +191,7 @@ theorem coeff_bdd_of_roots_le {B : ℝ} {d : ℕ} (f : F →+* K) {p : F[X]} (h1 _ ≤ max B 1 ^ d * d.choose (d / 2) := by gcongr; exact (i.choose_mono h3).trans (i.choose_le_middle d) · rw [eq_one_of_roots_le hB h1 h2 h4, Polynomial.map_one, coeff_one] - refine _root_.trans ?_ - (one_le_mul_of_one_le_of_one_le (one_le_pow_of_one_le (le_max_right B 1) d) ?_) + refine le_trans ?_ (one_le_mul_of_one_le_of_one_le (one_le_pow₀ (le_max_right B 1)) ?_) · split_ifs <;> norm_num · exact mod_cast Nat.succ_le_iff.mpr (Nat.choose_pos (d.div_le_self 2)) diff --git a/Mathlib/Topology/Algebra/PontryaginDual.lean b/Mathlib/Topology/Algebra/PontryaginDual.lean index 80aa1eef70921..4229049cf7321 100644 --- a/Mathlib/Topology/Algebra/PontryaginDual.lean +++ b/Mathlib/Topology/Algebra/PontryaginDual.lean @@ -22,9 +22,9 @@ isomorphic to its double dual. open Pointwise Function -variable (A B C D E G : Type*) [Monoid A] [Monoid B] [Monoid C] [Monoid D] [CommGroup E] [Group G] - [TopologicalSpace A] [TopologicalSpace B] [TopologicalSpace C] [TopologicalSpace D] - [TopologicalSpace E] [TopologicalSpace G] [TopologicalGroup E] [TopologicalGroup G] +variable (A B C G H : Type*) [Monoid A] [Monoid B] [Monoid C] [CommGroup G] [Group H] + [TopologicalSpace A] [TopologicalSpace B] [TopologicalSpace C] + [TopologicalSpace G] [TopologicalSpace H] [TopologicalGroup G] [TopologicalGroup H] /-- The Pontryagin dual of `A` is the group of continuous homomorphism `A → Circle`. -/ def PontryaginDual := @@ -48,23 +48,23 @@ instance : TopologicalGroup (PontryaginDual A) := noncomputable instance : Inhabited (PontryaginDual A) := (inferInstance : Inhabited (ContinuousMonoidHom A Circle)) -instance [LocallyCompactSpace G] : LocallyCompactSpace (PontryaginDual G) := by +instance [LocallyCompactSpace H] : LocallyCompactSpace (PontryaginDual H) := by let Vn : ℕ → Set Circle := fun n ↦ Circle.exp '' { x | |x| < Real.pi / 2 ^ (n + 1)} have hVn : ∀ n x, x ∈ Vn n ↔ |Complex.arg x| < Real.pi / 2 ^ (n + 1) := by refine fun n x ↦ ⟨?_, fun hx ↦ ⟨Complex.arg x, hx, Circle.exp_arg x⟩⟩ rintro ⟨t, ht : |t| < _, rfl⟩ - have ht' := ht.trans_le (div_le_self Real.pi_nonneg (one_le_pow_of_one_le one_le_two (n + 1))) + have ht' := ht.trans_le (div_le_self Real.pi_nonneg (one_le_pow₀ one_le_two)) rwa [Circle.arg_exp (neg_lt_of_abs_lt ht') (lt_of_abs_lt ht').le] refine ContinuousMonoidHom.locallyCompactSpace_of_hasBasis Vn ?_ ?_ · intro n x h1 h2 rw [hVn] at h1 h2 ⊢ rwa [Circle.coe_mul, Complex.arg_mul x.coe_ne_zero x.coe_ne_zero, - ← two_mul, abs_mul, abs_two, ← lt_div_iff' two_pos, div_div, ← pow_succ] at h2 + ← two_mul, abs_mul, abs_two, ← lt_div_iff₀' two_pos, div_div, ← pow_succ] at h2 apply Set.Ioo_subset_Ioc_self - rw [← two_mul, Set.mem_Ioo, ← abs_lt, abs_mul, abs_two, ← lt_div_iff' two_pos] + rw [← two_mul, Set.mem_Ioo, ← abs_lt, abs_mul, abs_two, ← lt_div_iff₀' two_pos] exact h1.trans_le - (div_le_div_of_nonneg_left Real.pi_nonneg two_pos (le_self_pow one_le_two n.succ_ne_zero)) + (div_le_div_of_nonneg_left Real.pi_nonneg two_pos (le_self_pow₀ one_le_two n.succ_ne_zero)) · rw [← Circle.exp_zero, ← isLocalHomeomorph_circleExp.map_nhds_eq 0] refine ((nhds_basis_zero_abs_sub_lt ℝ).to_hasBasis (fun x hx ↦ ⟨Nat.ceil (Real.pi / x), trivial, fun t ht ↦ ?_⟩) @@ -75,17 +75,20 @@ instance [LocallyCompactSpace G] : LocallyCompactSpace (PontryaginDual G) := by refine (Nat.le_ceil (Real.pi / x)).trans ?_ exact_mod_cast (Nat.le_succ _).trans (Nat.lt_two_pow _).le -variable {A B C D E} +variable {A B C G} namespace PontryaginDual open ContinuousMonoidHom instance : FunLike (PontryaginDual A) A Circle := - ContinuousMonoidHom.funLike + ContinuousMonoidHom.instFunLike -noncomputable instance : ContinuousMonoidHomClass (PontryaginDual A) A Circle := - ContinuousMonoidHom.ContinuousMonoidHomClass +noncomputable instance instContinuousMapClass : ContinuousMapClass (PontryaginDual A) A Circle := + ContinuousMonoidHom.instContinuousMapClass + +noncomputable instance instMonoidHomClass : MonoidHomClass (PontryaginDual A) A Circle := + ContinuousMonoidHom.instMonoidHomClass /-- `PontryaginDual` is a contravariant functor. -/ noncomputable def map (f : ContinuousMonoidHom A B) : @@ -107,15 +110,15 @@ theorem map_comp (g : ContinuousMonoidHom B C) (f : ContinuousMonoidHom A B) : ext fun _x => ext fun _y => rfl @[simp] -nonrec theorem map_mul (f g : ContinuousMonoidHom A E) : map (f * g) = map f * map g := +nonrec theorem map_mul (f g : ContinuousMonoidHom A G) : map (f * g) = map f * map g := ext fun x => ext fun y => map_mul x (f y) (g y) -variable (A B C D E) +variable (A B C G) /-- `ContinuousMonoidHom.dual` as a `ContinuousMonoidHom`. -/ -noncomputable def mapHom [LocallyCompactSpace E] : - ContinuousMonoidHom (ContinuousMonoidHom A E) - (ContinuousMonoidHom (PontryaginDual E) (PontryaginDual A)) where +noncomputable def mapHom [LocallyCompactSpace G] : + ContinuousMonoidHom (ContinuousMonoidHom A G) + (ContinuousMonoidHom (PontryaginDual G) (PontryaginDual A)) where toFun := map map_one' := map_one map_mul' := map_mul diff --git a/Mathlib/Topology/Algebra/ProperAction.lean b/Mathlib/Topology/Algebra/ProperAction.lean index cd13f848a2f41..4a337be7878ae 100644 --- a/Mathlib/Topology/Algebra/ProperAction.lean +++ b/Mathlib/Topology/Algebra/ProperAction.lean @@ -73,9 +73,8 @@ class ProperSMul (G X : Type*) [TopologicalSpace G] [TopologicalSpace X] [Group attribute [to_additive existing] properSMul_iff -variable {G X Y Z : Type*} [Group G] [MulAction G X] [MulAction G Y] -variable [TopologicalSpace G] [TopologicalSpace X] [TopologicalSpace Y] -variable [TopologicalSpace Z] +variable {G X : Type*} [Group G] [MulAction G X] +variable [TopologicalSpace G] [TopologicalSpace X] /-- If a group acts properly then in particular it acts continuously. -/ @[to_additive "If a group acts properly then in particular it acts continuously."] @@ -129,11 +128,9 @@ theorem t2Space_quotient_mulAction_of_properSMul [ProperSMul G X] : rw [t2_iff_isClosed_diagonal] set R := MulAction.orbitRel G X let π : X → Quotient R := Quotient.mk' - have : QuotientMap (Prod.map π π) := - (isOpenMap_quotient_mk'_mul.prod isOpenMap_quotient_mk'_mul).to_quotientMap - (continuous_quotient_mk'.prod_map continuous_quotient_mk') - ((surjective_quotient_mk' _).prodMap (surjective_quotient_mk' _)) - rw [← this.isClosed_preimage] + have : IsOpenQuotientMap (Prod.map π π) := + MulAction.isOpenQuotientMap_quotientMk.prodMap MulAction.isOpenQuotientMap_quotientMk + rw [← this.quotientMap.isClosed_preimage] convert ProperSMul.isProperMap_smul_pair.isClosedMap.isClosed_range · ext ⟨x₁, x₂⟩ simp only [mem_preimage, map_apply, mem_diagonal_iff, mem_range, Prod.mk.injEq, Prod.exists, @@ -175,7 +172,7 @@ theorem properSMul_of_closedEmbedding {H : Type*} [Group H] [MulAction H X] [Top (f_compat : ∀ (h : H) (x : X), f h • x = h • x) : ProperSMul H X where isProperMap_smul_pair := by have := isProperMap_of_closedEmbedding f_clemb - have h : IsProperMap (Prod.map f (fun x : X ↦ x)) := IsProperMap.prod_map this isProperMap_id + have h : IsProperMap (Prod.map f (fun x : X ↦ x)) := this.prodMap isProperMap_id have : (fun hx : H × X ↦ (hx.1 • hx.2, hx.2)) = (fun hx ↦ (f hx.1 • hx.2, hx.2)) := by simp [f_compat] rw [this] @@ -247,7 +244,7 @@ theorem properlyDiscontinuousSMul_iff_properSMul [T2Space X] [DiscreteTopology G apply IsCompact.finite_of_discrete -- Now set `h : (g, x) ↦ (g⁻¹ • x, x)`, because `f` is proper by hypothesis, so is `h`. have : IsProperMap (fun gx : G × X ↦ (gx.1⁻¹ • gx.2, gx.2)) := - (IsProperMap.prod_map (Homeomorph.isProperMap (Homeomorph.inv G)) isProperMap_id).comp <| + (IsProperMap.prodMap (Homeomorph.isProperMap (Homeomorph.inv G)) isProperMap_id).comp <| ProperSMul.isProperMap_smul_pair --But we also have that `{g | Set.Nonempty ((g • ·) '' K ∩ L)} = h ⁻¹ (K × L)`, which -- concludes the proof. diff --git a/Mathlib/Topology/Algebra/ProperConstSMul.lean b/Mathlib/Topology/Algebra/ProperConstSMul.lean index 30fbbb4b83bf7..7e3167890f5ee 100644 --- a/Mathlib/Topology/Algebra/ProperConstSMul.lean +++ b/Mathlib/Topology/Algebra/ProperConstSMul.lean @@ -61,7 +61,7 @@ instance {M X Y : Type*} [SMul M X] [TopologicalSpace X] [ProperConstSMul M X] [SMul M Y] [TopologicalSpace Y] [ProperConstSMul M Y] : ProperConstSMul M (X × Y) := - ⟨fun c ↦ (isProperMap_smul c X).prod_map (isProperMap_smul c Y)⟩ + ⟨fun c ↦ (isProperMap_smul c X).prodMap (isProperMap_smul c Y)⟩ instance {M ι : Type*} {X : ι → Type*} [∀ i, SMul M (X i)] [∀ i, TopologicalSpace (X i)] [∀ i, ProperConstSMul M (X i)] : diff --git a/Mathlib/Topology/Algebra/Ring/Ideal.lean b/Mathlib/Topology/Algebra/Ring/Ideal.lean index bd45ee761f821..aa3cf06eb57a1 100644 --- a/Mathlib/Topology/Algebra/Ring/Ideal.lean +++ b/Mathlib/Topology/Algebra/Ring/Ideal.lean @@ -51,26 +51,18 @@ instance topologicalRingQuotientTopology : TopologicalSpace (R ⧸ N) := -- note for the reader: in the following, `mk` is `Ideal.Quotient.mk`, the canonical map `R → R/I`. variable [TopologicalRing R] -theorem QuotientRing.isOpenMap_coe : IsOpenMap (mk N) := by - intro s s_op - change IsOpen (mk N ⁻¹' (mk N '' s)) - rw [quotient_ring_saturate] - exact isOpen_iUnion fun ⟨n, _⟩ => isOpenMap_add_left n s s_op +theorem QuotientRing.isOpenMap_coe : IsOpenMap (mk N) := + QuotientAddGroup.isOpenMap_coe + +theorem QuotientRing.isOpenQuotientMap_mk : IsOpenQuotientMap (mk N) := + QuotientAddGroup.isOpenQuotientMap_mk theorem QuotientRing.quotientMap_coe_coe : QuotientMap fun p : R × R => (mk N p.1, mk N p.2) := - IsOpenMap.to_quotientMap ((QuotientRing.isOpenMap_coe N).prod (QuotientRing.isOpenMap_coe N)) - ((continuous_quot_mk.comp continuous_fst).prod_mk (continuous_quot_mk.comp continuous_snd)) - (by rintro ⟨⟨x⟩, ⟨y⟩⟩; exact ⟨(x, y), rfl⟩) - -instance topologicalRing_quotient : TopologicalRing (R ⧸ N) := - TopologicalSemiring.toTopologicalRing - { continuous_add := - have cont : Continuous (mk N ∘ fun p : R × R => p.fst + p.snd) := - continuous_quot_mk.comp continuous_add - (QuotientMap.continuous_iff (QuotientRing.quotientMap_coe_coe N)).mpr cont - continuous_mul := - have cont : Continuous (mk N ∘ fun p : R × R => p.fst * p.snd) := - continuous_quot_mk.comp continuous_mul - (QuotientMap.continuous_iff (QuotientRing.quotientMap_coe_coe N)).mpr cont } + ((isOpenQuotientMap_mk N).prodMap (isOpenQuotientMap_mk N)).quotientMap + +instance topologicalRing_quotient : TopologicalRing (R ⧸ N) where + __ := QuotientAddGroup.instTopologicalAddGroup _ + continuous_mul := (QuotientRing.quotientMap_coe_coe N).continuous_iff.2 <| + continuous_quot_mk.comp continuous_mul end CommRing diff --git a/Mathlib/Topology/Algebra/SeparationQuotient.lean b/Mathlib/Topology/Algebra/SeparationQuotient.lean index 140e089dc9563..83775bba6cbe3 100644 --- a/Mathlib/Topology/Algebra/SeparationQuotient.lean +++ b/Mathlib/Topology/Algebra/SeparationQuotient.lean @@ -3,8 +3,9 @@ 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.Topology.Algebra.Module.Basic import Mathlib.LinearAlgebra.Basis.VectorSpace +import Mathlib.Topology.Algebra.Module.Basic +import Mathlib.Topology.Maps.OpenQuotient /-! # Algebraic operations on `SeparationQuotient` @@ -63,6 +64,12 @@ instance instIsScalarTower [SMul M N] [ContinuousConstSMul N X] [IsScalarTower M end SMul +instance instContinuousSMul {M X : Type*} [SMul M X] [TopologicalSpace M] [TopologicalSpace X] + [ContinuousSMul M X] : ContinuousSMul M (SeparationQuotient X) where + continuous_smul := by + rw [(IsOpenQuotientMap.id.prodMap isOpenQuotientMap_mk).quotientMap.continuous_iff] + exact continuous_mk.comp continuous_smul + instance instSMulZeroClass {M X : Type*} [Zero X] [SMulZeroClass M X] [TopologicalSpace X] [ContinuousConstSMul M X] : SMulZeroClass M (SeparationQuotient X) := ZeroHom.smulZeroClass ⟨mk, mk_zero⟩ mk_smul @@ -190,6 +197,17 @@ instance instCommGroup [CommGroup G] [TopologicalGroup G] : CommGroup (Separatio end Group +section UniformGroup + +@[to_additive] +instance instUniformGroup {G : Type*} [Group G] [UniformSpace G] [UniformGroup G] : + UniformGroup (SeparationQuotient G) where + uniformContinuous_div := by + rw [uniformContinuous_dom₂] + exact uniformContinuous_mk.comp uniformContinuous_div + +end UniformGroup + section MonoidWithZero variable {M₀ : Type*} [TopologicalSpace M₀] @@ -315,6 +333,12 @@ instance instCommRing [CommRing R] [TopologicalRing R] : surjective_mk.commRing mk mk_zero mk_one mk_add mk_mul mk_neg mk_sub mk_smul mk_smul mk_pow mk_natCast mk_intCast +/-- `SeparationQuotient.mk` as a `RingHom`. -/ +@[simps] +def mkRingHom [NonAssocSemiring R] [TopologicalSemiring R] : R →+* SeparationQuotient R where + toFun := mk + map_one' := mk_one; map_zero' := mk_zero; map_add' := mk_add; map_mul' := mk_mul + end Ring section DistribSMul @@ -357,6 +381,21 @@ def mkCLM : M →L[R] SeparationQuotient M where end Module +section Algebra +variable {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] + [TopologicalSpace A] [TopologicalSemiring A] [ContinuousConstSMul R A] + +instance instAlgebra : Algebra R (SeparationQuotient A) where + toRingHom := mkRingHom.comp (algebraMap R A) + commutes' r := Quotient.ind fun a => congrArg _ <| Algebra.commutes r a + smul_def' r := Quotient.ind fun a => congrArg _ <| Algebra.smul_def r a + +@[simp] +theorem mk_algebraMap (r : R) : mk (algebraMap R A r) = algebraMap R (SeparationQuotient A) r := + rfl + +end Algebra + section VectorSpace variable (K E : Type*) [DivisionRing K] [AddCommGroup E] [Module K E] @@ -391,6 +430,14 @@ theorem mk_outCLM (x : SeparationQuotient E) : mk (outCLM K E x) = x := @[simp] theorem mk_comp_outCLM : mk ∘ outCLM K E = id := funext (mk_outCLM K) +variable {K} in +theorem postcomp_mkCLM_surjective {L : Type*} [Semiring L] (σ : L →+* K) + (F : Type*) [AddCommMonoid F] [Module L F] [TopologicalSpace F] : + Function.Surjective ((mkCLM K E).comp : (F →SL[σ] E) → (F →SL[σ] SeparationQuotient E)) := by + intro f + use (outCLM K E).comp f + rw [← ContinuousLinearMap.comp_assoc, mkCLM_comp_outCLM, ContinuousLinearMap.id_comp] + /-- The `SeparationQuotient.outCLM K E` map is a topological embedding. -/ theorem outCLM_embedding : Embedding (outCLM K E) := Function.LeftInverse.embedding (mk_outCLM K) continuous_mk (map_continuous _) @@ -405,16 +452,22 @@ section VectorSpaceUniform variable (K E : Type*) [DivisionRing K] [AddCommGroup E] [Module K E] [UniformSpace E] [UniformAddGroup E] [ContinuousConstSMul K E] -theorem outCLM_uniformInducing : UniformInducing (outCLM K E) := by - rw [← uniformInducing_mk.uniformInducing_comp_iff, mk_comp_outCLM] - exact uniformInducing_id +theorem outCLM_isUniformInducing : IsUniformInducing (outCLM K E) := by + rw [← isUniformInducing_mk.isUniformInducing_comp_iff, mk_comp_outCLM] + exact .id -theorem outCLM_uniformEmbedding : UniformEmbedding (outCLM K E) where +@[deprecated (since := "2024-10-05")] +alias outCLM_uniformInducing := outCLM_isUniformInducing + +theorem outCLM_isUniformEmbedding : IsUniformEmbedding (outCLM K E) where inj := outCLM_injective K E - toUniformInducing := outCLM_uniformInducing K E + toIsUniformInducing := outCLM_isUniformInducing K E + +@[deprecated (since := "2024-10-01")] +alias outCLM_uniformEmbedding := outCLM_isUniformEmbedding theorem outCLM_uniformContinuous : UniformContinuous (outCLM K E) := - (outCLM_uniformInducing K E).uniformContinuous + (outCLM_isUniformInducing K E).uniformContinuous end VectorSpaceUniform diff --git a/Mathlib/Topology/Algebra/Star.lean b/Mathlib/Topology/Algebra/Star.lean index deb57a790041b..88af814e80c6e 100644 --- a/Mathlib/Topology/Algebra/Star.lean +++ b/Mathlib/Topology/Algebra/Star.lean @@ -6,7 +6,7 @@ Authors: Eric Wieser import Mathlib.Algebra.Star.Pi import Mathlib.Algebra.Star.Prod import Mathlib.Topology.Algebra.Constructions -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Defs /-! # Continuity of `star` diff --git a/Mathlib/Topology/Algebra/UniformField.lean b/Mathlib/Topology/Algebra/UniformField.lean index 059b0ae0cacfb..da3fb454151fa 100644 --- a/Mathlib/Topology/Algebra/UniformField.lean +++ b/Mathlib/Topology/Algebra/UniformField.lean @@ -55,17 +55,17 @@ namespace UniformSpace namespace Completion instance (priority := 100) [T0Space K] : Nontrivial (hat K) := - ⟨⟨0, 1, fun h => zero_ne_one <| (uniformEmbedding_coe K).inj h⟩⟩ + ⟨⟨0, 1, fun h => zero_ne_one <| (isUniformEmbedding_coe K).inj h⟩⟩ variable {K} /-- extension of inversion to the completion of a field. -/ def hatInv : hat K → hat K := - denseInducing_coe.extend fun x : K => (↑x⁻¹ : hat K) + isDenseInducing_coe.extend fun x : K => (↑x⁻¹ : hat K) theorem continuous_hatInv [CompletableTopField K] {x : hat K} (h : x ≠ 0) : ContinuousAt hatInv x := by - refine denseInducing_coe.continuousAt_extend ?_ + refine isDenseInducing_coe.continuousAt_extend ?_ apply mem_of_superset (compl_singleton_mem_nhds h) intro y y_ne rw [mem_compl_singleton_iff] at y_ne @@ -77,13 +77,13 @@ theorem continuous_hatInv [CompletableTopField K] {x : hat K} (h : x ≠ 0) : rw [this, ← Filter.map_map] apply Cauchy.map _ (Completion.uniformContinuous_coe K) apply CompletableTopField.nice - · haveI := denseInducing_coe.comap_nhds_neBot y + · haveI := isDenseInducing_coe.comap_nhds_neBot y apply cauchy_nhds.comap rw [Completion.comap_coe_eq_uniformity] · have eq_bot : 𝓝 (0 : hat K) ⊓ 𝓝 y = ⊥ := by by_contra h exact y_ne (eq_of_nhds_neBot <| neBot_iff.mpr h).symm - erw [denseInducing_coe.nhds_eq_comap (0 : K), ← Filter.comap_inf, eq_bot] + erw [isDenseInducing_coe.nhds_eq_comap (0 : K), ← Filter.comap_inf, eq_bot] exact comap_bot open Classical in @@ -97,7 +97,7 @@ instance instInvCompletion : Inv (hat K) := variable [TopologicalDivisionRing K] theorem hatInv_extends {x : K} (h : x ≠ 0) : hatInv (x : hat K) = ↑(x⁻¹ : K) := - denseInducing_coe.extend_eq_at ((continuous_coe K).continuousAt.comp (continuousAt_inv₀ h)) + isDenseInducing_coe.extend_eq_at ((continuous_coe K).continuousAt.comp (continuousAt_inv₀ h)) variable [CompletableTopField K] @@ -111,7 +111,7 @@ theorem coe_inv (x : K) : (x : hat K)⁻¹ = ((x⁻¹ : K) : hat K) := by · conv_lhs => dsimp [Inv.inv] rw [if_neg] · exact hatInv_extends h - · exact fun H => h (denseEmbedding_coe.inj H) + · exact fun H => h (isDenseEmbedding_coe.inj H) variable [UniformAddGroup K] @@ -126,7 +126,7 @@ theorem mul_hatInv_cancel {x : hat K} (x_ne : x ≠ 0) : x * hatInv x = 1 := by continuous_id.continuousAt.prod (continuous_hatInv x_ne) exact (_root_.continuous_mul.continuousAt.comp this : _) have clo : x ∈ closure (c '' {0}ᶜ) := by - have := denseInducing_coe.dense x + have := isDenseInducing_coe.dense x rw [← image_univ, show (univ : Set K) = {0} ∪ {0}ᶜ from (union_compl_self _).symm, image_union] at this apply mem_closure_of_mem_closure_union this @@ -145,7 +145,7 @@ theorem mul_hatInv_cancel {x : hat K} (x_ne : x ≠ 0) : x * hatInv x = 1 := by rwa [closure_singleton, mem_singleton_iff] at fxclo instance instField : Field (hat K) where - exists_pair_ne := ⟨0, 1, fun h => zero_ne_one ((uniformEmbedding_coe K).inj h)⟩ + exists_pair_ne := ⟨0, 1, fun h => zero_ne_one ((isUniformEmbedding_coe K).inj h)⟩ mul_inv_cancel := fun x x_ne => by simp only [Inv.inv, if_neg x_ne, mul_hatInv_cancel x_ne] inv_zero := by simp only [Inv.inv, ite_true] -- TODO: use a better defeq @@ -176,7 +176,7 @@ variable (L : Type*) [Field L] [UniformSpace L] [CompletableTopField L] instance Subfield.completableTopField (K : Subfield L) : CompletableTopField K where nice F F_cau inf_F := by let i : K →+* L := K.subtype - have hi : UniformInducing i := uniformEmbedding_subtype_val.toUniformInducing + have hi : IsUniformInducing i := isUniformEmbedding_subtype_val.isUniformInducing rw [← hi.cauchy_map_iff] at F_cau ⊢ rw [map_comm (show (i ∘ fun x => x⁻¹) = (fun x => x⁻¹) ∘ i by ext; rfl)] apply CompletableTopField.nice _ F_cau @@ -201,12 +201,12 @@ variable {α β : Type*} [Field β] [b : UniformSpace β] [CompletableTopField /-- The pullback of a completable topological field along a uniform inducing ring homomorphism is a completable topological field. -/ -theorem UniformInducing.completableTopField +theorem IsUniformInducing.completableTopField [UniformSpace α] [T0Space α] - {f : α →+* β} (hf : UniformInducing f) : + {f : α →+* β} (hf : IsUniformInducing f) : CompletableTopField α := by refine CompletableTopField.mk (fun F F_cau inf_F => ?_) - rw [← UniformInducing.cauchy_map_iff hf] at F_cau ⊢ + rw [← IsUniformInducing.cauchy_map_iff hf] at F_cau ⊢ have h_comm : (f ∘ fun x => x⁻¹) = (fun x => x⁻¹) ∘ f := by ext; simp only [Function.comp_apply, map_inv₀, Subfield.coe_inv] rw [Filter.map_comm h_comm] diff --git a/Mathlib/Topology/Algebra/UniformGroup.lean b/Mathlib/Topology/Algebra/UniformGroup.lean index f6f8cdc90796d..c05bd7340d340 100644 --- a/Mathlib/Topology/Algebra/UniformGroup.lean +++ b/Mathlib/Topology/Algebra/UniformGroup.lean @@ -179,13 +179,16 @@ theorem uniformity_translate_mul (a : α) : ((𝓤 α).map fun x : α × α => ( ) @[to_additive] -theorem uniformEmbedding_translate_mul (a : α) : UniformEmbedding fun x : α => x * a := +theorem isUniformEmbedding_translate_mul (a : α) : IsUniformEmbedding fun x : α => x * a := { comap_uniformity := by nth_rw 1 [← uniformity_translate_mul a, comap_map] rintro ⟨p₁, p₂⟩ ⟨q₁, q₂⟩ simp only [Prod.mk.injEq, mul_left_inj, imp_self] inj := mul_left_injective a } +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_translate_mul := isUniformEmbedding_translate_mul + namespace MulOpposite @[to_additive] @@ -222,18 +225,21 @@ theorem uniformGroup_inf {u₁ u₂ : UniformSpace β} (h₁ : @UniformGroup β cases b <;> assumption @[to_additive] -lemma UniformInducing.uniformGroup {γ : Type*} [Group γ] [UniformSpace γ] [UniformGroup γ] +lemma IsUniformInducing.uniformGroup {γ : Type*} [Group γ] [UniformSpace γ] [UniformGroup γ] [UniformSpace β] {F : Type*} [FunLike F β γ] [MonoidHomClass F β γ] - (f : F) (hf : UniformInducing f) : + (f : F) (hf : IsUniformInducing f) : UniformGroup β where uniformContinuous_div := by simp_rw [hf.uniformContinuous_iff, Function.comp_def, map_div] - exact uniformContinuous_div.comp (hf.uniformContinuous.prod_map hf.uniformContinuous) + exact uniformContinuous_div.comp (hf.uniformContinuous.prodMap hf.uniformContinuous) + +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformGroup := IsUniformInducing.uniformGroup @[to_additive] protected theorem UniformGroup.comap {γ : Type*} [Group γ] {u : UniformSpace γ} [UniformGroup γ] {F : Type*} [FunLike F β γ] [MonoidHomClass F β γ] (f : F) : @UniformGroup β (u.comap f) _ := - letI : UniformSpace β := u.comap f; UniformInducing.uniformGroup f ⟨rfl⟩ + letI : UniformSpace β := u.comap f; IsUniformInducing.uniformGroup f ⟨rfl⟩ end LatticeOps @@ -624,7 +630,7 @@ variable [TopologicalSpace β] [Group β] variable [FunLike hom β α] [MonoidHomClass hom β α] {e : hom} @[to_additive] -theorem tendsto_div_comap_self (de : DenseInducing e) (x₀ : α) : +theorem tendsto_div_comap_self (de : IsDenseInducing e) (x₀ : α) : Tendsto (fun t : β × β => t.2 / t.1) ((comap fun p : β × β => (e p.1, e p.2)) <| 𝓝 (x₀, x₀)) (𝓝 1) := by have comm : ((fun x : α × α => x.2 / x.1) ∘ fun t : β × β => (e t.1, e t.2)) = @@ -638,7 +644,7 @@ theorem tendsto_div_comap_self (de : DenseInducing e) (x₀ : α) : end -namespace DenseInducing +namespace IsDenseInducing variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} variable {G : Type*} @@ -650,8 +656,8 @@ variable [TopologicalSpace β] [AddCommGroup β] variable [TopologicalSpace γ] [AddCommGroup γ] [TopologicalAddGroup γ] variable [TopologicalSpace δ] [AddCommGroup δ] variable [UniformSpace G] [AddCommGroup G] -variable {e : β →+ α} (de : DenseInducing e) -variable {f : δ →+ γ} (df : DenseInducing f) +variable {e : β →+ α} (de : IsDenseInducing e) +variable {f : δ →+ γ} (df : IsDenseInducing f) variable {φ : β →+ δ →+ G} variable (hφ : Continuous (fun p : β × δ => φ p.1 p.2)) variable {W' : Set G} (W'_nhd : W' ∈ 𝓝 (0 : G)) @@ -725,21 +731,21 @@ private theorem extend_Z_bilin_key (x₀ : α) (y₀ : γ) : ∃ U ∈ comap e ( have h₄ := H x₁ x₁_in x xU₁ y yV₁ y' y'V₁ exact W4 h₁ h₂ h₃ h₄ -open DenseInducing +open IsDenseInducing variable [T0Space G] [CompleteSpace G] /-- Bourbaki GT III.6.5 Theorem I: ℤ-bilinear continuous maps from dense images into a complete Hausdorff group extend by continuity. Note: Bourbaki assumes that α and β are also complete Hausdorff, but this is not necessary. -/ -theorem extend_Z_bilin : Continuous (extend (de.prod df) (fun p : β × δ => φ p.1 p.2)) := by +theorem extend_Z_bilin : Continuous (extend (de.prodMap df) (fun p : β × δ => φ p.1 p.2)) := by refine continuous_extend_of_cauchy _ ?_ rintro ⟨x₀, y₀⟩ constructor · apply NeBot.map apply comap_neBot intro U h - rcases mem_closure_iff_nhds.1 ((de.prod df).dense (x₀, y₀)) U h with ⟨x, x_in, ⟨z, z_x⟩⟩ + rcases mem_closure_iff_nhds.1 ((de.prodMap df).dense (x₀, y₀)) U h with ⟨x, x_in, ⟨z, z_x⟩⟩ exists z aesop · suffices map (fun p : (β × δ) × β × δ => (fun p : β × δ => φ p.1 p.2) p.2 - @@ -767,7 +773,7 @@ theorem extend_Z_bilin : Continuous (extend (de.prod df) (fun p : β × δ => φ rcases p with ⟨⟨x, y⟩, ⟨x', y'⟩⟩ apply h <;> tauto -end DenseInducing +end IsDenseInducing section CompleteQuotient diff --git a/Mathlib/Topology/Algebra/UniformMulAction.lean b/Mathlib/Topology/Algebra/UniformMulAction.lean index d98b4c082accb..3f0de8b6107d6 100644 --- a/Mathlib/Topology/Algebra/UniformMulAction.lean +++ b/Mathlib/Topology/Algebra/UniformMulAction.lean @@ -88,13 +88,16 @@ theorem UniformContinuous.const_smul [UniformContinuousConstSMul M X] {f : Y → (uniformContinuous_const_smul c).comp hf @[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) : +lemma IsUniformInducing.uniformContinuousConstSMul [SMul M Y] [UniformContinuousConstSMul M Y] + {f : X → Y} (hf : IsUniformInducing 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 +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformContinuousConstSMul := IsUniformInducing.uniformContinuousConstSMul + /-- 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/Algebra/UniformRing.lean b/Mathlib/Topology/Algebra/UniformRing.lean index d5096b53d82a7..7ad0d76af8d94 100644 --- a/Mathlib/Topology/Algebra/UniformRing.lean +++ b/Mathlib/Topology/Algebra/UniformRing.lean @@ -38,7 +38,7 @@ noncomputable section universe u namespace UniformSpace.Completion -open DenseInducing UniformSpace Function +open IsDenseInducing UniformSpace Function section one_and_mul variable (α : Type*) [Ring α] [UniformSpace α] @@ -47,7 +47,7 @@ instance one : One (Completion α) := ⟨(1 : α)⟩ instance mul : Mul (Completion α) := - ⟨curry <| (denseInducing_coe.prod denseInducing_coe).extend ((↑) ∘ uncurry (· * ·))⟩ + ⟨curry <| (isDenseInducing_coe.prodMap isDenseInducing_coe).extend ((↑) ∘ uncurry (· * ·))⟩ @[norm_cast] theorem coe_one : ((1 : α) : Completion α) = 1 := @@ -59,7 +59,7 @@ variable {α : Type*} [Ring α] [UniformSpace α] [TopologicalRing α] @[norm_cast] theorem coe_mul (a b : α) : ((a * b : α) : Completion α) = a * b := - ((denseInducing_coe.prod denseInducing_coe).extend_eq + ((isDenseInducing_coe.prodMap isDenseInducing_coe).extend_eq ((continuous_coe α).comp (@continuous_mul α _ _ _)) (a, b)).symm variable [UniformAddGroup α] @@ -70,7 +70,7 @@ theorem continuous_mul : Continuous fun p : Completion α × Completion α => p. apply (continuous_coe α).comp _ simp only [AddMonoidHom.coe_mul, AddMonoidHom.coe_mulLeft] exact _root_.continuous_mul - have di : DenseInducing (toCompl : α → Completion α) := denseInducing_coe + have di : IsDenseInducing (toCompl : α → Completion α) := isDenseInducing_coe convert di.extend_Z_bilin di this theorem Continuous.mul {β : Type*} [TopologicalSpace β] {f g : β → Completion α} @@ -222,7 +222,7 @@ variable {α : Type*} theorem inseparableSetoid_ring (α) [CommRing α] [TopologicalSpace α] [TopologicalRing α] : inseparableSetoid α = Submodule.quotientRel (Ideal.closure ⊥) := Setoid.ext fun x y => - addGroup_inseparable_iff.trans <| .trans (by rfl) (Submodule.quotientRel_r_def _).symm + addGroup_inseparable_iff.trans <| .trans (by rfl) (Submodule.quotientRel_def _).symm @[deprecated (since := "2024-03-09")] alias ring_sep_rel := inseparableSetoid_ring @@ -276,28 +276,28 @@ variable {γ : Type*} [UniformSpace γ] [Semiring γ] [TopologicalSemiring γ] variable [T2Space γ] [CompleteSpace γ] /-- The dense inducing extension as a ring homomorphism. -/ -noncomputable def DenseInducing.extendRingHom {i : α →+* β} {f : α →+* γ} (ue : UniformInducing i) - (dr : DenseRange i) (hf : UniformContinuous f) : β →+* γ where - toFun := (ue.denseInducing dr).extend f +noncomputable def IsDenseInducing.extendRingHom {i : α →+* β} {f : α →+* γ} + (ue : IsUniformInducing i) (dr : DenseRange i) (hf : UniformContinuous f) : β →+* γ where + toFun := (ue.isDenseInducing dr).extend f map_one' := by - convert DenseInducing.extend_eq (ue.denseInducing dr) hf.continuous 1 + convert IsDenseInducing.extend_eq (ue.isDenseInducing dr) hf.continuous 1 exacts [i.map_one.symm, f.map_one.symm] map_zero' := by - convert DenseInducing.extend_eq (ue.denseInducing dr) hf.continuous 0 <;> + convert IsDenseInducing.extend_eq (ue.isDenseInducing dr) hf.continuous 0 <;> simp only [map_zero] map_add' := by have h := (uniformContinuous_uniformly_extend ue dr hf).continuous refine fun x y => DenseRange.induction_on₂ dr ?_ (fun a b => ?_) x y · exact isClosed_eq (Continuous.comp h continuous_add) ((h.comp continuous_fst).add (h.comp continuous_snd)) - · simp_rw [← i.map_add, DenseInducing.extend_eq (ue.denseInducing dr) hf.continuous _, + · simp_rw [← i.map_add, IsDenseInducing.extend_eq (ue.isDenseInducing dr) hf.continuous _, ← f.map_add] map_mul' := by have h := (uniformContinuous_uniformly_extend ue dr hf).continuous refine fun x y => DenseRange.induction_on₂ dr ?_ (fun a b => ?_) x y · exact isClosed_eq (Continuous.comp h continuous_mul) ((h.comp continuous_fst).mul (h.comp continuous_snd)) - · simp_rw [← i.map_mul, DenseInducing.extend_eq (ue.denseInducing dr) hf.continuous _, + · simp_rw [← i.map_mul, IsDenseInducing.extend_eq (ue.isDenseInducing dr) hf.continuous _, ← f.map_mul] end UniformExtension diff --git a/Mathlib/Topology/Algebra/Valued/NormedValued.lean b/Mathlib/Topology/Algebra/Valued/NormedValued.lean index dbe91b1484df4..2c9ce7c08f2c8 100644 --- a/Mathlib/Topology/Algebra/Valued/NormedValued.lean +++ b/Mathlib/Topology/Algebra/Valued/NormedValued.lean @@ -102,7 +102,7 @@ def toNormedField : NormedField L := · set δ : ℝ≥0 := hv.hom ε with hδ have hδ_pos : 0 < δ := by rw [hδ, ← _root_.map_zero hv.hom] - exact hv.strictMono (Units.zero_lt ε) + exact hv.strictMono _ (Units.zero_lt ε) use δ, hδ_pos apply subset_trans _ hε intro x hx diff --git a/Mathlib/Topology/Algebra/Valued/ValuedField.lean b/Mathlib/Topology/Algebra/Valued/ValuedField.lean index c9a159cdcd849..99151442537d6 100644 --- a/Mathlib/Topology/Algebra/Valued/ValuedField.lean +++ b/Mathlib/Topology/Algebra/Valued/ValuedField.lean @@ -187,14 +187,14 @@ open WithZeroTopology /-- The extension of the valuation of a valued field to the completion of the field. -/ noncomputable def extension : hat K → Γ₀ := - Completion.denseInducing_coe.extend (v : K → Γ₀) + Completion.isDenseInducing_coe.extend (v : K → Γ₀) theorem continuous_extension : Continuous (Valued.extension : hat K → Γ₀) := by - refine Completion.denseInducing_coe.continuous_extend ?_ + refine Completion.isDenseInducing_coe.continuous_extend ?_ intro x₀ rcases eq_or_ne x₀ 0 with (rfl | h) · refine ⟨0, ?_⟩ - erw [← Completion.denseInducing_coe.toInducing.nhds_eq_comap] + erw [← Completion.isDenseInducing_coe.toInducing.nhds_eq_comap] exact Valued.continuous_valuation.tendsto' 0 0 (map_zero v) · have preimage_one : v ⁻¹' {(1 : Γ₀)} ∈ 𝓝 (1 : K) := by have : (v (1 : K) : Γ₀) ≠ 0 := by @@ -204,7 +204,7 @@ theorem continuous_extension : Continuous (Valued.extension : hat K → Γ₀) : ext x rw [Valuation.map_one, mem_preimage, mem_singleton_iff, mem_setOf_eq] obtain ⟨V, V_in, hV⟩ : ∃ V ∈ 𝓝 (1 : hat K), ∀ x : K, (x : hat K) ∈ V → (v x : Γ₀) = 1 := by - rwa [Completion.denseInducing_coe.nhds_eq_comap, mem_comap] at preimage_one + rwa [Completion.isDenseInducing_coe.nhds_eq_comap, mem_comap] at preimage_one have : ∃ V' ∈ 𝓝 (1 : hat K), (0 : hat K) ∉ V' ∧ ∀ (x) (_ : x ∈ V') (y) (_ : y ∈ V'), x * y⁻¹ ∈ V := by have : Tendsto (fun p : hat K × hat K => p.1 * p.2⁻¹) ((𝓝 1) ×ˢ (𝓝 1)) (𝓝 1) := by @@ -265,8 +265,8 @@ theorem continuous_extension : Continuous (Valued.extension : hat K → Γ₀) : @[simp, norm_cast] theorem extension_extends (x : K) : extension (x : hat K) = v x := by - refine Completion.denseInducing_coe.extend_eq_of_tendsto ?_ - rw [← Completion.denseInducing_coe.nhds_eq_comap] + refine Completion.isDenseInducing_coe.extend_eq_of_tendsto ?_ + rw [← Completion.isDenseInducing_coe.nhds_eq_comap] exact Valued.continuous_valuation.continuousAt /-- the extension of a valuation on a division ring to its completion. -/ @@ -339,7 +339,7 @@ noncomputable instance valuedCompletion : Valued (hat K) Γ₀ where rw [this.mem_iff] exact exists_congr fun γ => by simp simp_rw [← closure_coe_completion_v_lt] - exact (hasBasis_nhds_zero K Γ₀).hasBasis_of_denseInducing Completion.denseInducing_coe + exact (hasBasis_nhds_zero K Γ₀).hasBasis_of_isDenseInducing Completion.isDenseInducing_coe -- Porting note: removed @[norm_cast] attribute due to error: -- norm_cast: badly shaped lemma, rhs can't start with coe diff --git a/Mathlib/Topology/Bases.lean b/Mathlib/Topology/Bases.lean index 033576301698e..bc50dd33b1af8 100644 --- a/Mathlib/Topology/Bases.lean +++ b/Mathlib/Topology/Bases.lean @@ -286,11 +286,6 @@ protected theorem IsTopologicalBasis.continuous_iff {β : Type*} [TopologicalSpa Continuous f ↔ ∀ s ∈ B, IsOpen (f ⁻¹' s) := by rw [hB.eq_generateFrom, continuous_generateFrom_iff] -@[deprecated (since := "2023-12-24")] -protected theorem IsTopologicalBasis.continuous {β : Type*} [TopologicalSpace β] {B : Set (Set β)} - (hB : IsTopologicalBasis B) (f : α → β) (hf : ∀ s ∈ B, IsOpen (f ⁻¹' s)) : Continuous f := - hB.continuous_iff.2 hf - variable (α) /-- A separable space is one with a countable dense subset, available through diff --git a/Mathlib/Topology/Basic.lean b/Mathlib/Topology/Basic.lean index 388fd5adcf054..55a8aa4aec4ec 100644 --- a/Mathlib/Topology/Basic.lean +++ b/Mathlib/Topology/Basic.lean @@ -799,9 +799,11 @@ theorem frequently_frequently_nhds {p : X → Prop} : simp only [not_frequently, eventually_eventually_nhds] @[simp] -theorem eventually_mem_nhds : (∀ᶠ x' in 𝓝 x, s ∈ 𝓝 x') ↔ s ∈ 𝓝 x := +theorem eventually_mem_nhds_iff : (∀ᶠ x' in 𝓝 x, s ∈ 𝓝 x') ↔ s ∈ 𝓝 x := eventually_eventually_nhds +@[deprecated (since := "2024-10-04")] alias eventually_mem_nhds := eventually_mem_nhds_iff + @[simp] theorem nhds_bind_nhds : (𝓝 x).bind 𝓝 = 𝓝 x := Filter.ext fun _ => eventually_eventually_nhds @@ -851,13 +853,13 @@ theorem tendsto_atTop_nhds [Nonempty α] [SemilatticeSup α] {f : α → X} : theorem tendsto_const_nhds {f : Filter α} : Tendsto (fun _ : α => x) f (𝓝 x) := tendsto_nhds.mpr fun _ _ ha => univ_mem' fun _ => ha -theorem tendsto_atTop_of_eventually_const {ι : Type*} [SemilatticeSup ι] [Nonempty ι] +theorem tendsto_atTop_of_eventually_const {ι : Type*} [Preorder ι] {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 + Tendsto.congr' (EventuallyEq.symm ((eventually_ge_atTop i₀).mono h)) tendsto_const_nhds -theorem tendsto_atBot_of_eventually_const {ι : Type*} [SemilatticeInf ι] [Nonempty ι] +theorem tendsto_atBot_of_eventually_const {ι : Type*} [Preorder ι] {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 + tendsto_atTop_of_eventually_const (ι := ιᵒᵈ) h theorem pure_le_nhds : pure ≤ (𝓝 : X → Filter X) := fun _ _ hs => mem_pure.2 <| mem_of_mem_nhds hs @@ -1400,7 +1402,7 @@ theorem ContinuousAt.eventually_mem {f : X → Y} {x : X} (hf : ContinuousAt f x (hs : s ∈ 𝓝 (f x)) : ∀ᶠ y in 𝓝 x, f y ∈ s := hf hs -/-- If a function ``f` tends to somewhere other than `𝓝 (f x)` at `x`, +/-- If a function `f` tends to somewhere other than `𝓝 (f x)` at `x`, then `f` is not continuous at `x` -/ lemma not_continuousAt_of_tendsto {f : X → Y} {l₁ : Filter X} {l₂ : Filter Y} {x : X} diff --git a/Mathlib/Topology/CWComplex.lean b/Mathlib/Topology/CWComplex.lean new file mode 100644 index 0000000000000..8dae230580f73 --- /dev/null +++ b/Mathlib/Topology/CWComplex.lean @@ -0,0 +1,100 @@ +/- +Copyright (c) 2024 Elliot Dean Young and Jiazhen Xia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jiazhen Xia, Elliot Dean Young +-/ +import Mathlib.Topology.Category.TopCat.Limits.Basic +import Mathlib.Topology.Category.TopCat.Sphere +import Mathlib.CategoryTheory.Limits.Shapes.Products +import Mathlib.CategoryTheory.Functor.OfSequence + +/-! +# CW-complexes + +This file defines (relative) CW-complexes. + +## Main definitions + +* `RelativeCWComplex`: A relative CW-complex is the colimit of an expanding sequence of subspaces + `sk i` (called the $(i-1)$-skeleton) for `i ≥ 0`, where `sk 0` (i.e., the $(-1)$-skeleton) is an + arbitrary topological space, and each `sk (n + 1)` (i.e., the $n$-skeleton) is obtained from + `sk n` (i.e., the $(n-1)$-skeleton) by attaching `n`-disks. + +* `CWComplex`: A CW-complex is a relative CW-complex whose `sk 0` (i.e., $(-1)$-skeleton) is empty. + +## References + +* [R. Fritsch and R. Piccinini, *Cellular Structures in Topology*][fritsch-piccinini1990] +* The definition of CW-complexes follows David Wärn's suggestion on + [Zulip](https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/Do.20we.20have.20CW.20complexes.3F/near/231769080). +-/ + +open CategoryTheory TopCat + +universe u + +namespace RelativeCWComplex + +/-- The inclusion map from the `n`-sphere to the `(n + 1)`-disk. (For `n = -1`, this +involves the empty space `𝕊 (-1)`. This is the reason why `sphere` takes `n : ℤ` as +an input rather than `n : ℕ`.) -/ +def sphereInclusion (n : ℤ) : 𝕊 n ⟶ 𝔻 (n + 1) where + toFun := fun ⟨p, hp⟩ ↦ ⟨p, le_of_eq hp⟩ + continuous_toFun := ⟨fun t ⟨s, ⟨r, hro, hrs⟩, hst⟩ ↦ by + rw [isOpen_induced_iff, ← hst, ← hrs] + tauto⟩ + +/-- A type witnessing that `X'` is obtained from `X` by attaching generalized cells `f : S ⟶ D` -/ +structure AttachGeneralizedCells {S D : TopCat.{u}} (f : S ⟶ D) (X X' : TopCat.{u}) where + /-- The index type over the generalized cells -/ + cells : Type u + /-- An attaching map for each generalized cell -/ + attachMaps : cells → (S ⟶ X) + /-- `X'` is the pushout of `∐ S ⟶ X` and `∐ S ⟶ ∐ D`. -/ + iso_pushout : X' ≅ Limits.pushout (Limits.Sigma.desc attachMaps) (Limits.Sigma.map fun _ ↦ f) + +/-- A type witnessing that `X'` is obtained from `X` by attaching `(n + 1)`-disks -/ +def AttachCells (n : ℤ) := AttachGeneralizedCells (sphereInclusion n) + +end RelativeCWComplex + +/-- A relative CW-complex consists of an expanding sequence of subspaces `sk i` (called the +$(i-1)$-skeleton) for `i ≥ 0`, where `sk 0` (i.e., the $(-1)$-skeleton) is an arbitrary topological +space, and each `sk (n + 1)` (i.e., the `n`-skeleton) is obtained from `sk n` (i.e., the +$(n-1)$-skeleton) by attaching `n`-disks. -/ +structure RelativeCWComplex where + /-- The skeletons. Note: `sk i` is usually called the $(i-1)$-skeleton in the math literature. -/ + sk : ℕ → TopCat.{u} + /-- Each `sk (n + 1)` (i.e., the $n$-skeleton) is obtained from `sk n` + (i.e., the $(n-1)$-skeleton) by attaching `n`-disks. -/ + attachCells (n : ℕ) : RelativeCWComplex.AttachCells ((n : ℤ) - 1) (sk n) (sk (n + 1)) + +/-- A CW-complex is a relative CW-complex whose `sk 0` (i.e., $(-1)$-skeleton) is empty. -/ +structure CWComplex extends RelativeCWComplex.{u} where + /-- `sk 0` (i.e., the $(-1)$-skeleton) is empty. -/ + isEmpty_sk_zero : IsEmpty (sk 0) + +namespace RelativeCWComplex + +noncomputable section Topology + +/-- The inclusion map from `X` to `X'`, when `X'` is obtained from `X` +by attaching generalized cells `f : S ⟶ D`. -/ +def AttachGeneralizedCells.inclusion {S D : TopCat.{u}} {f : S ⟶ D} {X X' : TopCat.{u}} + (att : AttachGeneralizedCells f X X') : X ⟶ X' := + Limits.pushout.inl _ _ ≫ att.iso_pushout.inv + +/-- The inclusion map from `sk n` (i.e., the $(n-1)$-skeleton) to `sk (n + 1)` (i.e., the +$n$-skeleton) of a relative CW-complex -/ +def skInclusion (X : RelativeCWComplex.{u}) (n : ℕ) : X.sk n ⟶ X.sk (n + 1) := + (X.attachCells n).inclusion + +/-- The topology on a relative CW-complex -/ +def toTopCat (X : RelativeCWComplex.{u}) : TopCat.{u} := + Limits.colimit (Functor.ofSequence X.skInclusion) + +instance : Coe RelativeCWComplex TopCat where coe X := toTopCat X + +end Topology + +end RelativeCWComplex diff --git a/Mathlib/Topology/Category/CompHaus/Projective.lean b/Mathlib/Topology/Category/CompHaus/Projective.lean index 97532c9b45d96..def47e5abc989 100644 --- a/Mathlib/Topology/Category/CompHaus/Projective.lean +++ b/Mathlib/Topology/Category/CompHaus/Projective.lean @@ -51,8 +51,9 @@ instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X) w -- The next two lines should not be needed. 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, id_comp] + -- This used to be `rw`, but we need `rw; rfl` after leanprover/lean4#2644 + rw [comp_assoc, ultrafilter_extend_extends, ← comp_assoc, this, id_comp] + rfl /-- For any compact Hausdorff space `X`, the natural map `Ultrafilter X → X` is a projective presentation. -/ diff --git a/Mathlib/Topology/Category/CompHausLike/Basic.lean b/Mathlib/Topology/Category/CompHausLike/Basic.lean index 045cd7441ef88..ca9de369a082e 100644 --- a/Mathlib/Topology/Category/CompHausLike/Basic.lean +++ b/Mathlib/Topology/Category/CompHausLike/Basic.lean @@ -255,4 +255,13 @@ def isoEquivHomeo {X Y : CompHausLike.{u} P} : (X ≅ Y) ≃ (X ≃ₜ Y) where left_inv _ := rfl right_inv _ := rfl +/-- A constant map as a morphism in `CompHausLike` -/ +def const {P : TopCat.{u} → Prop} + (T : CompHausLike.{u} P) {S : CompHausLike.{u} P} (s : S) : T ⟶ S := + ContinuousMap.const _ s + +lemma const_comp {P : TopCat.{u} → Prop} {S T U : CompHausLike.{u} P} + (s : S) (g : S ⟶ U) : T.const s ≫ g = T.const (g s) := + rfl + end CompHausLike diff --git a/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean index ec86cd6d90865..fc574ef66ea35 100644 --- a/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean +++ b/Mathlib/Topology/Category/CompHausLike/SigmaComparison.lean @@ -38,10 +38,6 @@ values on the components. def sigmaComparison : X.obj ⟨(of P ((a : α) × σ a))⟩ ⟶ ((a : α) → X.obj ⟨of P (σ a)⟩) := fun x a ↦ X.map ⟨Sigma.mk a, continuous_sigmaMk⟩ x -noncomputable instance : PreservesLimitsOfShape (Discrete α) X := - letI : Fintype α := Fintype.ofFinite _ - preservesFiniteProductsOfPreservesBinaryAndTerminal X α - theorem sigmaComparison_eq_comp_isos : sigmaComparison X σ = (X.mapIso (opCoproductIsoProduct' (finiteCoproduct.isColimit.{u, u} (fun a ↦ of P (σ a))) diff --git a/Mathlib/Topology/Category/LightProfinite/Basic.lean b/Mathlib/Topology/Category/LightProfinite/Basic.lean index 40d42567504e8..56a5871cbcd22 100644 --- a/Mathlib/Topology/Category/LightProfinite/Basic.lean +++ b/Mathlib/Topology/Category/LightProfinite/Basic.lean @@ -119,6 +119,11 @@ instance : FintypeCat.toLightProfinite.Faithful := instance : FintypeCat.toLightProfinite.Full := FintypeCat.toLightProfiniteFullyFaithful.full +instance (X : FintypeCat.{u}) : Fintype (FintypeCat.toLightProfinite.obj X) := + inferInstanceAs (Fintype X) + +instance (X : FintypeCat.{u}) : Fintype (LightProfinite.of X) := inferInstanceAs (Fintype X) + end DiscreteTopology namespace LightProfinite diff --git a/Mathlib/Topology/Category/LightProfinite/Extend.lean b/Mathlib/Topology/Category/LightProfinite/Extend.lean index bed0658153636..4f7e5eb315b90 100644 --- a/Mathlib/Topology/Category/LightProfinite/Extend.lean +++ b/Mathlib/Topology/Category/LightProfinite/Extend.lean @@ -118,7 +118,7 @@ then `cone G c.pt` is a limit cone. -/ noncomputable def isLimitCone (hc : IsLimit c) [∀ i, Epi (c.π.app i)] (hc' : IsLimit <| G.mapCone c) : - IsLimit (cone G c.pt) := (functor_initial c hc).isLimitWhiskerEquiv _ hc' + IsLimit (cone G c.pt) := (functor_initial c hc).isLimitWhiskerEquiv _ _ hc' end Limit @@ -158,7 +158,7 @@ noncomputable def isColimitCocone (hc : IsLimit c) [∀ i, Epi (c.π.app i)] (hc' : IsColimit <| G.mapCocone c.op) : IsColimit (cocone G c.pt) := haveI := functorOp_final c hc - (Functor.final_comp (opOpEquivalence ℕ).functor (functorOp c)).isColimitWhiskerEquiv _ hc' + (Functor.final_comp (opOpEquivalence ℕ).functor (functorOp c)).isColimitWhiskerEquiv _ _ hc' end Colimit diff --git a/Mathlib/Topology/Category/Profinite/Basic.lean b/Mathlib/Topology/Category/Profinite/Basic.lean index c11d6fa087fbc..fdde9e65b27a8 100644 --- a/Mathlib/Topology/Category/Profinite/Basic.lean +++ b/Mathlib/Topology/Category/Profinite/Basic.lean @@ -157,6 +157,10 @@ instance : FintypeCat.toProfinite.Faithful := FintypeCat.toProfiniteFullyFaithfu instance : FintypeCat.toProfinite.Full := FintypeCat.toProfiniteFullyFaithful.full +instance (X : FintypeCat) : Fintype (FintypeCat.toProfinite.obj X) := inferInstanceAs (Fintype X) + +instance (X : FintypeCat) : Fintype (Profinite.of X) := inferInstanceAs (Fintype X) + end DiscreteTopology end Profinite diff --git a/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean b/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean index acb77ad51c59d..fb9774c83263f 100644 --- a/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean +++ b/Mathlib/Topology/Category/Profinite/CofilteredLimit.lean @@ -168,8 +168,7 @@ theorem exists_locallyConstant_finite_nonempty {α : Type*} [Finite α] [Nonempt dsimp [σ] have h1 : ι (f x) = gg (C.π.app j x) := by change f.map (fun a b => if a = b then (0 : Fin 2) else 1) x = _ - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [h] + rw [h] rfl have h2 : ∃ a : α, ι a = gg (C.π.app j x) := ⟨f x, h1⟩ -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 diff --git a/Mathlib/Topology/Category/Profinite/Extend.lean b/Mathlib/Topology/Category/Profinite/Extend.lean index 8db0cc4dd84e9..2c00a5e5808e0 100644 --- a/Mathlib/Topology/Category/Profinite/Extend.lean +++ b/Mathlib/Topology/Category/Profinite/Extend.lean @@ -141,7 +141,7 @@ then `cone G c.pt` is a limit cone. -/ noncomputable def isLimitCone (hc : IsLimit c) [∀ i, Epi (c.π.app i)] (hc' : IsLimit <| G.mapCone c) : - IsLimit (cone G c.pt) := (functor_initial c hc).isLimitWhiskerEquiv _ hc' + IsLimit (cone G c.pt) := (functor_initial c hc).isLimitWhiskerEquiv _ _ hc' end Limit @@ -177,7 +177,7 @@ are epimorphic, then `cocone G c.pt` is a colimit cone. -/ noncomputable def isColimitCocone (hc : IsLimit c) [∀ i, Epi (c.π.app i)] (hc' : IsColimit <| G.mapCocone c.op) : - IsColimit (cocone G c.pt) := (functorOp_final c hc).isColimitWhiskerEquiv _ hc' + IsColimit (cocone G c.pt) := (functorOp_final c hc).isColimitWhiskerEquiv _ _ hc' end Colimit diff --git a/Mathlib/Topology/Category/Profinite/Nobeling.lean b/Mathlib/Topology/Category/Profinite/Nobeling.lean index d9f4b3c3fea60..3807d5656a53a 100644 --- a/Mathlib/Topology/Category/Profinite/Nobeling.lean +++ b/Mathlib/Topology/Category/Profinite/Nobeling.lean @@ -1354,13 +1354,13 @@ theorem CC_exact {f : LocallyConstant C ℤ} (hf : Linear_CC' C hsC ho f = 0) : exact C1_projOrd C hsC ho hx₁ variable (o) in -theorem succ_mono : CategoryTheory.Mono (ModuleCat.ofHom (πs C o)) := by +theorem succ_mono : CategoryTheory.Mono (ModuleCat.asHom (πs C o)) := by rw [ModuleCat.mono_iff_injective] exact injective_πs _ _ include hC in theorem succ_exact : - (ShortComplex.mk (ModuleCat.ofHom (πs C o)) (ModuleCat.ofHom (Linear_CC' C hsC ho)) + (ShortComplex.mk (ModuleCat.asHom (πs C o)) (ModuleCat.asHom (Linear_CC' C hsC ho)) (by ext; apply CC_comp_zero)).Exact := by rw [ShortComplex.moduleCat_exact_iff] intro f @@ -1478,7 +1478,7 @@ theorem span_sum : Set.range (eval C) = Set.range (Sum.elim theorem square_commutes : SumEval C ho ∘ Sum.inl = - ModuleCat.ofHom (πs C o) ∘ eval (π C (ord I · < o)) := by + ModuleCat.asHom (πs C o) ∘ eval (π C (ord I · < o)) := by ext l dsimp [SumEval] rw [← Products.eval_πs C (Products.prop_of_isGood _ _ l.prop)] @@ -1644,7 +1644,7 @@ theorem maxTail_isGood (l : MaxProducts C ho) rfl have hse := succ_exact C hC hsC ho rw [ShortComplex.moduleCat_exact_iff_range_eq_ker] at hse - dsimp [ModuleCat.ofHom] at hse + dsimp [ModuleCat.asHom] at hse -- Rewrite `this` using exact sequence manipulations to conclude that a term is in the range of -- the linear map `πs`: @@ -1701,8 +1701,8 @@ include hC in theorem linearIndependent_comp_of_eval (h₁ : ⊤ ≤ Submodule.span ℤ (Set.range (eval (π C (ord I · < o))))) : LinearIndependent ℤ (eval (C' C ho)) → - LinearIndependent ℤ (ModuleCat.ofHom (Linear_CC' C hsC ho) ∘ SumEval C ho ∘ Sum.inr) := by - dsimp [SumEval, ModuleCat.ofHom] + LinearIndependent ℤ (ModuleCat.asHom (Linear_CC' C hsC ho) ∘ SumEval C ho ∘ Sum.inr) := by + dsimp [SumEval, ModuleCat.asHom] erw [max_eq_eval_unapply C hsC ho] intro h let f := MaxToGood C hC hsC ho h₁ diff --git a/Mathlib/Topology/Category/Profinite/Projective.lean b/Mathlib/Topology/Category/Profinite/Projective.lean index 98eb2deeef7fc..55521c4ffef71 100644 --- a/Mathlib/Topology/Category/Profinite/Projective.lean +++ b/Mathlib/Topology/Category/Profinite/Projective.lean @@ -50,8 +50,9 @@ instance projective_ultrafilter (X : Type u) : Projective (of <| Ultrafilter X) -- Porting note: same fix as in `Topology.Category.CompHaus.Projective` 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, id_comp] + -- This used to be `rw`, but we need `rw; rfl` after leanprover/lean4#2644 + rw [comp_assoc, ultrafilter_extend_extends, ← comp_assoc, this, id_comp] + rfl /-- For any profinite `X`, the natural map `Ultrafilter X → X` is a projective presentation. -/ def projectivePresentation (X : Profinite.{u}) : ProjectivePresentation X where diff --git a/Mathlib/Topology/Category/TopCat/Basic.lean b/Mathlib/Topology/Category/TopCat/Basic.lean index 40459bf75dc71..ab44aa713d2eb 100644 --- a/Mathlib/Topology/Category/TopCat/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Patrick Massot, Kim Morrison, Mario Carneiro -/ import Mathlib.CategoryTheory.ConcreteCategory.BundledHom -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # Category instance for topological spaces @@ -56,7 +56,7 @@ instance topologicalSpaceUnbundled (X : TopCat) : TopologicalSpace X := instance instFunLike (X Y : TopCat) : FunLike (X ⟶ Y) X Y := inferInstanceAs <| FunLike C(X, Y) X Y -instance instMonoidHomClass (X Y : TopCat) : ContinuousMapClass (X ⟶ Y) X Y := +instance instContinuousMapClass (X Y : TopCat) : ContinuousMapClass (X ⟶ Y) X Y := inferInstanceAs <| ContinuousMapClass C(X, Y) X Y -- Porting note (#10618): simp can prove this; removed simp diff --git a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean index 3fcf13740229c..b476fb65fb907 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Basic.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Basic.lean @@ -70,7 +70,7 @@ def limitConeIsLimit (F : J ⥤ TopCat.{max v u}) : IsLimit (limitCone.{v,u} F) { toFun := fun x => ⟨fun j => S.π.app _ x, fun f => by dsimp - erw [← S.w f] + rw [← S.w f] rfl⟩ continuous_toFun := Continuous.subtype_mk (continuous_pi fun j => (S.π.app j).2) fun x i j f => by @@ -184,7 +184,7 @@ instance forgetPreservesColimits : PreservesColimits (forget : TopCat.{u} ⥤ Ty /-- The terminal object of `Top` is `PUnit`. -/ def isTerminalPUnit : IsTerminal (TopCat.of PUnit.{u + 1}) := haveI : ∀ X, Unique (X ⟶ TopCat.of PUnit.{u + 1}) := fun X => - ⟨⟨⟨fun _ => PUnit.unit, by continuity⟩⟩, fun f => by ext; aesop⟩ + ⟨⟨⟨fun _ => PUnit.unit, continuous_const⟩⟩, fun f => by ext; aesop⟩ Limits.IsTerminal.ofUnique _ /-- The terminal object of `Top` is `PUnit`. -/ diff --git a/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean b/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean index 7350fd1934dc2..dc77a067581bd 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Cofiltered.lean @@ -104,7 +104,7 @@ theorem isTopologicalBasis_cofiltered_limit (hC : IsLimit C) (T : ∀ j, Set (Se rw [Set.preimage_iInter] apply congrArg ext1 e - erw [Set.preimage_iInter] + rw [Set.preimage_iInter] apply congrArg ext1 he -- Porting note: needed more hand holding here @@ -113,7 +113,7 @@ theorem isTopologicalBasis_cofiltered_limit (hC : IsLimit C) (T : ∀ j, Set (Se rw [dif_pos he, ← Set.preimage_comp] apply congrFun apply congrArg - erw [← coe_comp, D.w] -- now `erw` after #13170 + rw [← coe_comp, D.w] rfl end CofilteredLimit diff --git a/Mathlib/Topology/Category/TopCat/Limits/Products.lean b/Mathlib/Topology/Category/TopCat/Limits/Products.lean index 12a0b862fc298..780074ed743fe 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Products.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Products.lean @@ -236,12 +236,12 @@ theorem range_prod_map {W X Y Z : TopCat.{u}} (f : W ⟶ Y) (g : X ⟶ Z) : · change limit.π (pair Y Z) _ ((prod.map f g) _) = _ erw [← comp_apply, Limits.prod.map_fst] change (_ ≫ _ ≫ f) _ = _ - erw [TopCat.prodIsoProd_inv_fst_assoc,TopCat.comp_app] + rw [TopCat.prodIsoProd_inv_fst_assoc,TopCat.comp_app] exact hx₁ · change limit.π (pair Y Z) _ ((prod.map f g) _) = _ erw [← comp_apply, Limits.prod.map_snd] change (_ ≫ _ ≫ g) _ = _ - erw [TopCat.prodIsoProd_inv_snd_assoc,TopCat.comp_app] + rw [TopCat.prodIsoProd_inv_snd_assoc,TopCat.comp_app] exact hx₂ theorem inducing_prod_map {W X Y Z : TopCat.{u}} {f : W ⟶ X} {g : Y ⟶ Z} (hf : Inducing f) @@ -346,8 +346,7 @@ theorem binaryCofan_isColimit_iff {X Y : TopCat} (c : BinaryCofan X Y) : refine (dif_pos ?_).trans ?_ · exact ⟨x, rfl⟩ · dsimp - conv_lhs => erw [Equiv.ofInjective_symm_apply] - rfl -- `rfl` was not needed here before #13170 + conv_lhs => rw [Equiv.ofInjective_symm_apply] · intro T f g ext x refine (dif_neg ?_).trans ?_ diff --git a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean index 7701c3fb0e265..3d1a8ae947989 100644 --- a/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean +++ b/Mathlib/Topology/Category/TopCat/Limits/Pullbacks.lean @@ -214,17 +214,14 @@ theorem range_pullback_map {W X Y Z S T : TopCat} (f₁ : W ⟶ S) (f₂ : X ⟶ erw [← comp_apply, ← comp_apply] -- now `erw` after #13170 · simp only [Category.assoc, limit.lift_π, PullbackCone.mk_π_app_one] simp only [cospan_one, pullbackIsoProdSubtype_inv_fst_assoc, comp_apply] - erw [pullbackFst_apply, hx₁] - rw [← limit.w _ WalkingCospan.Hom.inl, cospan_map_inl, comp_apply (g := g₁)] - rfl -- `rfl` was not needed before #13170 + rw [pullbackFst_apply, hx₁, ← limit.w _ WalkingCospan.Hom.inl, cospan_map_inl, + comp_apply (g := g₁)] · simp only [cospan_left, limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, pullbackIsoProdSubtype_inv_fst_assoc, comp_apply] erw [hx₁] -- now `erw` after #13170 - rfl -- `rfl` was not needed before #13170 · simp only [cospan_right, limit.lift_π, PullbackCone.mk_pt, PullbackCone.mk_π_app, pullbackIsoProdSubtype_inv_snd_assoc, comp_apply] erw [hx₂] -- now `erw` after #13170 - rfl -- `rfl` was not needed before #13170 theorem pullback_fst_range {X Y S : TopCat} (f : X ⟶ S) (g : Y ⟶ S) : Set.range (pullback.fst f g) = { x : X | ∃ y : Y, f x = g y } := by @@ -318,8 +315,7 @@ theorem fst_embedding_of_right_embedding {X Y S : TopCat} (f : X ⟶ S) {g : Y theorem embedding_of_pullback_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S} (H₁ : Embedding f) (H₂ : Embedding g) : Embedding (limit.π (cospan f g) WalkingCospan.one) := by convert H₂.comp (snd_embedding_of_left_embedding H₁ g) - erw [← coe_comp] - rw [← limit.w _ WalkingCospan.Hom.inr] + rw [← coe_comp, ← limit.w _ WalkingCospan.Hom.inr] rfl theorem snd_openEmbedding_of_left_openEmbedding {X Y S : TopCat} {f : X ⟶ S} (H : OpenEmbedding f) @@ -343,8 +339,7 @@ theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) : OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g) - erw [← coe_comp] - rw [← limit.w _ WalkingCospan.Hom.inr] + rw [← coe_comp, ← limit.w _ WalkingCospan.Hom.inr] rfl theorem fst_iso_of_right_embedding_range_subset {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S} diff --git a/Mathlib/Topology/Category/TopCat/Sphere.lean b/Mathlib/Topology/Category/TopCat/Sphere.lean new file mode 100644 index 0000000000000..b8f23e34fc643 --- /dev/null +++ b/Mathlib/Topology/Category/TopCat/Sphere.lean @@ -0,0 +1,39 @@ +/- +Copyright (c) 2024 Elliot Dean Young and Jiazhen Xia. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jiazhen Xia, Elliot Dean Young +-/ + +import Mathlib.Analysis.InnerProductSpace.PiL2 +import Mathlib.Topology.Category.TopCat.Basic + +/-! +# Euclidean spheres + +This files defines the `n`-sphere `𝕊 n` and the `n`-disk `𝔻` as objects in `TopCat`. +The parameter `n` is in `ℤ` so as to facilitate the definition of +CW-complexes (see the file `Topology.CWComplex`). + +-/ + +universe u + +namespace TopCat + +/-- The `n`-sphere is the set of points in ℝⁿ⁺¹ whose norm equals `1`, +endowed with the subspace topology. -/ +noncomputable def sphere (n : ℤ) : TopCat.{u} := + TopCat.of <| ULift <| Metric.sphere (0 : EuclideanSpace ℝ <| Fin <| (n + 1).toNat) 1 + +/-- The `n`-disk is the set of points in ℝⁿ whose norm is at most `1`, +endowed with the subspace topology. -/ +noncomputable def disk (n : ℤ) : TopCat.{u} := + TopCat.of <| ULift <| Metric.closedBall (0 : EuclideanSpace ℝ <| Fin <| n.toNat) 1 + +/-- `𝕊 n` denotes the `n`-sphere. -/ +scoped prefix:arg "𝕊 " => sphere + +/-- `𝔻 n` denotes the `n`-disk. -/ +scoped prefix:arg "𝔻 " => disk + +end TopCat diff --git a/Mathlib/Topology/Category/UniformSpace.lean b/Mathlib/Topology/Category/UniformSpace.lean index 0b3083f80e4e6..dc6f68256827c 100644 --- a/Mathlib/Topology/Category/UniformSpace.lean +++ b/Mathlib/Topology/Category/UniformSpace.lean @@ -191,7 +191,7 @@ noncomputable def adj : completionFunctor ⊣ forget₂ CpltSepUniformSpace Unif { homEquiv := fun X Y => { toFun := fun f => completionHom X ≫ f invFun := fun f => extensionHom f - left_inv := fun f => by dsimp; erw [extension_comp_coe] + left_inv := fun f => by dsimp; rw [extension_comp_coe] right_inv := fun f => by apply Subtype.eq; funext x; cases f exact @Completion.extension_coe _ _ _ _ _ (CpltSepUniformSpace.t0Space _) diff --git a/Mathlib/Topology/Clopen.lean b/Mathlib/Topology/Clopen.lean index c560e10009cd9..ff10a04698b33 100644 --- a/Mathlib/Topology/Clopen.lean +++ b/Mathlib/Topology/Clopen.lean @@ -102,6 +102,10 @@ theorem isClopen_inter_of_disjoint_cover_clopen {s a b : Set X} (h : IsClopen s) rintro x ⟨hx₁, hx₂⟩ exact ⟨hx₁, by simpa [not_mem_of_mem_compl hx₂] using cover hx₁⟩ +theorem isClopen_of_disjoint_cover_open {a b : Set X} (cover : univ ⊆ a ∪ b) + (ha : IsOpen a) (hb : IsOpen b) (hab : Disjoint a b) : IsClopen a := + univ_inter a ▸ isClopen_inter_of_disjoint_cover_clopen isClopen_univ cover ha hb hab + @[simp] theorem isClopen_discrete [DiscreteTopology X] (s : Set X) : IsClopen s := ⟨isClosed_discrete _, isOpen_discrete _⟩ diff --git a/Mathlib/Topology/CompactOpen.lean b/Mathlib/Topology/CompactOpen.lean index 99e06e4f3aa34..0338dd8e2d361 100644 --- a/Mathlib/Topology/CompactOpen.lean +++ b/Mathlib/Topology/CompactOpen.lean @@ -3,7 +3,7 @@ Copyright (c) 2018 Reid Barton. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Reid Barton -/ -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # The compact-open topology @@ -167,8 +167,6 @@ theorem continuous_eval [LocallyCompactPair X Y] : Continuous fun p : C(X, Y) × rcases exists_mem_nhds_isCompact_mapsTo f.continuous (hU.mem_nhds hx) with ⟨K, hxK, hK, hKU⟩ filter_upwards [prod_mem_nhds (eventually_mapsTo hK hU hKU) hxK] using fun _ h ↦ h.1 h.2 -@[deprecated (since := "2023-12-26")] alias continuous_eval' := continuous_eval - /-- Evaluation of a continuous map `f` at a point `x` is continuous in `f`. Porting note: merged `continuous_eval_const` with `continuous_eval_const'` removing unneeded @@ -376,7 +374,7 @@ theorem continuous_curry [LocallyCompactSpace (X × Y)] : /-- The uncurried form of a continuous map `X → C(Y, Z)` is a continuous map `X × Y → Z`. -/ theorem continuous_uncurry_of_continuous [LocallyCompactSpace Y] (f : C(X, C(Y, Z))) : Continuous (Function.uncurry fun x y => f x y) := - continuous_eval.comp <| f.continuous.prod_map continuous_id + continuous_eval.comp <| f.continuous.prodMap continuous_id /-- The uncurried form of a continuous map `X → C(Y, Z)` as a continuous map `X × Y → Z` (if `Y` is locally compact). If `X` is also locally compact, then this is a homeomorphism between the two @@ -390,7 +388,7 @@ theorem continuous_uncurry [LocallyCompactSpace X] [LocallyCompactSpace Y] : Continuous (uncurry : C(X, C(Y, Z)) → C(X × Y, Z)) := by apply continuous_of_continuous_uncurry rw [← (Homeomorph.prodAssoc _ _ _).comp_continuous_iff'] - apply continuous_eval.comp (continuous_eval.prod_map continuous_id) + apply continuous_eval.comp (continuous_eval.prodMap continuous_id) /-- The family of constant maps: `Y → C(X, Y)` as a continuous map. -/ def const' : C(Y, C(X, Y)) := diff --git a/Mathlib/Topology/Compactification/OnePoint.lean b/Mathlib/Topology/Compactification/OnePoint.lean index 0201f2ccbee78..7552539c3ada1 100644 --- a/Mathlib/Topology/Compactification/OnePoint.lean +++ b/Mathlib/Topology/Compactification/OnePoint.lean @@ -187,7 +187,7 @@ instance : TopologicalSpace (OnePoint X) where rw [preimage_sUnion] exact isOpen_biUnion fun s hs => (ho s hs).2 -variable {s : Set (OnePoint X)} {t : Set X} +variable {s : Set (OnePoint X)} theorem isOpen_def : IsOpen s ↔ (∞ ∈ s → IsCompact ((↑) ⁻¹' s : Set X)ᶜ) ∧ IsOpen ((↑) ⁻¹' s : Set X) := @@ -426,9 +426,12 @@ theorem denseRange_coe [NoncompactSpace X] : DenseRange ((↑) : X → OnePoint rw [DenseRange, ← compl_infty] exact dense_compl_singleton _ -theorem denseEmbedding_coe [NoncompactSpace X] : DenseEmbedding ((↑) : X → OnePoint X) := +theorem isDenseEmbedding_coe [NoncompactSpace X] : IsDenseEmbedding ((↑) : X → OnePoint X) := { openEmbedding_coe with dense := denseRange_coe } +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_coe := isDenseEmbedding_coe + @[simp, norm_cast] theorem specializes_coe {x y : X} : (x : OnePoint X) ⤳ y ↔ x ⤳ y := openEmbedding_coe.toInducing.specializes_iff @@ -507,7 +510,7 @@ example [WeaklyLocallyCompactSpace X] [T2Space X] : T4Space (OnePoint X) := infe /-- If `X` is not a compact space, then `OnePoint X` is a connected space. -/ instance [PreconnectedSpace X] [NoncompactSpace X] : ConnectedSpace (OnePoint X) where - toPreconnectedSpace := denseEmbedding_coe.toDenseInducing.preconnectedSpace + toPreconnectedSpace := isDenseEmbedding_coe.toIsDenseInducing.preconnectedSpace toNonempty := inferInstance /-- If `X` is an infinite type with discrete topology (e.g., `ℕ`), then the identity map from diff --git a/Mathlib/Topology/Compactness/LocallyCompact.lean b/Mathlib/Topology/Compactness/LocallyCompact.lean index 2f3de63565306..e0c44089ecd15 100644 --- a/Mathlib/Topology/Compactness/LocallyCompact.lean +++ b/Mathlib/Topology/Compactness/LocallyCompact.lean @@ -76,9 +76,6 @@ theorem LocallyCompactSpace.of_hasBasis {ι : X → Type*} {p : ∀ x, ι x → let ⟨i, hp, ht⟩ := (h x).mem_iff.1 ht ⟨s x i, (h x).mem_of_mem hp, ht, hc x i hp⟩⟩ -@[deprecated (since := "2023-12-29")] -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) := diff --git a/Mathlib/Topology/Connected/PathConnected.lean b/Mathlib/Topology/Connected/PathConnected.lean index 1cad1a9499c1e..644fcb694b3a8 100644 --- a/Mathlib/Topology/Connected/PathConnected.lean +++ b/Mathlib/Topology/Connected/PathConnected.lean @@ -75,8 +75,8 @@ structure Path (x y : X) extends C(I, X) where target' : toFun 1 = y instance Path.funLike : FunLike (Path x y) I X where - coe := fun γ ↦ ⇑γ.toContinuousMap - coe_injective' := fun γ₁ γ₂ h => by + coe γ := ⇑γ.toContinuousMap + coe_injective' γ₁ γ₂ h := by simp only [DFunLike.coe_fn_eq] at h cases γ₁; cases γ₂; congr @@ -200,7 +200,7 @@ instance topologicalSpace : TopologicalSpace (Path x y) := theorem continuous_eval : Continuous fun p : Path x y × I => p.1 p.2 := ContinuousMap.continuous_eval.comp <| - (continuous_induced_dom (α := Path x y)).prod_map continuous_id + (continuous_induced_dom (α := Path x y)).prodMap continuous_id @[continuity] theorem _root_.Continuous.path_eval {Y} [TopologicalSpace Y] {f : Y → Path x y} {g : Y → I} @@ -423,7 +423,7 @@ theorem cast_coe (γ : Path x y) {x' y'} (hx : x' = x) (hy : y' = y) : (γ.cast theorem symm_continuous_family {ι : Type*} [TopologicalSpace ι] {a b : ι → X} (γ : ∀ t : ι, Path (a t) (b t)) (h : Continuous ↿γ) : Continuous ↿fun t => (γ t).symm := - h.comp (continuous_id.prod_map continuous_symm) + h.comp (continuous_id.prodMap continuous_symm) @[continuity] theorem continuous_symm : Continuous (symm : Path x y → Path y x) := @@ -433,7 +433,7 @@ theorem continuous_symm : Continuous (symm : Path x y → Path y x) := theorem continuous_uncurry_extend_of_continuous_family {ι : Type*} [TopologicalSpace ι] {a b : ι → X} (γ : ∀ t : ι, Path (a t) (b t)) (h : Continuous ↿γ) : Continuous ↿fun t => (γ t).extend := by - apply h.comp (continuous_id.prod_map continuous_projIcc) + apply h.comp (continuous_id.prodMap continuous_projIcc) exact zero_le_one @[continuity] @@ -447,12 +447,12 @@ theorem trans_continuous_family {ι : Type*} [TopologicalSpace ι] refine Continuous.if_le ?_ ?_ (continuous_subtype_val.comp continuous_snd) continuous_const ?_ · change Continuous ((fun p : ι × ℝ => (γ₁ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x : I → ℝ)) - exact h₁'.comp (continuous_id.prod_map <| continuous_const.mul continuous_subtype_val) + exact h₁'.comp (continuous_id.prodMap <| continuous_const.mul continuous_subtype_val) · change Continuous ((fun p : ι × ℝ => (γ₂ p.1).extend p.2) ∘ Prod.map id (fun x => 2 * x - 1 : I → ℝ)) exact h₂'.comp - (continuous_id.prod_map <| + (continuous_id.prodMap <| (continuous_const.mul continuous_subtype_val).sub continuous_const) · rintro st hst simp [hst, mul_inv_cancel₀ (two_ne_zero' ℝ)] diff --git a/Mathlib/Topology/Connected/TotallyDisconnected.lean b/Mathlib/Topology/Connected/TotallyDisconnected.lean index 0da1004c037f4..b7f1ff02b4fb4 100644 --- a/Mathlib/Topology/Connected/TotallyDisconnected.lean +++ b/Mathlib/Topology/Connected/TotallyDisconnected.lean @@ -195,7 +195,7 @@ alias IsTotallySeparated.isTotallyDisconnected := isTotallyDisconnected_of_isTot /-- A space is totally separated if any two points can be separated by two disjoint open sets covering the whole space. -/ -class TotallySeparatedSpace (α : Type u) [TopologicalSpace α] : Prop where +@[mk_iff] class TotallySeparatedSpace (α : Type u) [TopologicalSpace α] : Prop where /-- The universal set `Set.univ` in a totally separated space is totally separated. -/ isTotallySeparated_univ : IsTotallySeparated (univ : Set α) @@ -210,15 +210,19 @@ instance (priority := 100) TotallySeparatedSpace.of_discrete (α : Type*) [Topol ⟨fun _ _ b _ h => ⟨{b}ᶜ, {b}, isOpen_discrete _, isOpen_discrete _, h, rfl, (compl_union_self _).symm.subset, disjoint_compl_left⟩⟩ +theorem totallySeparatedSpace_iff_exists_isClopen {α : Type*} [TopologicalSpace α] : + TotallySeparatedSpace α ↔ ∀ x y : α, x ≠ y → ∃ U : Set α, IsClopen U ∧ x ∈ U ∧ y ∈ Uᶜ := by + simp only [totallySeparatedSpace_iff, IsTotallySeparated, Set.Pairwise, mem_univ, true_implies] + refine forall₃_congr fun x y _ ↦ + ⟨fun ⟨U, V, hU, hV, Ux, Vy, f, disj⟩ ↦ ?_, fun ⟨U, hU, Ux, Ucy⟩ ↦ ?_⟩ + · exact ⟨U, isClopen_of_disjoint_cover_open f hU hV disj, + Ux, fun Uy ↦ Set.disjoint_iff.mp disj ⟨Uy, Vy⟩⟩ + · exact ⟨U, Uᶜ, hU.2, hU.compl.2, Ux, Ucy, (Set.union_compl_self U).ge, disjoint_compl_right⟩ + theorem exists_isClopen_of_totally_separated {α : Type*} [TopologicalSpace α] [TotallySeparatedSpace α] {x y : α} (hxy : x ≠ y) : - ∃ U : Set α, IsClopen U ∧ x ∈ U ∧ y ∈ Uᶜ := by - obtain ⟨U, V, hU, hV, Ux, Vy, f, disj⟩ := - TotallySeparatedSpace.isTotallySeparated_univ (Set.mem_univ x) (Set.mem_univ y) hxy - have hU := isClopen_inter_of_disjoint_cover_clopen isClopen_univ f hU hV disj - rw [univ_inter _] at hU - rw [← Set.subset_compl_iff_disjoint_right, subset_compl_comm] at disj - exact ⟨U, hU, Ux, disj Vy⟩ + ∃ U : Set α, IsClopen U ∧ x ∈ U ∧ y ∈ Uᶜ := + totallySeparatedSpace_iff_exists_isClopen.mp ‹_› _ _ hxy end TotallySeparated @@ -260,7 +264,6 @@ theorem Continuous.connectedComponentsLift_unique (h : Continuous f) (g : Connec (hg : g ∘ (↑) = f) : g = h.connectedComponentsLift := connectedComponents_lift_unique' <| hg.trans h.connectedComponentsLift_comp_coe.symm - instance ConnectedComponents.totallyDisconnectedSpace : TotallyDisconnectedSpace (ConnectedComponents α) := by rw [totallyDisconnectedSpace_iff_connectedComponent_singleton] diff --git a/Mathlib/Topology/Constructions.lean b/Mathlib/Topology/Constructions.lean index d8f4038358755..b4bf95ad2f9e1 100644 --- a/Mathlib/Topology/Constructions.lean +++ b/Mathlib/Topology/Constructions.lean @@ -400,10 +400,12 @@ theorem Continuous.comp₄ {g : X × Y × Z × ζ → ε} (hg : Continuous g) {e hg.comp₃ he hf <| hk.prod_mk hl @[continuity] -theorem Continuous.prod_map {f : Z → X} {g : W → Y} (hf : Continuous f) (hg : Continuous g) : - Continuous fun p : Z × W => (f p.1, g p.2) := +theorem Continuous.prodMap {f : Z → X} {g : W → Y} (hf : Continuous f) (hg : Continuous g) : + Continuous (Prod.map f g) := hf.fst'.prod_mk hg.snd' +@[deprecated (since := "2024-10-05")] alias Continuous.prod_map := Continuous.prodMap + /-- A version of `continuous_inf_dom_left` for binary functions -/ theorem continuous_inf_dom_left₂ {X Y Z} {f : X → Y → Z} {ta1 ta2 : TopologicalSpace X} {tb1 tb2 : TopologicalSpace Y} {tc1 : TopologicalSpace Z} @@ -411,7 +413,7 @@ theorem continuous_inf_dom_left₂ {X Y Z} {f : X → Y → Z} {ta1 ta2 : Topolo haveI := ta1 ⊓ ta2; haveI := tb1 ⊓ tb2; exact Continuous fun p : X × Y => f p.1 p.2 := by have ha := @continuous_inf_dom_left _ _ id ta1 ta2 ta1 (@continuous_id _ (id _)) have hb := @continuous_inf_dom_left _ _ id tb1 tb2 tb1 (@continuous_id _ (id _)) - have h_continuous_id := @Continuous.prod_map _ _ _ _ ta1 tb1 (ta1 ⊓ ta2) (tb1 ⊓ tb2) _ _ ha hb + have h_continuous_id := @Continuous.prodMap _ _ _ _ ta1 tb1 (ta1 ⊓ ta2) (tb1 ⊓ tb2) _ _ ha hb exact @Continuous.comp _ _ _ (id _) (id _) _ _ _ h h_continuous_id /-- A version of `continuous_inf_dom_right` for binary functions -/ @@ -421,7 +423,7 @@ theorem continuous_inf_dom_right₂ {X Y Z} {f : X → Y → Z} {ta1 ta2 : Topol haveI := ta1 ⊓ ta2; haveI := tb1 ⊓ tb2; exact Continuous fun p : X × Y => f p.1 p.2 := by have ha := @continuous_inf_dom_right _ _ id ta1 ta2 ta2 (@continuous_id _ (id _)) have hb := @continuous_inf_dom_right _ _ id tb1 tb2 tb2 (@continuous_id _ (id _)) - have h_continuous_id := @Continuous.prod_map _ _ _ _ ta2 tb2 (ta1 ⊓ ta2) (tb1 ⊓ tb2) _ _ ha hb + have h_continuous_id := @Continuous.prodMap _ _ _ _ ta2 tb2 (ta1 ⊓ ta2) (tb1 ⊓ tb2) _ _ ha hb exact @Continuous.comp _ _ _ (id _) (id _) _ _ _ h h_continuous_id /-- A version of `continuous_sInf_dom` for binary functions -/ @@ -433,7 +435,7 @@ theorem continuous_sInf_dom₂ {X Y Z} {f : X → Y → Z} {tas : Set (Topologic exact @Continuous _ _ _ tc fun p : X × Y => f p.1 p.2 := by have hX := continuous_sInf_dom hX continuous_id have hY := continuous_sInf_dom hY continuous_id - have h_continuous_id := @Continuous.prod_map _ _ _ _ tX tY (sInf tas) (sInf tbs) _ _ hX hY + have h_continuous_id := @Continuous.prodMap _ _ _ _ tX tY (sInf tas) (sInf tbs) _ _ hX hY exact @Continuous.comp _ _ _ (id _) (id _) _ _ _ hf h_continuous_id theorem Filter.Eventually.prod_inl_nhds {p : X → Prop} {x : X} (h : ∀ᶠ x in 𝓝 x, p x) (y : Y) : @@ -582,13 +584,19 @@ theorem ContinuousAt.prod {f : X → Y} {g : X → Z} {x : X} (hf : ContinuousAt (hg : ContinuousAt g x) : ContinuousAt (fun x => (f x, g x)) x := hf.prod_mk_nhds hg -theorem ContinuousAt.prod_map {f : X → Z} {g : Y → W} {p : X × Y} (hf : ContinuousAt f p.fst) - (hg : ContinuousAt g p.snd) : ContinuousAt (fun p : X × Y => (f p.1, g p.2)) p := +theorem ContinuousAt.prodMap {f : X → Z} {g : Y → W} {p : X × Y} (hf : ContinuousAt f p.fst) + (hg : ContinuousAt g p.snd) : ContinuousAt (Prod.map f g) p := hf.fst''.prod hg.snd'' -theorem ContinuousAt.prod_map' {f : X → Z} {g : Y → W} {x : X} {y : Y} (hf : ContinuousAt f x) - (hg : ContinuousAt g y) : ContinuousAt (fun p : X × Y => (f p.1, g p.2)) (x, y) := - hf.fst'.prod hg.snd' +@[deprecated (since := "2024-10-05")] alias ContinuousAt.prod_map := ContinuousAt.prodMap + +/-- A version of `ContinuousAt.prodMap` that avoids `Prod.fst`/`Prod.snd` +by assuming that the point is `(x, y)`. -/ +theorem ContinuousAt.prodMap' {f : X → Z} {g : Y → W} {x : X} {y : Y} (hf : ContinuousAt f x) + (hg : ContinuousAt g y) : ContinuousAt (Prod.map f g) (x, y) := + hf.prodMap hg + +@[deprecated (since := "2024-10-05")] alias ContinuousAt.prod_map' := ContinuousAt.prodMap' theorem ContinuousAt.comp₂ {f : Y × Z → W} {g : X → Y} {h : X → Z} {x : X} (hf : ContinuousAt f (g x, h x)) (hg : ContinuousAt g x) (hh : ContinuousAt h x) : @@ -776,15 +784,19 @@ theorem Dense.prod {s : Set X} {t : Set Y} (hs : Dense s) (ht : Dense t) : Dense exact ⟨hs x.1, ht x.2⟩ /-- If `f` and `g` are maps with dense range, then `Prod.map f g` has dense range. -/ -theorem DenseRange.prod_map {ι : Type*} {κ : Type*} {f : ι → Y} {g : κ → Z} (hf : DenseRange f) +theorem DenseRange.prodMap {ι : Type*} {κ : Type*} {f : ι → Y} {g : κ → Z} (hf : DenseRange f) (hg : DenseRange g) : DenseRange (Prod.map f g) := by simpa only [DenseRange, prod_range_range_eq] using hf.prod hg -theorem Inducing.prod_map {f : X → Y} {g : Z → W} (hf : Inducing f) (hg : Inducing g) : +@[deprecated (since := "2024-10-05")] alias DenseRange.prod_map := DenseRange.prodMap + +theorem Inducing.prodMap {f : X → Y} {g : Z → W} (hf : Inducing f) (hg : Inducing g) : Inducing (Prod.map f g) := inducing_iff_nhds.2 fun (x, z) => by simp_rw [Prod.map_def, nhds_prod_eq, hf.nhds_eq_comap, hg.nhds_eq_comap, prod_comap_comap_eq] +@[deprecated (since := "2024-10-05")] alias Inducing.prod_map := Inducing.prodMap + @[simp] theorem inducing_const_prod {x : X} {f : Y → Z} : (Inducing fun x' => (x, f x')) ↔ Inducing f := by simp_rw [inducing_iff, instTopologicalSpaceProd, induced_inf, induced_compose, Function.comp_def, @@ -795,21 +807,27 @@ theorem inducing_prod_const {y : Y} {f : X → Z} : (Inducing fun x => (f x, y)) simp_rw [inducing_iff, instTopologicalSpaceProd, induced_inf, induced_compose, Function.comp_def, induced_const, inf_top_eq] -theorem Embedding.prod_map {f : X → Y} {g : Z → W} (hf : Embedding f) (hg : Embedding g) : +theorem Embedding.prodMap {f : X → Y} {g : Z → W} (hf : Embedding f) (hg : Embedding g) : Embedding (Prod.map f g) := - { hf.toInducing.prod_map hg.toInducing with + { hf.toInducing.prodMap hg.toInducing with inj := fun ⟨x₁, z₁⟩ ⟨x₂, z₂⟩ => by simp [hf.inj.eq_iff, hg.inj.eq_iff] } -protected theorem IsOpenMap.prod {f : X → Y} {g : Z → W} (hf : IsOpenMap f) (hg : IsOpenMap g) : - IsOpenMap fun p : X × Z => (f p.1, g p.2) := by +@[deprecated (since := "2024-10-05")] alias Embedding.prod_map := Embedding.prodMap + +protected theorem IsOpenMap.prodMap {f : X → Y} {g : Z → W} (hf : IsOpenMap f) (hg : IsOpenMap g) : + IsOpenMap (Prod.map f g) := by rw [isOpenMap_iff_nhds_le] rintro ⟨a, b⟩ - rw [nhds_prod_eq, nhds_prod_eq, ← Filter.prod_map_map_eq] + rw [nhds_prod_eq, nhds_prod_eq, ← Filter.prod_map_map_eq'] exact Filter.prod_mono (hf.nhds_le a) (hg.nhds_le b) -protected theorem OpenEmbedding.prod {f : X → Y} {g : Z → W} (hf : OpenEmbedding f) - (hg : OpenEmbedding g) : OpenEmbedding fun x : X × Z => (f x.1, g x.2) := - openEmbedding_of_embedding_open (hf.1.prod_map hg.1) (hf.isOpenMap.prod hg.isOpenMap) +@[deprecated (since := "2024-10-05")] alias IsOpenMap.prod := IsOpenMap.prodMap + +protected theorem OpenEmbedding.prodMap {f : X → Y} {g : Z → W} (hf : OpenEmbedding f) + (hg : OpenEmbedding g) : OpenEmbedding (Prod.map f g) := + openEmbedding_of_embedding_open (hf.1.prodMap hg.1) (hf.isOpenMap.prodMap hg.isOpenMap) + +@[deprecated (since := "2024-10-05")] alias OpenEmbedding.prod := OpenEmbedding.prodMap theorem embedding_graph {f : X → Y} (hf : Continuous f) : Embedding fun x => (x, f x) := embedding_of_embedding_compose (continuous_id.prod_mk hf) continuous_fst embedding_id @@ -817,6 +835,10 @@ theorem embedding_graph {f : X → Y} (hf : Continuous f) : Embedding fun x => ( theorem embedding_prod_mk (x : X) : Embedding (Prod.mk x : Y → X × Y) := embedding_of_embedding_compose (Continuous.Prod.mk x) continuous_snd embedding_id +theorem IsOpenQuotientMap.prodMap {f : X → Y} {g : Z → W} (hf : IsOpenQuotientMap f) + (hg : IsOpenQuotientMap g) : IsOpenQuotientMap (Prod.map f g) := + ⟨.prodMap hf.1 hg.1, .prodMap hf.2 hg.2, .prodMap hf.3 hg.3⟩ + end Prod section Bool @@ -963,7 +985,7 @@ end Sum section Subtype -variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] {p : X → Prop} +variable [TopologicalSpace X] [TopologicalSpace Y] {p : X → Prop} theorem inducing_subtype_val {t : Set Y} : Inducing ((↑) : t → Y) := ⟨rfl⟩ @@ -1118,7 +1140,7 @@ end Subtype section Quotient -variable [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] +variable [TopologicalSpace X] [TopologicalSpace Y] variable {r : X → X → Prop} {s : Setoid X} theorem quotientMap_quot_mk : QuotientMap (@Quot.mk X r) := @@ -1144,7 +1166,7 @@ theorem Continuous.quotient_lift {f : X → Y} (h : Continuous f) (hs : ∀ a b, continuous_coinduced_dom.2 h theorem Continuous.quotient_liftOn' {f : X → Y} (h : Continuous f) - (hs : ∀ a b, @Setoid.r _ s a b → f a = f b) : + (hs : ∀ a b, s a b → f a = f b) : Continuous (fun x => Quotient.liftOn' x f hs : Quotient s → Y) := h.quotient_lift hs @@ -1244,7 +1266,7 @@ theorem Finset.continuous_restrict₂ {s t : Finset ι} (hst : s ⊆ t) : Continuous (Finset.restrict₂ (π := π) hst) := continuous_pi fun _ ↦ continuous_apply _ -variable {Z : Type*} [TopologicalSpace Z] +variable [TopologicalSpace Z] @[continuity, fun_prop] theorem Pi.continuous_restrict_apply (s : Set X) {f : X → Z} (hf : Continuous f) : @@ -1638,8 +1660,8 @@ theorem IsClosed.trans (ht : IsClosed t) (hs : IsClosed s) : IsClosed (t : Set X end Monad section NhdsSet -variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] {f : Filter X} - {s : Set X} {t : Set Y} {x : X} +variable [TopologicalSpace X] [TopologicalSpace Y] + {s : Set X} {t : Set Y} /-- 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. -/ diff --git a/Mathlib/Topology/ContinuousFunction/Algebra.lean b/Mathlib/Topology/ContinuousMap/Algebra.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/Algebra.lean rename to Mathlib/Topology/ContinuousMap/Algebra.lean index f355d40dd16c6..4e62f17e049be 100644 --- a/Mathlib/Topology/ContinuousFunction/Algebra.lean +++ b/Mathlib/Topology/ContinuousMap/Algebra.lean @@ -14,7 +14,7 @@ import Mathlib.Topology.Algebra.InfiniteSum.Basic import Mathlib.Topology.Algebra.Ring.Basic import Mathlib.Topology.Algebra.Star import Mathlib.Topology.Algebra.UniformGroup -import Mathlib.Topology.ContinuousFunction.Ordered +import Mathlib.Topology.ContinuousMap.Ordered import Mathlib.Topology.UniformSpace.CompactConvergence /-! @@ -295,9 +295,9 @@ instance [LocallyCompactSpace α] [Mul β] [ContinuousMul β] : ContinuousMul C( ⟨by refine continuous_of_continuous_uncurry _ ?_ have h1 : Continuous fun x : (C(α, β) × C(α, β)) × α => x.fst.fst x.snd := - continuous_eval.comp (continuous_fst.prod_map continuous_id) + continuous_eval.comp (continuous_fst.prodMap continuous_id) have h2 : Continuous fun x : (C(α, β) × C(α, β)) × α => x.fst.snd x.snd := - continuous_eval.comp (continuous_snd.prod_map continuous_id) + continuous_eval.comp (continuous_snd.prodMap continuous_id) exact h1.mul h2⟩ /-- Coercion to a function as a `MonoidHom`. Similar to `MonoidHom.coeFn`. -/ @@ -550,7 +550,7 @@ instance [LocallyCompactSpace α] [TopologicalSpace R] [SMul R M] [ContinuousSMu ⟨by refine continuous_of_continuous_uncurry _ ?_ have h : Continuous fun x : (R × C(α, M)) × α => x.fst.snd x.snd := - continuous_eval.comp (continuous_snd.prod_map continuous_id) + continuous_eval.comp (continuous_snd.prodMap continuous_id) exact (continuous_fst.comp continuous_fst).smul h⟩ @[to_additive (attr := simp, norm_cast)] diff --git a/Mathlib/Topology/ContinuousFunction/Basic.lean b/Mathlib/Topology/ContinuousMap/Basic.lean similarity index 78% rename from Mathlib/Topology/ContinuousFunction/Basic.lean rename to Mathlib/Topology/ContinuousMap/Basic.lean index e77f01dabfc8e..bd8aca0de948b 100644 --- a/Mathlib/Topology/ContinuousFunction/Basic.lean +++ b/Mathlib/Topology/ContinuousMap/Basic.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Nicolò Cavalleri -/ import Mathlib.Data.Set.UnionLift +import Mathlib.Topology.ContinuousMap.Defs import Mathlib.Topology.Homeomorph /-! @@ -19,37 +20,6 @@ be satisfied by itself and all stricter types. open Function open scoped Topology -/-- The type of continuous maps from `α` to `β`. - -When possible, instead of parametrizing results over `(f : C(α, β))`, -you should parametrize over `{F : Type*} [ContinuousMapClass F α β] (f : F)`. - -When you extend this structure, make sure to extend `ContinuousMapClass`. -/ -structure ContinuousMap (α β : Type*) [TopologicalSpace α] [TopologicalSpace β] where - /-- The function `α → β` -/ - protected toFun : α → β - /-- Proposition that `toFun` is continuous -/ - protected continuous_toFun : Continuous toFun := by continuity - -/-- The type of continuous maps from `α` to `β`. -/ -notation "C(" α ", " β ")" => ContinuousMap α β - -section - -/-- `ContinuousMapClass F α β` states that `F` is a type of continuous maps. - -You should extend this class when you extend `ContinuousMap`. -/ -class ContinuousMapClass (F α β : Type*) [TopologicalSpace α] [TopologicalSpace β] - [FunLike F α β] : Prop where - /-- Continuity -/ - map_continuous (f : F) : Continuous f - -end - -export ContinuousMapClass (map_continuous) - -attribute [continuity, fun_prop] map_continuous - section ContinuousMapClass variable {F α β : Type*} [TopologicalSpace α] [TopologicalSpace β] [FunLike F α β] @@ -61,11 +31,6 @@ theorem map_continuousAt (f : F) (a : α) : ContinuousAt f a := theorem map_continuousWithinAt (f : F) (s : Set α) (a : α) : ContinuousWithinAt f s a := (map_continuous f).continuousWithinAt -/-- Coerce a bundled morphism with a `ContinuousMapClass` instance to a `ContinuousMap`. -/ -@[coe] def toContinuousMap (f : F) : C(α, β) := ⟨f, map_continuous f⟩ - -instance : CoeTC F C(α, β) := ⟨toContinuousMap⟩ - end ContinuousMapClass /-! ### Continuous maps -/ @@ -76,75 +41,11 @@ namespace ContinuousMap variable {α β γ δ : Type*} [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] [TopologicalSpace δ] -instance funLike : FunLike C(α, β) α β where - coe := ContinuousMap.toFun - coe_injective' f g h := by cases f; cases g; congr - -instance toContinuousMapClass : ContinuousMapClass C(α, β) α β where - map_continuous := ContinuousMap.continuous_toFun - -@[simp] -theorem toFun_eq_coe {f : C(α, β)} : f.toFun = (f : α → β) := - rfl - -instance : CanLift (α → β) C(α, β) DFunLike.coe Continuous := ⟨fun f hf ↦ ⟨⟨f, hf⟩, rfl⟩⟩ - -/-- See note [custom simps projection]. -/ -def Simps.apply (f : C(α, β)) : α → β := f - --- this must come after the coe_to_fun definition -initialize_simps_projections ContinuousMap (toFun → apply) - -@[simp] -- Porting note: removed `norm_cast` attribute -protected theorem coe_coe {F : Type*} [FunLike F α β] [ContinuousMapClass F α β] (f : F) : - ⇑(f : C(α, β)) = f := - rfl - -@[ext] -theorem ext {f g : C(α, β)} (h : ∀ a, f a = g a) : f = g := - DFunLike.ext _ _ h - -/-- Copy of a `ContinuousMap` with a new `toFun` equal to the old one. Useful to fix definitional -equalities. -/ -protected def copy (f : C(α, β)) (f' : α → β) (h : f' = f) : C(α, β) where - toFun := f' - continuous_toFun := h.symm ▸ f.continuous_toFun - -@[simp] -theorem coe_copy (f : C(α, β)) (f' : α → β) (h : f' = f) : ⇑(f.copy f' h) = f' := - rfl - -theorem copy_eq (f : C(α, β)) (f' : α → β) (h : f' = f) : f.copy f' h = f := - DFunLike.ext' h - variable {f g : C(α, β)} -/-- Deprecated. Use `map_continuous` instead. -/ -protected theorem continuous (f : C(α, β)) : Continuous f := - f.continuous_toFun - -@[continuity] -theorem continuous_set_coe (s : Set C(α, β)) (f : s) : Continuous (f : α → β) := - f.1.continuous - /-- Deprecated. Use `map_continuousAt` instead. -/ protected theorem continuousAt (f : C(α, β)) (x : α) : ContinuousAt f x := - f.continuous.continuousAt - -/-- Deprecated. Use `DFunLike.congr_fun` instead. -/ -protected theorem congr_fun {f g : C(α, β)} (H : f = g) (x : α) : f x = g x := - H ▸ rfl - -/-- Deprecated. Use `DFunLike.congr_arg` instead. -/ -protected theorem congr_arg (f : C(α, β)) {x y : α} (h : x = y) : f x = f y := - h ▸ rfl - -theorem coe_injective : @Function.Injective C(α, β) (α → β) (↑) := fun f g h => by - cases f; cases g; congr - -@[simp] -theorem coe_mk (f : α → β) (h : Continuous f) : ⇑(⟨f, h⟩ : C(α, β)) = f := - rfl + map_continuousAt f x theorem map_specializes (f : C(α, β)) {x y : α} (h : x ⤳ y) : f x ⤳ f y := h.map f.2 @@ -271,8 +172,6 @@ def prodMk (f : C(α, β₁)) (g : C(α, β₂)) : C(α, β₁ × β₂) where @[simps] def prodMap (f : C(α₁, α₂)) (g : C(β₁, β₂)) : C(α₁ × β₁, α₂ × β₂) where toFun := Prod.map f g - continuous_toFun := f.continuous.prod_map g.continuous - -- Porting note: proof was `continuity` @[simp] theorem prod_eval (f : C(α, β₁)) (g : C(α, β₂)) (a : α) : (prodMk f g) a = (f a, g a) := @@ -380,13 +279,14 @@ 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 ↦ - DFunLike.ext' <| f.continuous.ext_on hs g.continuous <| Set.restrict_eq_restrict_iff.1 <| - congr_arg DFunLike.coe h + DFunLike.ext' <| (map_continuous f).ext_on hs (map_continuous g) <| + Set.restrict_eq_restrict_iff.1 <| congr_arg DFunLike.coe h /-- The restriction of a continuous map to the preimage of a set. -/ @[simps] def restrictPreimage (f : C(α, β)) (s : Set β) : C(f ⁻¹' s, s) := - ⟨s.restrictPreimage f, continuous_iff_continuousAt.mpr fun _ => f.2.continuousAt.restrictPreimage⟩ + ⟨s.restrictPreimage f, continuous_iff_continuousAt.mpr fun _ ↦ + (map_continuousAt f _).restrictPreimage⟩ end Restrict @@ -404,8 +304,8 @@ noncomputable def liftCover : C(α, β) := Set.iUnion_eq_univ_iff.2 fun x ↦ (hS x).imp fun _ ↦ mem_of_mem_nhds mk (Set.liftCover S (fun i ↦ φ i) hφ H) <| continuous_of_cover_nhds hS fun i ↦ by rw [continuousOn_iff_continuous_restrict] - simpa (config := { unfoldPartialApp := true }) only [Set.restrict, Set.liftCover_coe] using - (φ i).continuous + simpa (config := { unfoldPartialApp := true }) only [Set.restrict, Set.liftCover_coe] + using map_continuous (φ i) variable {S φ hφ hS} @@ -463,8 +363,8 @@ variable {X Y Z : Type*} [TopologicalSpace X] [TopologicalSpace Y] [TopologicalS def Function.RightInverse.homeomorph {f' : C(Y, X)} (hf : Function.RightInverse f' f) : Quotient (Setoid.ker f) ≃ₜ Y where toEquiv := Setoid.quotientKerEquivOfRightInverse _ _ hf - continuous_toFun := quotientMap_quot_mk.continuous_iff.mpr f.continuous - continuous_invFun := continuous_quotient_mk'.comp f'.continuous + continuous_toFun := quotientMap_quot_mk.continuous_iff.mpr (map_continuous f) + continuous_invFun := continuous_quotient_mk'.comp (map_continuous f') namespace QuotientMap diff --git a/Mathlib/Topology/ContinuousFunction/Bounded.lean b/Mathlib/Topology/ContinuousMap/Bounded.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/Bounded.lean rename to Mathlib/Topology/ContinuousMap/Bounded.lean index 619fbc2c6b8a5..01840e85e6d01 100644 --- a/Mathlib/Topology/ContinuousFunction/Bounded.lean +++ b/Mathlib/Topology/ContinuousMap/Bounded.lean @@ -4,11 +4,12 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Sébastien Gouëzel, Mario Carneiro, Yury Kudryashov, Heather Macbeth -/ import Mathlib.Algebra.Module.MinimalAxioms -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Analysis.Normed.Order.Lattice import Mathlib.Analysis.NormedSpace.OperatorNorm.Basic import Mathlib.Analysis.CStarAlgebra.Basic import Mathlib.Topology.Bornology.BoundedOperation +import Mathlib.Tactic.Monotonicity /-! # Bounded continuous functions @@ -245,7 +246,7 @@ theorem inducing_coeFn : Inducing (UniformFun.ofFun ∘ (⇑) : (α →ᵇ β) UniformFun.tendsto_iff_tendstoUniformly] simp [comp_def] --- TODO: upgrade to a `UniformEmbedding` +-- TODO: upgrade to a `IsUniformEmbedding` theorem embedding_coeFn : Embedding (UniformFun.ofFun ∘ (⇑) : (α →ᵇ β) → α →ᵤ β) := ⟨inducing_coeFn, fun _ _ h => ext fun x => congr_fun h x⟩ @@ -523,7 +524,7 @@ theorem arzela_ascoli₂ (s : Set β) (hs : IsCompact s) (A : Set (α →ᵇ β) fun f hf => ?_ · haveI : CompactSpace s := isCompact_iff_compactSpace.1 hs refine arzela_ascoli₁ _ (continuous_iff_isClosed.1 (continuous_comp M) _ closed) ?_ - rw [uniformEmbedding_subtype_val.toUniformInducing.equicontinuous_iff] + rw [isUniformEmbedding_subtype_val.isUniformInducing.equicontinuous_iff] exact H.comp (A.restrictPreimage F) · let g := codRestrict s f fun x => in_s f x hf rw [show f = F g by ext; rfl] at hf ⊢ diff --git a/Mathlib/Topology/ContinuousFunction/BoundedCompactlySupported.lean b/Mathlib/Topology/ContinuousMap/BoundedCompactlySupported.lean similarity index 98% rename from Mathlib/Topology/ContinuousFunction/BoundedCompactlySupported.lean rename to Mathlib/Topology/ContinuousMap/BoundedCompactlySupported.lean index 9b6c91a69de4e..ff7efe16ef944 100644 --- a/Mathlib/Topology/ContinuousFunction/BoundedCompactlySupported.lean +++ b/Mathlib/Topology/ContinuousMap/BoundedCompactlySupported.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Yoh Tanimoto. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yoh Tanimoto -/ -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded import Mathlib.RingTheory.TwoSidedIdeal.Lattice /-! diff --git a/Mathlib/Topology/ContinuousFunction/CocompactMap.lean b/Mathlib/Topology/ContinuousMap/CocompactMap.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/CocompactMap.lean rename to Mathlib/Topology/ContinuousMap/CocompactMap.lean index 8794fe4397f20..d5662c0299843 100644 --- a/Mathlib/Topology/ContinuousFunction/CocompactMap.lean +++ b/Mathlib/Topology/ContinuousMap/CocompactMap.lean @@ -3,7 +3,7 @@ Copyright (c) 2022 Jireh Loreaux. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # Cocompact continuous maps diff --git a/Mathlib/Topology/ContinuousFunction/Compact.lean b/Mathlib/Topology/ContinuousMap/Compact.lean similarity index 79% rename from Mathlib/Topology/ContinuousFunction/Compact.lean rename to Mathlib/Topology/ContinuousMap/Compact.lean index 50b42bb56fb90..ca3851110e939 100644 --- a/Mathlib/Topology/ContinuousFunction/Compact.lean +++ b/Mathlib/Topology/ContinuousMap/Compact.lean @@ -3,7 +3,7 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded import Mathlib.Topology.UniformSpace.Compact import Mathlib.Topology.CompactOpen import Mathlib.Topology.Sets.Compacts @@ -29,8 +29,8 @@ open NNReal BoundedContinuousFunction Set Metric namespace ContinuousMap -variable {α β E : Type*} [TopologicalSpace α] [CompactSpace α] [MetricSpace β] - [NormedAddCommGroup E] +variable {α β E : Type*} +variable [TopologicalSpace α] [CompactSpace α] [PseudoMetricSpace β] [SeminormedAddCommGroup E] section @@ -47,8 +47,8 @@ def equivBoundedOfCompact : C(α, β) ≃ (α →ᵇ β) := ext rfl⟩ -theorem uniformInducing_equivBoundedOfCompact : UniformInducing (equivBoundedOfCompact α β) := - UniformInducing.mk' +theorem isUniformInducing_equivBoundedOfCompact : IsUniformInducing (equivBoundedOfCompact α β) := + IsUniformInducing.mk' (by simp only [hasBasis_compactConvergenceUniformity.mem_iff, uniformity_basis_dist_le.mem_iff] exact fun s => @@ -59,8 +59,15 @@ theorem uniformInducing_equivBoundedOfCompact : UniformInducing (equivBoundedOfC ⟨⟨Set.univ, { p | dist p.1 p.2 ≤ ε }⟩, ⟨isCompact_univ, ⟨ε, hε, fun _ h => h⟩⟩, fun ⟨f, g⟩ h => hs _ _ (ht ((dist_le hε.le).mpr fun x => h x (mem_univ x)))⟩⟩) -theorem uniformEmbedding_equivBoundedOfCompact : UniformEmbedding (equivBoundedOfCompact α β) := - { uniformInducing_equivBoundedOfCompact α β with inj := (equivBoundedOfCompact α β).injective } +@[deprecated (since := "2024-10-05")] +alias uniformInducing_equivBoundedOfCompact := isUniformInducing_equivBoundedOfCompact + +theorem isUniformEmbedding_equivBoundedOfCompact : IsUniformEmbedding (equivBoundedOfCompact α β) := + { isUniformInducing_equivBoundedOfCompact α β with + inj := (equivBoundedOfCompact α β).injective } + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_equivBoundedOfCompact := isUniformEmbedding_equivBoundedOfCompact /-- When `α` is compact, the bounded continuous maps `α →ᵇ 𝕜` are additively equivalent to `C(α, 𝕜)`. @@ -82,8 +89,13 @@ theorem addEquivBoundedOfCompact_apply [AddMonoid β] [LipschitzAdd β] : ⇑(addEquivBoundedOfCompact α β) = mkOfCompact := rfl -instance metricSpace : MetricSpace C(α, β) := - (uniformEmbedding_equivBoundedOfCompact α β).comapMetricSpace _ +instance instPseudoMetricSpace : PseudoMetricSpace C(α, β) := + (isUniformEmbedding_equivBoundedOfCompact α β).comapPseudoMetricSpace _ + +instance instMetricSpace {β : Type*} [MetricSpace β] : + MetricSpace C(α, β) := + (isUniformEmbedding_equivBoundedOfCompact α β).comapMetricSpace _ + /-- When `α` is compact, and `β` is a metric space, the bounded continuous maps `α →ᵇ β` are isometric to `C(α, β)`. @@ -133,6 +145,13 @@ theorem dist_lt_iff (C0 : (0 : ℝ) < C) : dist f g < C ↔ ∀ x : α, dist (f rw [← dist_mkOfCompact, dist_lt_iff_of_compact C0] simp only [mkOfCompact_apply] +instance {R} [Zero R] [Zero β] [PseudoMetricSpace R] [SMul R β] [BoundedSMul R β] : + BoundedSMul R C(α, β) where + dist_smul_pair' r f g := by + simpa only [← dist_mkOfCompact] using dist_smul_pair r (mkOfCompact f) (mkOfCompact g) + dist_pair_smul' r₁ r₂ f := by + simpa only [← dist_mkOfCompact] using dist_pair_smul r₁ r₂ (mkOfCompact f) + end -- TODO at some point we will need lemmas characterising this norm! @@ -150,13 +169,17 @@ theorem _root_.BoundedContinuousFunction.norm_toContinuousMap_eq (f : α →ᵇ open BoundedContinuousFunction -instance : NormedAddCommGroup C(α, E) := - { ContinuousMap.metricSpace _ _, - ContinuousMap.instAddCommGroupContinuousMap with - dist_eq := fun x y => by - rw [← norm_mkOfCompact, ← dist_mkOfCompact, dist_eq_norm, mkOfCompact_sub] - dist := dist - norm := norm } +instance : SeminormedAddCommGroup C(α, E) where + __ := ContinuousMap.instPseudoMetricSpace _ _ + __ := ContinuousMap.instAddCommGroupContinuousMap + dist_eq x y := by + rw [← norm_mkOfCompact, ← dist_mkOfCompact, dist_eq_norm, mkOfCompact_sub] + dist := dist + norm := norm + +instance {E : Type*} [NormedAddCommGroup E] : NormedAddCommGroup C(α, E) where + __ : SeminormedAddCommGroup C(α, E) := inferInstance + __ : MetricSpace C(α, E) := inferInstance instance [Nonempty α] [One E] [NormOneClass E] : NormOneClass C(α, E) where norm_one := by simp only [← norm_mkOfCompact, mkOfCompact_one, norm_one] @@ -215,11 +238,40 @@ end section -variable {R : Type*} [NormedRing R] +variable {R : Type*} + +instance [NonUnitalSeminormedRing R] : NonUnitalSeminormedRing C(α, R) where + __ : SeminormedAddCommGroup C(α, R) := inferInstance + __ : NonUnitalRing C(α, R) := inferInstance + norm_mul f g := norm_mul_le (mkOfCompact f) (mkOfCompact g) + +instance [NonUnitalSeminormedCommRing R] : NonUnitalSeminormedCommRing C(α, R) where + __ : NonUnitalSeminormedRing C(α, R) := inferInstance + __ : NonUnitalCommRing C(α, R) := inferInstance + +instance [SeminormedRing R] : SeminormedRing C(α, R) where + __ : NonUnitalSeminormedRing C(α, R) := inferInstance + __ : Ring C(α, R) := inferInstance + +instance [SeminormedCommRing R] : SeminormedCommRing C(α, R) where + __ : SeminormedRing C(α, R) := inferInstance + __ : CommRing C(α, R) := inferInstance + +instance [NonUnitalNormedRing R] : NonUnitalNormedRing C(α, R) where + __ : NormedAddCommGroup C(α, R) := inferInstance + __ : NonUnitalSeminormedRing C(α, R) := inferInstance + +instance [NonUnitalNormedCommRing R] : NonUnitalNormedCommRing C(α, R) where + __ : NonUnitalNormedRing C(α, R) := inferInstance + __ : NonUnitalCommRing C(α, R) := inferInstance + +instance [NormedRing R] : NormedRing C(α, R) where + __ : NormedAddCommGroup C(α, R) := inferInstance + __ : SeminormedRing C(α, R) := inferInstance -instance : NormedRing C(α, R) := - { (inferInstance : NormedAddCommGroup C(α, R)), ContinuousMap.instRing with - norm_mul := fun f g => norm_mul_le (mkOfCompact f) (mkOfCompact g) } +instance [NormedCommRing R] : NormedCommRing C(α, R) where + __ : NormedRing C(α, R) := inferInstance + __ : CommRing C(α, R) := inferInstance end @@ -228,7 +280,7 @@ section variable {𝕜 : Type*} [NormedField 𝕜] [NormedSpace 𝕜 E] instance normedSpace : NormedSpace 𝕜 C(α, E) where - norm_smul_le c f := (norm_smul_le c (mkOfCompact f) : _) + norm_smul_le := norm_smul_le section @@ -287,7 +339,7 @@ end section -variable {𝕜 : Type*} {γ : Type*} [NormedField 𝕜] [NormedRing γ] [NormedAlgebra 𝕜 γ] +variable {𝕜 : Type*} {γ : Type*} [NormedField 𝕜] [SeminormedRing γ] [NormedAlgebra 𝕜 γ] instance : NormedAlgebra 𝕜 C(α, γ) := { ContinuousMap.normedSpace, ContinuousMap.algebra with } @@ -301,7 +353,7 @@ namespace ContinuousMap section UniformContinuity variable {α β : Type*} -variable [MetricSpace α] [CompactSpace α] [MetricSpace β] +variable [PseudoMetricSpace α] [CompactSpace α] [PseudoMetricSpace β] /-! We now set up some declarations making it convenient to use uniform continuity. @@ -335,7 +387,7 @@ section CompLeft variable (X : Type*) {𝕜 β γ : Type*} [TopologicalSpace X] [CompactSpace X] [NontriviallyNormedField 𝕜] -variable [NormedAddCommGroup β] [NormedSpace 𝕜 β] [NormedAddCommGroup γ] [NormedSpace 𝕜 γ] +variable [SeminormedAddCommGroup β] [NormedSpace 𝕜 β] [SeminormedAddCommGroup γ] [NormedSpace 𝕜 γ] open ContinuousMap @@ -382,7 +434,8 @@ section CompRight /-- Precomposition by a continuous map is itself a continuous map between spaces of continuous maps. -/ def compRightContinuousMap {X Y : Type*} (T : Type*) [TopologicalSpace X] [CompactSpace X] - [TopologicalSpace Y] [CompactSpace Y] [MetricSpace T] (f : C(X, Y)) : C(C(Y, T), C(X, T)) where + [TopologicalSpace Y] [CompactSpace Y] [PseudoMetricSpace T] (f : C(X, Y)) : + C(C(Y, T), C(X, T)) where toFun g := g.comp f continuous_toFun := by refine Metric.continuous_iff.mpr ?_ @@ -393,14 +446,15 @@ def compRightContinuousMap {X Y : Type*} (T : Type*) [TopologicalSpace X] [Compa @[simp] theorem compRightContinuousMap_apply {X Y : Type*} (T : Type*) [TopologicalSpace X] - [CompactSpace X] [TopologicalSpace Y] [CompactSpace Y] [MetricSpace T] (f : C(X, Y)) + [CompactSpace X] [TopologicalSpace Y] [CompactSpace Y] [PseudoMetricSpace T] (f : C(X, Y)) (g : C(Y, T)) : (compRightContinuousMap T f) g = g.comp f := rfl /-- Precomposition by a homeomorphism is itself a homeomorphism between spaces of continuous maps. -/ def compRightHomeomorph {X Y : Type*} (T : Type*) [TopologicalSpace X] [CompactSpace X] - [TopologicalSpace Y] [CompactSpace Y] [MetricSpace T] (f : X ≃ₜ Y) : C(Y, T) ≃ₜ C(X, T) where + [TopologicalSpace Y] [CompactSpace Y] [PseudoMetricSpace T] (f : X ≃ₜ Y) : + C(Y, T) ≃ₜ C(X, T) where toFun := compRightContinuousMap T f.toContinuousMap invFun := compRightContinuousMap T f.symm.toContinuousMap left_inv g := ext fun _ => congr_arg g (f.apply_symm_apply _) @@ -408,7 +462,7 @@ def compRightHomeomorph {X Y : Type*} (T : Type*) [TopologicalSpace X] [CompactS theorem compRightAlgHom_continuous {X Y : Type*} (R A : Type*) [TopologicalSpace X] [CompactSpace X] [TopologicalSpace Y] [CompactSpace Y] [CommSemiring R] [Semiring A] - [MetricSpace A] [TopologicalSemiring A] [Algebra R A] (f : C(X, Y)) : + [PseudoMetricSpace A] [TopologicalSemiring A] [Algebra R A] (f : C(X, Y)) : Continuous (compRightAlgHom R A f) := map_continuous (compRightContinuousMap A f) @@ -457,7 +511,7 @@ Furthermore, if `α` is compact and `β` is a C⋆-ring, then `C(α, β)` is a C section NormedSpace variable {α : Type*} {β : Type*} -variable [TopologicalSpace α] [NormedAddCommGroup β] [StarAddMonoid β] [NormedStarGroup β] +variable [TopologicalSpace α] [SeminormedAddCommGroup β] [StarAddMonoid β] [NormedStarGroup β] theorem _root_.BoundedContinuousFunction.mkOfCompact_star [CompactSpace α] (f : C(α, β)) : mkOfCompact (star f) = star (mkOfCompact f) := @@ -473,7 +527,7 @@ end NormedSpace section CStarRing variable {α : Type*} {β : Type*} -variable [TopologicalSpace α] [NormedRing β] [StarRing β] +variable [TopologicalSpace α] [NonUnitalNormedRing β] [StarRing β] instance [CompactSpace α] [CStarRing β] : CStarRing C(α, β) where norm_mul_self_le f := by diff --git a/Mathlib/Topology/ContinuousFunction/CompactlySupported.lean b/Mathlib/Topology/ContinuousMap/CompactlySupported.lean similarity index 98% rename from Mathlib/Topology/ContinuousFunction/CompactlySupported.lean rename to Mathlib/Topology/ContinuousMap/CompactlySupported.lean index d8d72123235af..cea48f4937a02 100644 --- a/Mathlib/Topology/ContinuousFunction/CompactlySupported.lean +++ b/Mathlib/Topology/ContinuousMap/CompactlySupported.lean @@ -3,8 +3,8 @@ Copyright (c) 2024 Yoh Tanimoto. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Yoh Tanimoto -/ -import Mathlib.Topology.ContinuousFunction.CocompactMap -import Mathlib.Topology.ContinuousFunction.ZeroAtInfty +import Mathlib.Topology.ContinuousMap.CocompactMap +import Mathlib.Topology.ContinuousMap.ZeroAtInfty import Mathlib.Topology.Support /-! @@ -119,7 +119,6 @@ theorem eq_of_empty [IsEmpty α] (f g : C_c(α, β)) : f = g := def ContinuousMap.liftCompactlySupported [CompactSpace α] : C(α, β) ≃ C_c(α, β) where toFun f := { toFun := f - continuous_toFun := f.continuous hasCompactSupport' := HasCompactSupport.of_compactSpace f } invFun f := f left_inv _ := rfl @@ -168,7 +167,7 @@ theorem mul_apply [MulZeroClass β] [ContinuousMul β] (f g : C_c(α, β)) : (f instance [Zero β] [TopologicalSpace γ] [SMulZeroClass γ β] [ContinuousSMul γ β] {F : Type*} [FunLike F α γ] [ContinuousMapClass F α γ] : SMul F C_c(α, β) where smul f g := - ⟨⟨fun x ↦ f x • g x, (map_continuous f).smul g.continuous⟩, g.hasCompactSupport'.smul_left⟩ + ⟨⟨fun x ↦ f x • g x, (map_continuous f).smul (map_continuous g)⟩, g.hasCompactSupport.smul_left⟩ @[simp] theorem coe_smulc [Zero β] [TopologicalSpace γ] [SMulZeroClass γ β] [ContinuousSMul γ β] @@ -209,7 +208,7 @@ def coeFnMonoidHom [AddMonoid β] [ContinuousAdd β] : C_c(α, β) →+ α → instance [Zero β] {R : Type*} [SMulZeroClass R β] [ContinuousConstSMul R β] : SMul R C_c(α, β) := - ⟨fun r f => ⟨⟨r • ⇑f, Continuous.const_smul f.continuous r⟩, HasCompactSupport.smul_left f.2⟩⟩ + ⟨fun r f => ⟨⟨r • ⇑f, (map_continuous f).const_smul r⟩, HasCompactSupport.smul_left f.2⟩⟩ @[simp, norm_cast] theorem coe_smul [Zero β] {R : Type*} [SMulZeroClass R β] [ContinuousConstSMul R β] (r : R) diff --git a/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean b/Mathlib/Topology/ContinuousMap/ContinuousMapZero.lean similarity index 91% rename from Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean rename to Mathlib/Topology/ContinuousMap/ContinuousMapZero.lean index a0e26115b77b1..5fa65e8b7c342 100644 --- a/Mathlib/Topology/ContinuousFunction/ContinuousMapZero.lean +++ b/Mathlib/Topology/ContinuousMap/ContinuousMapZero.lean @@ -3,8 +3,8 @@ Copyright (c) 2024 Jireh Loreaux. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ -import Mathlib.Topology.ContinuousFunction.Algebra -import Mathlib.Topology.ContinuousFunction.Compact +import Mathlib.Topology.ContinuousMap.Algebra +import Mathlib.Topology.ContinuousMap.Compact /-! # Continuous maps sending zero to zero @@ -268,20 +268,26 @@ variable [Zero R] [UniformSpace R] protected instance instUniformSpace : UniformSpace C(X, R)₀ := .comap toContinuousMap inferInstance -lemma uniformEmbedding_toContinuousMap : - UniformEmbedding ((↑) : C(X, R)₀ → C(X, R)) where +lemma isUniformEmbedding_toContinuousMap : + IsUniformEmbedding ((↑) : C(X, R)₀ → C(X, R)) where comap_uniformity := rfl inj _ _ h := ext fun x ↦ congr($(h) x) +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toContinuousMap := isUniformEmbedding_toContinuousMap + instance [T1Space R] [CompleteSpace C(X, R)] : CompleteSpace C(X, R)₀ := - completeSpace_iff_isComplete_range uniformEmbedding_toContinuousMap.toUniformInducing + completeSpace_iff_isComplete_range isUniformEmbedding_toContinuousMap.isUniformInducing |>.mpr closedEmbedding_toContinuousMap.isClosed_range.isComplete -lemma uniformEmbedding_comp {Y : Type*} [UniformSpace Y] [Zero Y] (g : C(Y, R)₀) - (hg : UniformEmbedding g) : UniformEmbedding (g.comp · : C(X, Y)₀ → C(X, R)₀) := - uniformEmbedding_toContinuousMap.of_comp_iff.mp <| - ContinuousMap.uniformEmbedding_comp g.toContinuousMap hg |>.comp - uniformEmbedding_toContinuousMap +lemma isUniformEmbedding_comp {Y : Type*} [UniformSpace Y] [Zero Y] (g : C(Y, R)₀) + (hg : IsUniformEmbedding g) : IsUniformEmbedding (g.comp · : C(X, Y)₀ → C(X, R)₀) := + isUniformEmbedding_toContinuousMap.of_comp_iff.mp <| + ContinuousMap.isUniformEmbedding_comp g.toContinuousMap hg |>.comp + isUniformEmbedding_toContinuousMap + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_comp := isUniformEmbedding_comp /-- The uniform equivalence `C(X, R)₀ ≃ᵤ C(Y, R)₀` induced by a homeomorphism of the domains sending `0 : X` to `0 : Y`. -/ @@ -291,12 +297,12 @@ def _root_.UniformEquiv.arrowCongrLeft₀ {Y : Type*} [TopologicalSpace Y] [Zero invFun g := g.comp ⟨f.toContinuousMap, hf⟩ left_inv g := ext fun _ ↦ congrArg g <| f.left_inv _ right_inv g := ext fun _ ↦ congrArg g <| f.right_inv _ - uniformContinuous_toFun := uniformEmbedding_toContinuousMap.uniformContinuous_iff.mpr <| + uniformContinuous_toFun := isUniformEmbedding_toContinuousMap.uniformContinuous_iff.mpr <| ContinuousMap.uniformContinuous_comp_left f.symm.toContinuousMap |>.comp - uniformEmbedding_toContinuousMap.uniformContinuous - uniformContinuous_invFun := uniformEmbedding_toContinuousMap.uniformContinuous_iff.mpr <| + isUniformEmbedding_toContinuousMap.uniformContinuous + uniformContinuous_invFun := isUniformEmbedding_toContinuousMap.uniformContinuous_iff.mpr <| ContinuousMap.uniformContinuous_comp_left f.toContinuousMap |>.comp - uniformEmbedding_toContinuousMap.uniformContinuous + isUniformEmbedding_toContinuousMap.uniformContinuous end UniformSpace @@ -340,7 +346,7 @@ section Norm variable {α : Type*} {𝕜 : Type*} {R : Type*} [TopologicalSpace α] [CompactSpace α] [Zero α] noncomputable instance [MetricSpace R] [Zero R]: MetricSpace C(α, R)₀ := - ContinuousMapZero.uniformEmbedding_toContinuousMap.comapMetricSpace _ + ContinuousMapZero.isUniformEmbedding_toContinuousMap.comapMetricSpace _ noncomputable instance [NormedAddCommGroup R] : Norm C(α, R)₀ where norm f := ‖(f : C(α, R))‖ diff --git a/Mathlib/Topology/ContinuousMap/Defs.lean b/Mathlib/Topology/ContinuousMap/Defs.lean new file mode 100644 index 0000000000000..f576214a27758 --- /dev/null +++ b/Mathlib/Topology/ContinuousMap/Defs.lean @@ -0,0 +1,136 @@ +/- +Copyright (c) 2020 Nicolò Cavalleri. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Nicolò Cavalleri, Yury Kudryashov +-/ +import Mathlib.Tactic.Continuity +import Mathlib.Tactic.Lift +import Mathlib.Topology.Defs.Basic + +/-! +# Continuous bundled maps + +In this file we define the type `ContinuousMap` of continuous bundled maps. + +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. +-/ + +open Function +open scoped Topology + +/-- The type of continuous maps from `X` to `Y`. + +When possible, instead of parametrizing results over `(f : C(X, Y))`, +you should parametrize over `{F : Type*} [ContinuousMapClass F X Y] (f : F)`. + +When you extend this structure, make sure to extend `ContinuousMapClass`. -/ +structure ContinuousMap (X Y : Type*) [TopologicalSpace X] [TopologicalSpace Y] where + /-- The function `X → Y` -/ + protected toFun : X → Y + /-- Proposition that `toFun` is continuous -/ + protected continuous_toFun : Continuous toFun := by continuity + +/-- The type of continuous maps from `X` to `Y`. -/ +notation "C(" X ", " Y ")" => ContinuousMap X Y + +section + +/-- `ContinuousMapClass F X Y` states that `F` is a type of continuous maps. + +You should extend this class when you extend `ContinuousMap`. -/ +class ContinuousMapClass (F : Type*) (X Y : outParam Type*) + [TopologicalSpace X] [TopologicalSpace Y] [FunLike F X Y] : Prop where + /-- Continuity -/ + map_continuous (f : F) : Continuous f + +end + +export ContinuousMapClass (map_continuous) + +attribute [continuity, fun_prop] map_continuous + +section ContinuousMapClass + +variable {F X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] [FunLike F X Y] +variable [ContinuousMapClass F X Y] + +/-- Coerce a bundled morphism with a `ContinuousMapClass` instance to a `ContinuousMap`. -/ +@[coe] def toContinuousMap (f : F) : C(X, Y) := ⟨f, map_continuous f⟩ + +instance : CoeTC F C(X, Y) := ⟨toContinuousMap⟩ + +end ContinuousMapClass + +/-! ### Continuous maps -/ + + +namespace ContinuousMap + +variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] + +instance instFunLike : FunLike C(X, Y) X Y where + coe := ContinuousMap.toFun + coe_injective' f g h := by cases f; cases g; congr + +instance instContinuousMapClass : ContinuousMapClass C(X, Y) X Y where + map_continuous := ContinuousMap.continuous_toFun + +@[simp] +theorem toFun_eq_coe {f : C(X, Y)} : f.toFun = (f : X → Y) := + rfl + +instance : CanLift (X → Y) C(X, Y) DFunLike.coe Continuous := ⟨fun f hf ↦ ⟨⟨f, hf⟩, rfl⟩⟩ + +/-- See note [custom simps projection]. -/ +def Simps.apply (f : C(X, Y)) : X → Y := f + +-- this must come after the coe_to_fun definition +initialize_simps_projections ContinuousMap (toFun → apply) + +@[simp] -- Porting note: removed `norm_cast` attribute +protected theorem coe_coe {F : Type*} [FunLike F X Y] [ContinuousMapClass F X Y] (f : F) : + ⇑(f : C(X, Y)) = f := + rfl + +@[ext] +theorem ext {f g : C(X, Y)} (h : ∀ a, f a = g a) : f = g := + DFunLike.ext _ _ h + +/-- Copy of a `ContinuousMap` with a new `toFun` equal to the old one. Useful to fix definitional +equalities. -/ +protected def copy (f : C(X, Y)) (f' : X → Y) (h : f' = f) : C(X, Y) where + toFun := f' + continuous_toFun := h.symm ▸ f.continuous_toFun + +@[simp] +theorem coe_copy (f : C(X, Y)) (f' : X → Y) (h : f' = f) : ⇑(f.copy f' h) = f' := + rfl + +theorem copy_eq (f : C(X, Y)) (f' : X → Y) (h : f' = f) : f.copy f' h = f := + DFunLike.ext' h + +/-- Deprecated. Use `map_continuous` instead. -/ +protected theorem continuous (f : C(X, Y)) : Continuous f := + f.continuous_toFun + +@[deprecated map_continuous (since := "2024-09-29")] +theorem continuous_set_coe (s : Set C(X, Y)) (f : s) : Continuous (f : X → Y) := + map_continuous _ + +/-- Deprecated. Use `DFunLike.congr_fun` instead. -/ +protected theorem congr_fun {f g : C(X, Y)} (H : f = g) (x : X) : f x = g x := + H ▸ rfl + +/-- Deprecated. Use `DFunLike.congr_arg` instead. -/ +protected theorem congr_arg (f : C(X, Y)) {x y : X} (h : x = y) : f x = f y := + h ▸ rfl + +theorem coe_injective : Function.Injective (DFunLike.coe : C(X, Y) → (X → Y)) := + DFunLike.coe_injective + +@[simp] +theorem coe_mk (f : X → Y) (h : Continuous f) : ⇑(⟨f, h⟩ : C(X, Y)) = f := + rfl + +end ContinuousMap diff --git a/Mathlib/Topology/ContinuousFunction/Ideals.lean b/Mathlib/Topology/ContinuousMap/Ideals.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/Ideals.lean rename to Mathlib/Topology/ContinuousMap/Ideals.lean index e40d94ca79034..5edb4350d5274 100644 --- a/Mathlib/Topology/ContinuousFunction/Ideals.lean +++ b/Mathlib/Topology/ContinuousMap/Ideals.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ import Mathlib.Topology.Algebra.Algebra -import Mathlib.Topology.ContinuousFunction.Compact +import Mathlib.Topology.ContinuousMap.Compact import Mathlib.Topology.UrysohnsLemma import Mathlib.Analysis.RCLike.Basic import Mathlib.Analysis.Normed.Ring.Units @@ -169,7 +169,7 @@ theorem exists_mul_le_one_eqOn_ge (f : C(X, ℝ≥0)) {c : ℝ≥0} (hc : 0 < c) continuous_toFun := ((map_continuous f).sup <| map_continuous _).inv₀ fun _ => (hc.trans_le le_sup_right).ne' }, fun x => - (inv_mul_le_iff (hc.trans_le le_sup_right)).mpr ((mul_one (f x ⊔ c)).symm ▸ le_sup_left), + (inv_mul_le_iff₀ (hc.trans_le le_sup_right)).mpr ((mul_one (f x ⊔ c)).symm ▸ le_sup_left), fun x hx => by simpa only [coe_const, mul_apply, coe_mk, Pi.inv_apply, Pi.sup_apply, Function.const_apply, sup_eq_left.mpr (Set.mem_setOf.mp hx), ne_eq, Pi.one_apply] diff --git a/Mathlib/Topology/ContinuousFunction/LocallyConstant.lean b/Mathlib/Topology/ContinuousMap/LocallyConstant.lean similarity index 92% rename from Mathlib/Topology/ContinuousFunction/LocallyConstant.lean rename to Mathlib/Topology/ContinuousMap/LocallyConstant.lean index a9858942c825d..bbe26fe3ba211 100644 --- a/Mathlib/Topology/ContinuousFunction/LocallyConstant.lean +++ b/Mathlib/Topology/ContinuousMap/LocallyConstant.lean @@ -4,8 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Oliver Nash -/ import Mathlib.Topology.LocallyConstant.Algebra -import Mathlib.Topology.ContinuousFunction.Basic -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Basic +import Mathlib.Topology.ContinuousMap.Algebra /-! # The algebra morphism from locally constant functions to continuous functions. @@ -15,7 +15,7 @@ import Mathlib.Topology.ContinuousFunction.Algebra namespace LocallyConstant -variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] (f : LocallyConstant X Y) +variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] /-- The inclusion of locally-constant functions into continuous functions as a multiplicative monoid hom. -/ diff --git a/Mathlib/Topology/ContinuousFunction/Ordered.lean b/Mathlib/Topology/ContinuousMap/Ordered.lean similarity index 98% rename from Mathlib/Topology/ContinuousFunction/Ordered.lean rename to Mathlib/Topology/ContinuousMap/Ordered.lean index 383451ecd6565..14a4185687a12 100644 --- a/Mathlib/Topology/ContinuousFunction/Ordered.lean +++ b/Mathlib/Topology/ContinuousMap/Ordered.lean @@ -3,9 +3,9 @@ Copyright (c) 2021 Kim Morrison. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison, Shing Tak Lam -/ -import Mathlib.Topology.ContinuousFunction.Basic import Mathlib.Topology.Order.Lattice import Mathlib.Topology.Order.ProjIcc +import Mathlib.Topology.ContinuousMap.Defs /-! # Bundled continuous maps into orders, with order-compatible topology diff --git a/Mathlib/Topology/ContinuousFunction/Polynomial.lean b/Mathlib/Topology/ContinuousMap/Polynomial.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/Polynomial.lean rename to Mathlib/Topology/ContinuousMap/Polynomial.lean index 5e3cd45660fa2..83a3dd5e6a0ed 100644 --- a/Mathlib/Topology/ContinuousFunction/Polynomial.lean +++ b/Mathlib/Topology/ContinuousMap/Polynomial.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kim Morrison -/ import Mathlib.Topology.Algebra.Polynomial -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Topology.UnitInterval import Mathlib.Algebra.Star.Subalgebra diff --git a/Mathlib/Topology/ContinuousFunction/Sigma.lean b/Mathlib/Topology/ContinuousMap/Sigma.lean similarity index 98% rename from Mathlib/Topology/ContinuousFunction/Sigma.lean rename to Mathlib/Topology/ContinuousMap/Sigma.lean index a444781b712f5..320fd5cc4ab1f 100644 --- a/Mathlib/Topology/ContinuousFunction/Sigma.lean +++ b/Mathlib/Topology/ContinuousMap/Sigma.lean @@ -63,7 +63,7 @@ some `i` and a continuous map `g : C(X, Y i)`. See also `Continuous.exists_lift_ with unbundled functions and `ContinuousMap.sigmaCodHomeomorph` for a homeomorphism defined using 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 + let ⟨i, g, hg, hfg⟩ := (map_continuous f).exists_lift_sigma ⟨i, ⟨g, hg⟩, DFunLike.ext' hfg⟩ variable (X Y) diff --git a/Mathlib/Topology/ContinuousFunction/StarOrdered.lean b/Mathlib/Topology/ContinuousMap/StarOrdered.lean similarity index 97% rename from Mathlib/Topology/ContinuousFunction/StarOrdered.lean rename to Mathlib/Topology/ContinuousMap/StarOrdered.lean index 18882fe259d74..b894be96cbeb1 100644 --- a/Mathlib/Topology/ContinuousFunction/StarOrdered.lean +++ b/Mathlib/Topology/ContinuousMap/StarOrdered.lean @@ -5,8 +5,8 @@ Authors: Jireh Loreaux -/ import Mathlib.Analysis.Complex.Basic import Mathlib.Data.Real.StarOrdered -import Mathlib.Topology.ContinuousFunction.Algebra -import Mathlib.Topology.ContinuousFunction.ContinuousMapZero +import Mathlib.Topology.ContinuousMap.Algebra +import Mathlib.Topology.ContinuousMap.ContinuousMapZero /-! # Continuous functions as a star-ordered ring -/ diff --git a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean rename to Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean index 75dd242760f15..643b6ad6595d6 100644 --- a/Mathlib/Topology/ContinuousFunction/StoneWeierstrass.lean +++ b/Mathlib/Topology/ContinuousMap/StoneWeierstrass.lean @@ -6,8 +6,8 @@ Authors: Kim Morrison, Heather Macbeth import Mathlib.Algebra.Algebra.Subalgebra.Unitization import Mathlib.Analysis.RCLike.Basic import Mathlib.Topology.Algebra.StarSubalgebra -import Mathlib.Topology.ContinuousFunction.ContinuousMapZero -import Mathlib.Topology.ContinuousFunction.Weierstrass +import Mathlib.Topology.ContinuousMap.ContinuousMapZero +import Mathlib.Topology.ContinuousMap.Weierstrass /-! # The Stone-Weierstrass theorem @@ -222,9 +222,7 @@ theorem sublattice_closure_eq_top (L : Set C(X, ℝ)) (nA : L.Nonempty) have W_nhd : ∀ x, W x ∈ 𝓝 x := by intro x refine IsOpen.mem_nhds ?_ ?_ - · -- Porting note: mathlib3 `continuity` found `continuous_set_coe` - apply isOpen_lt (continuous_set_coe _ _) - continuity + · apply isOpen_lt <;> fun_prop · dsimp only [W, Set.mem_setOf_eq] rw [h_eq] exact lt_add_of_pos_right _ pos diff --git a/Mathlib/Topology/ContinuousFunction/T0Sierpinski.lean b/Mathlib/Topology/ContinuousMap/T0Sierpinski.lean similarity index 97% rename from Mathlib/Topology/ContinuousFunction/T0Sierpinski.lean rename to Mathlib/Topology/ContinuousMap/T0Sierpinski.lean index 48655f0023ded..4e9903ccc7400 100644 --- a/Mathlib/Topology/ContinuousFunction/T0Sierpinski.lean +++ b/Mathlib/Topology/ContinuousMap/T0Sierpinski.lean @@ -5,7 +5,7 @@ Authors: Ivan Sadofschi Costa -/ import Mathlib.Topology.Order import Mathlib.Topology.Sets.Opens -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # Any T0 space embeds in a product of copies of the Sierpinski space. diff --git a/Mathlib/Topology/ContinuousFunction/Units.lean b/Mathlib/Topology/ContinuousMap/Units.lean similarity index 98% rename from Mathlib/Topology/ContinuousFunction/Units.lean rename to Mathlib/Topology/ContinuousMap/Units.lean index a8c880cf3a2bc..0337bcc434faa 100644 --- a/Mathlib/Topology/ContinuousFunction/Units.lean +++ b/Mathlib/Topology/ContinuousMap/Units.lean @@ -5,7 +5,7 @@ Authors: Jireh Loreaux -/ import Mathlib.Analysis.Normed.Ring.Units import Mathlib.Algebra.Algebra.Spectrum -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra /-! # Units of continuous functions diff --git a/Mathlib/Topology/ContinuousFunction/Weierstrass.lean b/Mathlib/Topology/ContinuousMap/Weierstrass.lean similarity index 100% rename from Mathlib/Topology/ContinuousFunction/Weierstrass.lean rename to Mathlib/Topology/ContinuousMap/Weierstrass.lean diff --git a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean similarity index 99% rename from Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean rename to Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean index 932426106e17d..b9c5713bf06fd 100644 --- a/Mathlib/Topology/ContinuousFunction/ZeroAtInfty.lean +++ b/Mathlib/Topology/ContinuousMap/ZeroAtInfty.lean @@ -3,8 +3,8 @@ Copyright (c) 2022 Jireh Loreaux. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jireh Loreaux -/ -import Mathlib.Topology.ContinuousFunction.Bounded -import Mathlib.Topology.ContinuousFunction.CocompactMap +import Mathlib.Topology.ContinuousMap.Bounded +import Mathlib.Topology.ContinuousMap.CocompactMap /-! # Continuous functions vanishing at infinity @@ -428,7 +428,7 @@ theorem isClosed_range_toBCF : IsClosed (range (toBCF : C₀(α, β) → α → /-- 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 + (completeSpace_iff_isComplete_range isometry_toBCF.isUniformInducing).mpr isClosed_range_toBCF.isComplete end Metric diff --git a/Mathlib/Topology/ContinuousOn.lean b/Mathlib/Topology/ContinuousOn.lean index 69e02cd2a9319..7608fd4158dbb 100644 --- a/Mathlib/Topology/ContinuousOn.lean +++ b/Mathlib/Topology/ContinuousOn.lean @@ -54,12 +54,20 @@ theorem mem_closure_ne_iff_frequently_within {z : α} {s : Set α} : simp [mem_closure_iff_frequently, frequently_nhdsWithin_iff] @[simp] -theorem eventually_nhdsWithin_nhdsWithin {a : α} {s : Set α} {p : α → Prop} : +theorem eventually_eventually_nhdsWithin {a : α} {s : Set α} {p : α → Prop} : (∀ᶠ y in 𝓝[s] a, ∀ᶠ x in 𝓝[s] y, p x) ↔ ∀ᶠ x in 𝓝[s] a, p x := by refine ⟨fun h => ?_, fun h => (eventually_nhds_nhdsWithin.2 h).filter_mono inf_le_left⟩ simp only [eventually_nhdsWithin_iff] at h ⊢ exact h.mono fun x hx hxs => (hx hxs).self_of_nhds hxs +@[deprecated (since := "2024-10-04")] +alias eventually_nhdsWithin_nhdsWithin := eventually_eventually_nhdsWithin + +@[simp] +theorem eventually_mem_nhdsWithin_iff {x : α} {s t : Set α} : + (∀ᶠ x' in 𝓝[s] x, t ∈ 𝓝[s] x') ↔ t ∈ 𝓝[s] x := + eventually_eventually_nhdsWithin + theorem nhdsWithin_eq (a : α) (s : Set α) : 𝓝[s] a = ⨅ t ∈ { t : Set α | a ∈ t ∧ IsOpen t }, 𝓟 (t ∩ s) := ((nhds_basis_opens a).inf_principal s).eq_biInf @@ -609,7 +617,7 @@ theorem continuous_of_cover_nhds {ι : Sort*} {f : α → β} {s : ι → Set α rw [ContinuousAt, ← nhdsWithin_eq_nhds.2 hi] exact hf _ _ (mem_of_mem_nhds hi) -theorem continuousOn_empty (f : α → β) : ContinuousOn f ∅ := fun _ => False.elim +@[simp] theorem continuousOn_empty (f : α → β) : ContinuousOn f ∅ := fun _ => False.elim @[simp] theorem continuousOn_singleton (f : α → β) (a : α) : ContinuousOn f {a} := diff --git a/Mathlib/Topology/Defs/Basic.lean b/Mathlib/Topology/Defs/Basic.lean index 607362753bace..e7526dd6e9024 100644 --- a/Mathlib/Topology/Defs/Basic.lean +++ b/Mathlib/Topology/Defs/Basic.lean @@ -151,6 +151,28 @@ def IsOpenMap (f : X → Y) : Prop := ∀ U : Set X, IsOpen U → IsOpen (f '' U if the image of any closed `U : Set X` is closed in `Y`. -/ def IsClosedMap (f : X → Y) : Prop := ∀ U : Set X, IsClosed U → IsClosed (f '' U) +/-- An open quotient map is an open map `f : X → Y` which is both an open map and a quotient map. +Equivalently, it is a surjective continuous open map. +We use the latter characterization as a definition. + +Many important quotient maps are open quotient maps, including + +- the quotient map from a topological space to its quotient by the action of a group; +- the quotient map from a topological group to its quotient by a normal subgroup; +- the quotient map from a topological spaace to its separation quotient. + +Contrary to general quotient maps, +the category of open quotient maps is closed under `Prod.map`. +-/ +@[mk_iff] +structure IsOpenQuotientMap (f : X → Y) : Prop where + /-- An open quotient map is surjective. -/ + surjective : Function.Surjective f + /-- An open quotient map is continuous. -/ + continuous : Continuous f + /-- An open quotient map is an open map. -/ + isOpenMap : IsOpenMap f + end Defs /-! ### Notation for non-standard topologies -/ diff --git a/Mathlib/Topology/DenseEmbedding.lean b/Mathlib/Topology/DenseEmbedding.lean index f346261d50bed..210caa3dca529 100644 --- a/Mathlib/Topology/DenseEmbedding.lean +++ b/Mathlib/Topology/DenseEmbedding.lean @@ -11,14 +11,14 @@ import Mathlib.Topology.Bases This file defines three properties of functions: -* `DenseRange f` means `f` has dense image; -* `DenseInducing i` means `i` is also `Inducing`, namely it induces the topology on its codomain; -* `DenseEmbedding e` means `e` is further an `Embedding`, namely it is injective and `Inducing`. +* `DenseRange f` means `f` has dense image; +* `IsDenseInducing i` means `i` is also `Inducing`, namely it induces the topology on its codomain; +* `IsDenseEmbedding e` means `e` is further an `Embedding`, namely it is injective and `Inducing`. The main theorem `continuous_extend` gives a criterion for a function `f : X → Z` to a T₃ space Z to extend along a dense embedding `i : X → Y` to a continuous function `g : Y → Z`. Actually `i` only -has to be `DenseInducing` (not necessarily injective). +has to be `IsDenseInducing` (not necessarily injective). -/ @@ -32,30 +32,30 @@ variable {α : Type*} {β : Type*} {γ : Type*} {δ : Type*} /-- `i : α → β` is "dense inducing" if it has dense range and the topology on `α` is the one induced by `i` from the topology on `β`. -/ -structure DenseInducing [TopologicalSpace α] [TopologicalSpace β] (i : α → β) +structure IsDenseInducing [TopologicalSpace α] [TopologicalSpace β] (i : α → β) extends Inducing i : Prop where /-- The range of a dense inducing map is a dense set. -/ protected dense : DenseRange i -namespace DenseInducing +namespace IsDenseInducing variable [TopologicalSpace α] [TopologicalSpace β] variable {i : α → β} -theorem nhds_eq_comap (di : DenseInducing i) : ∀ a : α, 𝓝 a = comap i (𝓝 <| i a) := +theorem nhds_eq_comap (di : IsDenseInducing i) : ∀ a : α, 𝓝 a = comap i (𝓝 <| i a) := di.toInducing.nhds_eq_comap -protected theorem continuous (di : DenseInducing i) : Continuous i := +protected theorem continuous (di : IsDenseInducing i) : Continuous i := di.toInducing.continuous -theorem closure_range (di : DenseInducing i) : closure (range i) = univ := +theorem closure_range (di : IsDenseInducing i) : closure (range i) = univ := di.dense.closure_range -protected theorem preconnectedSpace [PreconnectedSpace α] (di : DenseInducing i) : +protected theorem preconnectedSpace [PreconnectedSpace α] (di : IsDenseInducing i) : PreconnectedSpace β := di.dense.preconnectedSpace di.continuous -theorem closure_image_mem_nhds {s : Set α} {a : α} (di : DenseInducing i) (hs : s ∈ 𝓝 a) : +theorem closure_image_mem_nhds {s : Set α} {a : α} (di : IsDenseInducing i) (hs : s ∈ 𝓝 a) : closure (i '' s) ∈ 𝓝 (i a) := by rw [di.nhds_eq_comap a, ((nhds_basis_opens _).comap _).mem_iff] at hs rcases hs with ⟨U, ⟨haU, hUo⟩, sub : i ⁻¹' U ⊆ s⟩ @@ -64,14 +64,14 @@ theorem closure_image_mem_nhds {s : Set α} {a : α} (di : DenseInducing i) (hs U ⊆ closure (i '' (i ⁻¹' U)) := di.dense.subset_closure_image_preimage_of_isOpen hUo _ ⊆ closure (i '' s) := closure_mono (image_subset i sub) -theorem dense_image (di : DenseInducing i) {s : Set α} : Dense (i '' s) ↔ Dense s := by +theorem dense_image (di : IsDenseInducing i) {s : Set α} : Dense (i '' s) ↔ Dense s := by refine ⟨fun H x => ?_, di.dense.dense_image di.continuous⟩ rw [di.toInducing.closure_eq_preimage_closure_image, H.closure_eq, preimage_univ] trivial /-- If `i : α → β` is a dense embedding with dense complement of the range, then any compact set in `α` has empty interior. -/ -theorem interior_compact_eq_empty [T2Space β] (di : DenseInducing i) (hd : Dense (range i)ᶜ) +theorem interior_compact_eq_empty [T2Space β] (di : IsDenseInducing i) (hd : Dense (range i)ᶜ) {s : Set α} (hs : IsCompact s) : interior s = ∅ := by refine eq_empty_iff_forall_not_mem.2 fun x hx => ?_ rw [mem_interior_iff_mem_nhds] at hx @@ -81,16 +81,19 @@ theorem interior_compact_eq_empty [T2Space β] (di : DenseInducing i) (hd : Dens exact hyi (image_subset_range _ _ hys) /-- The product of two dense inducings is a dense inducing -/ -protected theorem prod [TopologicalSpace γ] [TopologicalSpace δ] {e₁ : α → β} {e₂ : γ → δ} - (de₁ : DenseInducing e₁) (de₂ : DenseInducing e₂) : - DenseInducing fun p : α × γ => (e₁ p.1, e₂ p.2) where - toInducing := de₁.toInducing.prod_map de₂.toInducing - dense := de₁.dense.prod_map de₂.dense +protected theorem prodMap [TopologicalSpace γ] [TopologicalSpace δ] {e₁ : α → β} {e₂ : γ → δ} + (de₁ : IsDenseInducing e₁) (de₂ : IsDenseInducing e₂) : + IsDenseInducing (Prod.map e₁ e₂) where + toInducing := de₁.toInducing.prodMap de₂.toInducing + dense := de₁.dense.prodMap de₂.dense + +@[deprecated (since := "2024-10-06")] +protected alias prod := IsDenseInducing.prodMap open TopologicalSpace -/-- If the domain of a `DenseInducing` map is a separable space, then so is the codomain. -/ -protected theorem separableSpace [SeparableSpace α] (di : DenseInducing i) : SeparableSpace β := +/-- If the domain of a `IsDenseInducing` map is a separable space, then so is the codomain. -/ +protected theorem separableSpace [SeparableSpace α] (di : IsDenseInducing i) : SeparableSpace β := di.dense.separableSpace di.continuous variable [TopologicalSpace δ] {f : γ → α} {g : γ → δ} {h : δ → β} @@ -102,7 +105,7 @@ g↓ ↓e δ -h→ β ``` -/ -theorem tendsto_comap_nhds_nhds {d : δ} {a : α} (di : DenseInducing i) +theorem tendsto_comap_nhds_nhds {d : δ} {a : α} (di : IsDenseInducing i) (H : Tendsto h (𝓝 d) (𝓝 (i a))) (comm : h ∘ g = i ∘ f) : Tendsto f (comap g (𝓝 d)) (𝓝 a) := by have lim1 : map g (comap g (𝓝 d)) ≤ 𝓝 d := map_comap_le replace lim1 : map h (map g (comap g (𝓝 d))) ≤ map h (𝓝 d) := map_mono lim1 @@ -111,10 +114,10 @@ theorem tendsto_comap_nhds_nhds {d : δ} {a : α} (di : DenseInducing i) rw [← di.nhds_eq_comap] at lim2 exact le_trans lim1 lim2 -protected theorem nhdsWithin_neBot (di : DenseInducing i) (b : β) : NeBot (𝓝[range i] b) := +protected theorem nhdsWithin_neBot (di : IsDenseInducing i) (b : β) : NeBot (𝓝[range i] b) := di.dense.nhdsWithin_neBot b -theorem comap_nhds_neBot (di : DenseInducing i) (b : β) : NeBot (comap i (𝓝 b)) := +theorem comap_nhds_neBot (di : IsDenseInducing i) (b : β) : NeBot (comap i (𝓝 b)) := comap_neBot fun s hs => by rcases mem_closure_iff_nhds.1 (di.dense b) s hs with ⟨_, ⟨ha, a, rfl⟩⟩ exact ⟨a, ha⟩ @@ -122,38 +125,38 @@ theorem comap_nhds_neBot (di : DenseInducing i) (b : β) : NeBot (comap i (𝓝 variable [TopologicalSpace γ] /-- If `i : α → β` is a dense inducing, then any function `f : α → γ` "extends" to a function `g = - DenseInducing.extend di f : β → γ`. If `γ` is Hausdorff and `f` has a continuous extension, then + IsDenseInducing.extend di f : β → γ`. If `γ` is Hausdorff and `f` has a continuous extension, then `g` is the unique such extension. In general, `g` might not be continuous or even extend `f`. -/ -def extend (di : DenseInducing i) (f : α → γ) (b : β) : γ := +def extend (di : IsDenseInducing i) (f : α → γ) (b : β) : γ := @limUnder _ _ _ ⟨f (di.dense.some b)⟩ (comap i (𝓝 b)) f -theorem extend_eq_of_tendsto [T2Space γ] (di : DenseInducing i) {b : β} {c : γ} {f : α → γ} +theorem extend_eq_of_tendsto [T2Space γ] (di : IsDenseInducing i) {b : β} {c : γ} {f : α → γ} (hf : Tendsto f (comap i (𝓝 b)) (𝓝 c)) : di.extend f b = c := haveI := di.comap_nhds_neBot hf.limUnder_eq -theorem extend_eq_at [T2Space γ] (di : DenseInducing i) {f : α → γ} {a : α} +theorem extend_eq_at [T2Space γ] (di : IsDenseInducing i) {f : α → γ} {a : α} (hf : ContinuousAt f a) : di.extend f (i a) = f a := extend_eq_of_tendsto _ <| di.nhds_eq_comap a ▸ hf -theorem extend_eq_at' [T2Space γ] (di : DenseInducing i) {f : α → γ} {a : α} (c : γ) +theorem extend_eq_at' [T2Space γ] (di : IsDenseInducing i) {f : α → γ} {a : α} (c : γ) (hf : Tendsto f (𝓝 a) (𝓝 c)) : di.extend f (i a) = f a := di.extend_eq_at (continuousAt_of_tendsto_nhds hf) -theorem extend_eq [T2Space γ] (di : DenseInducing i) {f : α → γ} (hf : Continuous f) (a : α) : +theorem extend_eq [T2Space γ] (di : IsDenseInducing i) {f : α → γ} (hf : Continuous f) (a : α) : di.extend f (i a) = f a := di.extend_eq_at hf.continuousAt /-- Variation of `extend_eq` where we ask that `f` has a limit along `comap i (𝓝 b)` for each `b : β`. This is a strictly stronger assumption than continuity of `f`, but in a lot of cases you'd have to prove it anyway to use `continuous_extend`, so this avoids doing the work twice. -/ -theorem extend_eq' [T2Space γ] {f : α → γ} (di : DenseInducing i) +theorem extend_eq' [T2Space γ] {f : α → γ} (di : IsDenseInducing i) (hf : ∀ b, ∃ c, Tendsto f (comap i (𝓝 b)) (𝓝 c)) (a : α) : di.extend f (i a) = f a := by rcases hf (i a) with ⟨b, hb⟩ refine di.extend_eq_at' b ?_ rwa [← di.toInducing.nhds_eq_comap] at hb -theorem extend_unique_at [T2Space γ] {b : β} {f : α → γ} {g : β → γ} (di : DenseInducing i) +theorem extend_unique_at [T2Space γ] {b : β} {f : α → γ} {g : β → γ} (di : IsDenseInducing i) (hf : ∀ᶠ x in comap i (𝓝 b), g (i x) = f x) (hg : ContinuousAt g b) : di.extend f b = g b := by refine di.extend_eq_of_tendsto fun s hs => mem_map.2 ?_ suffices ∀ᶠ x : α in comap i (𝓝 b), g (i x) ∈ s from @@ -163,11 +166,11 @@ theorem extend_unique_at [T2Space γ] {b : β} {f : α → γ} {g : β → γ} ( rintro _ hxs x rfl exact hxs -theorem extend_unique [T2Space γ] {f : α → γ} {g : β → γ} (di : DenseInducing i) +theorem extend_unique [T2Space γ] {f : α → γ} {g : β → γ} (di : IsDenseInducing i) (hf : ∀ x, g (i x) = f x) (hg : Continuous g) : di.extend f = g := funext fun _ => extend_unique_at di (Eventually.of_forall hf) hg.continuousAt -theorem continuousAt_extend [T3Space γ] {b : β} {f : α → γ} (di : DenseInducing i) +theorem continuousAt_extend [T3Space γ] {b : β} {f : α → γ} (di : IsDenseInducing i) (hf : ∀ᶠ x in 𝓝 b, ∃ c, Tendsto f (comap i <| 𝓝 x) (𝓝 c)) : ContinuousAt (di.extend f) b := by set φ := di.extend f haveI := di.comap_nhds_neBot @@ -189,61 +192,66 @@ theorem continuousAt_extend [T3Space γ] {b : β} {f : α → γ} (di : DenseInd use V₂ tauto -theorem continuous_extend [T3Space γ] {f : α → γ} (di : DenseInducing i) +theorem continuous_extend [T3Space γ] {f : α → γ} (di : IsDenseInducing i) (hf : ∀ b, ∃ c, Tendsto f (comap i (𝓝 b)) (𝓝 c)) : Continuous (di.extend f) := continuous_iff_continuousAt.mpr fun _ => di.continuousAt_extend <| univ_mem' hf theorem mk' (i : α → β) (c : Continuous i) (dense : ∀ x, x ∈ closure (range i)) - (H : ∀ (a : α), ∀ s ∈ 𝓝 a, ∃ t ∈ 𝓝 (i a), ∀ b, i b ∈ t → b ∈ s) : DenseInducing i := + (H : ∀ (a : α), ∀ s ∈ 𝓝 a, ∃ t ∈ 𝓝 (i a), ∀ b, i b ∈ t → b ∈ s) : IsDenseInducing i := { toInducing := inducing_iff_nhds.2 fun a => le_antisymm (c.tendsto _).le_comap (by simpa [Filter.le_def] using H a) dense } -end DenseInducing +end IsDenseInducing /-- A dense embedding is an embedding with dense image. -/ -structure DenseEmbedding [TopologicalSpace α] [TopologicalSpace β] (e : α → β) extends - DenseInducing e : Prop where +structure IsDenseEmbedding [TopologicalSpace α] [TopologicalSpace β] (e : α → β) extends + IsDenseInducing e : Prop where /-- A dense embedding is injective. -/ inj : Function.Injective e -theorem DenseEmbedding.mk' [TopologicalSpace α] [TopologicalSpace β] (e : α → β) (c : Continuous e) +lemma IsDenseEmbedding.mk' [TopologicalSpace α] [TopologicalSpace β] (e : α → β) (c : Continuous e) (dense : DenseRange e) (inj : Function.Injective e) - (H : ∀ (a : α), ∀ s ∈ 𝓝 a, ∃ t ∈ 𝓝 (e a), ∀ b, e b ∈ t → b ∈ s) : DenseEmbedding e := - { DenseInducing.mk' e c dense H with inj } + (H : ∀ (a : α), ∀ s ∈ 𝓝 a, ∃ t ∈ 𝓝 (e a), ∀ b, e b ∈ t → b ∈ s) : IsDenseEmbedding e := + { IsDenseInducing.mk' e c dense H with inj } + +@[deprecated (since := "2024-09-30")] +alias DenseEmbedding.mk' := IsDenseEmbedding.mk' -namespace DenseEmbedding +namespace IsDenseEmbedding open TopologicalSpace variable [TopologicalSpace α] [TopologicalSpace β] [TopologicalSpace γ] [TopologicalSpace δ] variable {e : α → β} -theorem inj_iff (de : DenseEmbedding e) {x y} : e x = e y ↔ x = y := +theorem inj_iff (de : IsDenseEmbedding e) {x y} : e x = e y ↔ x = y := de.inj.eq_iff -theorem to_embedding (de : DenseEmbedding e) : Embedding e := +theorem to_embedding (de : IsDenseEmbedding e) : Embedding e := { induced := de.induced inj := de.inj } -/-- If the domain of a `DenseEmbedding` is a separable space, then so is its codomain. -/ -protected theorem separableSpace [SeparableSpace α] (de : DenseEmbedding e) : SeparableSpace β := - de.toDenseInducing.separableSpace +/-- If the domain of a `IsDenseEmbedding` is a separable space, then so is its codomain. -/ +protected theorem separableSpace [SeparableSpace α] (de : IsDenseEmbedding e) : SeparableSpace β := + de.toIsDenseInducing.separableSpace /-- The product of two dense embeddings is a dense embedding. -/ -protected theorem prod {e₁ : α → β} {e₂ : γ → δ} (de₁ : DenseEmbedding e₁) - (de₂ : DenseEmbedding e₂) : DenseEmbedding fun p : α × γ => (e₁ p.1, e₂ p.2) := - { de₁.toDenseInducing.prod de₂.toDenseInducing with +protected theorem prodMap {e₁ : α → β} {e₂ : γ → δ} (de₁ : IsDenseEmbedding e₁) + (de₂ : IsDenseEmbedding e₂) : IsDenseEmbedding fun p : α × γ => (e₁ p.1, e₂ p.2) := + { de₁.toIsDenseInducing.prodMap de₂.toIsDenseInducing with inj := de₁.inj.prodMap de₂.inj } +@[deprecated (since := "2024-10-06")] protected alias prod := IsDenseEmbedding.prodMap + /-- The dense embedding of a subtype inside its closure. -/ @[simps] def subtypeEmb {α : Type*} (p : α → Prop) (e : α → β) (x : { x // p x }) : { x // x ∈ closure (e '' { x | p x }) } := ⟨e x, subset_closure <| mem_image_of_mem e x.prop⟩ -protected theorem subtype (de : DenseEmbedding e) (p : α → Prop) : - DenseEmbedding (subtypeEmb p e) := +protected theorem subtype (de : IsDenseEmbedding e) (p : α → Prop) : + IsDenseEmbedding (subtypeEmb p e) := { dense := dense_iff_closure_eq.2 <| by ext ⟨x, hx⟩ @@ -255,18 +263,24 @@ protected theorem subtype (de : DenseEmbedding e) (p : α → Prop) : simp [subtypeEmb, nhds_subtype_eq_comap, de.toInducing.nhds_eq_comap, comap_comap, Function.comp_def] } -theorem dense_image (de : DenseEmbedding e) {s : Set α} : Dense (e '' s) ↔ Dense s := - de.toDenseInducing.dense_image - -end DenseEmbedding +theorem dense_image (de : IsDenseEmbedding e) {s : Set α} : Dense (e '' s) ↔ Dense s := + de.toIsDenseInducing.dense_image -theorem denseEmbedding_id {α : Type*} [TopologicalSpace α] : DenseEmbedding (id : α → α) := +protected lemma id {α : Type*} [TopologicalSpace α] : IsDenseEmbedding (id : α → α) := { embedding_id with dense := denseRange_id } -theorem Dense.denseEmbedding_val [TopologicalSpace α] {s : Set α} (hs : Dense s) : - DenseEmbedding ((↑) : s → α) := +end IsDenseEmbedding + +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_id := IsDenseEmbedding.id + +theorem Dense.isDenseEmbedding_val [TopologicalSpace α] {s : Set α} (hs : Dense s) : + IsDenseEmbedding ((↑) : s → α) := { embedding_subtype_val with dense := hs.denseRange_val } +@[deprecated (since := "2024-09-30")] +alias Dense.denseEmbedding_val := Dense.isDenseEmbedding_val + theorem isClosed_property [TopologicalSpace β] {e : α → β} {p : β → Prop} (he : DenseRange e) (hp : IsClosed { x | p x }) (h : ∀ a, p (e a)) : ∀ b, p b := have : univ ⊆ { b | p b } := @@ -279,14 +293,14 @@ theorem isClosed_property [TopologicalSpace β] {e : α → β} {p : β → Prop theorem isClosed_property2 [TopologicalSpace β] {e : α → β} {p : β → β → Prop} (he : DenseRange e) (hp : IsClosed { q : β × β | p q.1 q.2 }) (h : ∀ a₁ a₂, p (e a₁) (e a₂)) : ∀ b₁ b₂, p b₁ b₂ := - have : ∀ q : β × β, p q.1 q.2 := isClosed_property (he.prod_map he) hp fun _ => h _ _ + have : ∀ q : β × β, p q.1 q.2 := isClosed_property (he.prodMap he) hp fun _ => h _ _ fun b₁ b₂ => this ⟨b₁, b₂⟩ theorem isClosed_property3 [TopologicalSpace β] {e : α → β} {p : β → β → β → Prop} (he : DenseRange e) (hp : IsClosed { q : β × β × β | p q.1 q.2.1 q.2.2 }) (h : ∀ a₁ a₂ a₃, p (e a₁) (e a₂) (e a₃)) : ∀ b₁ b₂ b₃, p b₁ b₂ b₃ := have : ∀ q : β × β × β, p q.1 q.2.1 q.2.2 := - isClosed_property (he.prod_map <| he.prod_map he) hp fun _ => h _ _ _ + isClosed_property (he.prodMap <| he.prodMap he) hp fun _ => h _ _ _ fun b₁ b₂ b₃ => this ⟨b₁, b₂, b₃⟩ @[elab_as_elim] @@ -319,9 +333,9 @@ theorem DenseRange.equalizer (hfd : DenseRange f) {g h : β → γ} (hg : Contin end -- Bourbaki GT III §3 no.4 Proposition 7 (generalised to any dense-inducing map to a T₃ space) -theorem Filter.HasBasis.hasBasis_of_denseInducing [TopologicalSpace α] [TopologicalSpace β] +theorem Filter.HasBasis.hasBasis_of_isDenseInducing [TopologicalSpace α] [TopologicalSpace β] [T3Space β] {ι : Type*} {s : ι → Set α} {p : ι → Prop} {x : α} (h : (𝓝 x).HasBasis p s) - {f : α → β} (hf : DenseInducing f) : (𝓝 (f x)).HasBasis p fun i => closure <| f '' s i := by + {f : α → β} (hf : IsDenseInducing f) : (𝓝 (f x)).HasBasis p fun i => closure <| f '' s i := by rw [Filter.hasBasis_iff] at h ⊢ intro T refine ⟨fun hT => ?_, fun hT => ?_⟩ diff --git a/Mathlib/Topology/DiscreteQuotient.lean b/Mathlib/Topology/DiscreteQuotient.lean index a6413350f7c54..ed3253cad0993 100644 --- a/Mathlib/Topology/DiscreteQuotient.lean +++ b/Mathlib/Topology/DiscreteQuotient.lean @@ -182,7 +182,7 @@ variable {A B C : DiscreteQuotient X} /-- The map induced by a refinement of a discrete quotient. -/ def ofLE (h : A ≤ B) : A → B := - Quotient.map' (fun x => x) h + Quotient.map' id h @[simp] theorem ofLE_refl : ofLE (le_refl A) = id := by diff --git a/Mathlib/Topology/EMetricSpace/Basic.lean b/Mathlib/Topology/EMetricSpace/Basic.lean index 20efe03e7d47a..0aba00ba4c0d7 100644 --- a/Mathlib/Topology/EMetricSpace/Basic.lean +++ b/Mathlib/Topology/EMetricSpace/Basic.lean @@ -58,28 +58,38 @@ theorem edist_le_range_sum_of_edist_le {f : ℕ → α} (n : ℕ) {d : ℕ → namespace EMetric -theorem uniformInducing_iff [PseudoEMetricSpace β] {f : α → β} : - UniformInducing f ↔ UniformContinuous f ∧ +theorem isUniformInducing_iff [PseudoEMetricSpace β] {f : α → β} : + IsUniformInducing f ↔ UniformContinuous f ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, edist (f a) (f b) < ε → edist a b < δ := - uniformInducing_iff'.trans <| Iff.rfl.and <| + isUniformInducing_iff'.trans <| Iff.rfl.and <| ((uniformity_basis_edist.comap _).le_basis_iff uniformity_basis_edist).trans <| by simp only [subset_def, Prod.forall]; rfl +@[deprecated (since := "2024-10-05")] +alias uniformInducing_iff := isUniformInducing_iff + /-- ε-δ characterization of uniform embeddings on pseudoemetric spaces -/ -nonrec theorem uniformEmbedding_iff [PseudoEMetricSpace β] {f : α → β} : - UniformEmbedding f ↔ Function.Injective f ∧ UniformContinuous f ∧ +nonrec theorem isUniformEmbedding_iff [PseudoEMetricSpace β] {f : α → β} : + IsUniformEmbedding f ↔ Function.Injective f ∧ UniformContinuous f ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, edist (f a) (f b) < ε → edist a b < δ := - (uniformEmbedding_iff _).trans <| and_comm.trans <| Iff.rfl.and uniformInducing_iff + (isUniformEmbedding_iff _).trans <| and_comm.trans <| Iff.rfl.and isUniformInducing_iff + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_iff := isUniformEmbedding_iff /-- If a map between pseudoemetric spaces is a uniform embedding then the edistance between `f x` and `f y` is controlled in terms of the distance between `x` and `y`. -In fact, this lemma holds for a `UniformInducing` map. +In fact, this lemma holds for a `IsUniformInducing` map. TODO: generalize? -/ -theorem controlled_of_uniformEmbedding [PseudoEMetricSpace β] {f : α → β} (h : UniformEmbedding f) : +theorem controlled_of_isUniformEmbedding [PseudoEMetricSpace β] {f : α → β} + (h : IsUniformEmbedding f) : (∀ ε > 0, ∃ δ > 0, ∀ {a b : α}, edist a b < δ → edist (f a) (f b) < ε) ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, edist (f a) (f b) < ε → edist a b < δ := - ⟨uniformContinuous_iff.1 h.uniformContinuous, (uniformEmbedding_iff.1 h).2.2⟩ + ⟨uniformContinuous_iff.1 h.uniformContinuous, (isUniformEmbedding_iff.1 h).2.2⟩ + +@[deprecated (since := "2024-10-01")] +alias controlled_of_uniformEmbedding := controlled_of_isUniformEmbedding /-- ε-δ characterization of Cauchy sequences on pseudoemetric spaces -/ protected theorem cauchy_iff {f : Filter α} : @@ -231,11 +241,14 @@ instance (priority := 100) EMetricSpace.instT0Space : T0Space γ where /-- A map between emetric spaces is a uniform embedding if and only if the edistance between `f x` and `f y` is controlled in terms of the distance between `x` and `y` and conversely. -/ -theorem EMetric.uniformEmbedding_iff' [EMetricSpace β] {f : γ → β} : - UniformEmbedding f ↔ +theorem EMetric.isUniformEmbedding_iff' [EMetricSpace β] {f : γ → β} : + IsUniformEmbedding f ↔ (∀ ε > 0, ∃ δ > 0, ∀ {a b : γ}, edist a b < δ → edist (f a) (f b) < ε) ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : γ}, edist (f a) (f b) < ε → edist a b < δ := by - rw [uniformEmbedding_iff_uniformInducing, uniformInducing_iff, uniformContinuous_iff] + rw [isUniformEmbedding_iff_isUniformInducing, isUniformInducing_iff, uniformContinuous_iff] + +@[deprecated (since := "2024-10-01")] +alias EMetric.uniformEmbedding_iff' := EMetric.isUniformEmbedding_iff' /-- If a `PseudoEMetricSpace` is a T₀ space, then it is an `EMetricSpace`. -/ -- Porting note: made `reducible`; diff --git a/Mathlib/Topology/EMetricSpace/Defs.lean b/Mathlib/Topology/EMetricSpace/Defs.lean index 5afe753e4baa3..2b6096cad74f3 100644 --- a/Mathlib/Topology/EMetricSpace/Defs.lean +++ b/Mathlib/Topology/EMetricSpace/Defs.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.ENNReal.Inv -import Mathlib.Topology.UniformSpace.Basic +import Mathlib.Topology.UniformSpace.OfFun /-! # Extended metric spaces @@ -25,7 +25,7 @@ to `EMetricSpace` at the end. -/ assert_not_exists Nat.instLocallyFiniteOrder -assert_not_exists UniformEmbedding +assert_not_exists IsUniformEmbedding assert_not_exists TendstoUniformlyOnFilter open Set Filter diff --git a/Mathlib/Topology/EMetricSpace/Diam.lean b/Mathlib/Topology/EMetricSpace/Diam.lean index 7fb1092cbfdc0..18895f5377d0d 100644 --- a/Mathlib/Topology/EMetricSpace/Diam.lean +++ b/Mathlib/Topology/EMetricSpace/Diam.lean @@ -4,7 +4,6 @@ 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.EMetricSpace.Pi -import Mathlib.Data.ENNReal.Real /-! # Diameters of sets in extended metric spaces diff --git a/Mathlib/Topology/ExtendFrom.lean b/Mathlib/Topology/ExtendFrom.lean index e425d7ce55e1a..1c043eb2756ea 100644 --- a/Mathlib/Topology/ExtendFrom.lean +++ b/Mathlib/Topology/ExtendFrom.lean @@ -12,7 +12,7 @@ The main definition of this file is `extendFrom A f` where `f : X → Y` and `A : Set X`. This defines a new function `g : X → Y` which maps any `x₀ : X` to the limit of `f` as `x` tends to `x₀`, if such a limit exists. -This is analogous to the way `DenseInducing.extend` "extends" a function +This is analogous to the way `IsDenseInducing.extend` "extends" a function `f : X → Z` to a function `g : Y → Z` along a dense inducing `i : X → Y`. The main theorem we prove about this definition is `continuousOn_extendFrom` diff --git a/Mathlib/Topology/FiberBundle/Constructions.lean b/Mathlib/Topology/FiberBundle/Constructions.lean index 8a7ea9e221f3c..b5cac2629b8cf 100644 --- a/Mathlib/Topology/FiberBundle/Constructions.lean +++ b/Mathlib/Topology/FiberBundle/Constructions.lean @@ -138,8 +138,7 @@ theorem Prod.continuous_to_fun : ContinuousOn (Prod.toFun' e₁ e₂) have hf₁ : Continuous f₁ := (Prod.inducing_diag F₁ E₁ F₂ E₂).continuous have hf₂ : ContinuousOn f₂ (e₁.source ×ˢ e₂.source) := e₁.toPartialHomeomorph.continuousOn.prod_map e₂.toPartialHomeomorph.continuousOn - have hf₃ : Continuous f₃ := - (continuous_fst.comp continuous_fst).prod_mk (continuous_snd.prod_map continuous_snd) + have hf₃ : Continuous f₃ := by fun_prop refine ((hf₃.comp_continuousOn hf₂).comp hf₁.continuousOn ?_).congr ?_ · rw [e₁.source_eq, e₂.source_eq] exact mapsTo_preimage _ _ @@ -176,8 +175,7 @@ theorem Prod.right_inv {x : B × F₁ × F₂} theorem Prod.continuous_inv_fun : ContinuousOn (Prod.invFun' e₁ e₂) ((e₁.baseSet ∩ e₂.baseSet) ×ˢ univ) := by rw [(Prod.inducing_diag F₁ E₁ F₂ E₂).continuousOn_iff] - have H₁ : Continuous fun p : B × F₁ × F₂ ↦ ((p.1, p.2.1), (p.1, p.2.2)) := - (continuous_id.prod_map continuous_fst).prod_mk (continuous_id.prod_map continuous_snd) + have H₁ : Continuous fun p : B × F₁ × F₂ ↦ ((p.1, p.2.1), (p.1, p.2.2)) := by fun_prop refine (e₁.continuousOn_symm.prod_map e₂.continuousOn_symm).comp H₁.continuousOn ?_ exact fun x h ↦ ⟨⟨h.1.1, mem_univ _⟩, ⟨h.1.2, mem_univ _⟩⟩ @@ -226,7 +224,7 @@ variable [∀ x, Zero (E₁ x)] [∀ x, Zero (E₂ x)] [∀ x : B, TopologicalSp noncomputable instance FiberBundle.prod : FiberBundle (F₁ × F₂) (E₁ ×ᵇ E₂) where totalSpaceMk_inducing' b := by rw [← (Prod.inducing_diag F₁ E₁ F₂ E₂).of_comp_iff] - exact (totalSpaceMk_inducing F₁ E₁ b).prod_map (totalSpaceMk_inducing F₂ E₂ b) + exact (totalSpaceMk_inducing F₁ E₁ b).prodMap (totalSpaceMk_inducing F₂ E₂ b) trivializationAtlas' := { e | ∃ (e₁ : Trivialization F₁ (π F₁ E₁)) (e₂ : Trivialization F₂ (π F₂ E₂)) (_ : MemTrivializationAtlas e₁) (_ : MemTrivializationAtlas e₂), @@ -334,7 +332,7 @@ noncomputable def Trivialization.pullback (e : Trivialization F (π F E)) (f : K pullbackTotalSpaceEmbedding] refine continuousOn_fst.prod - (e.continuousOn_symm.comp ((map_continuous f).prod_map continuous_id).continuousOn + (e.continuousOn_symm.comp ((map_continuous f).prodMap continuous_id).continuousOn Subset.rfl) source_eq := by dsimp only diff --git a/Mathlib/Topology/FiberPartition.lean b/Mathlib/Topology/FiberPartition.lean index c01b90f3fe77b..8e21ee229b9e1 100644 --- a/Mathlib/Topology/FiberPartition.lean +++ b/Mathlib/Topology/FiberPartition.lean @@ -29,7 +29,7 @@ variable [TopologicalSpace S] /-- The canonical map from the disjoint union induced by `f` to `S`. -/ @[simps apply] def sigmaIsoHom : C((x : Fiber f) × x.val, S) where - toFun := fun ⟨a, x⟩ ↦ x.val + toFun | ⟨a, x⟩ => x.val lemma sigmaIsoHom_inj : Function.Injective (sigmaIsoHom f) := by rintro ⟨⟨_, _, rfl⟩, ⟨_, hx⟩⟩ ⟨⟨_, _, rfl⟩, ⟨_, hy⟩⟩ h @@ -43,7 +43,7 @@ lemma sigmaIsoHom_surj : Function.Surjective (sigmaIsoHom f) := /-- The inclusion map from a component of the disjoint union induced by `f` into `S`. -/ def sigmaIncl (a : Fiber f) : C(a.val, S) where - toFun := fun x ↦ x.val + toFun x := x.val /-- The inclusion map from a fiber of a composition into the intermediate fiber. -/ def sigmaInclIncl {X : Type*} (g : Y → X) (a : Fiber (g ∘ f)) @@ -53,7 +53,7 @@ def sigmaInclIncl {X : Type*} (g : Y → X) (a : Fiber (g ∘ f)) have := x.prop simp only [sigmaIncl, ContinuousMap.coe_mk, Fiber.mem_iff_eq_image, comp_apply] at this rw [Fiber.mem_iff_eq_image, Fiber.mk_image, this, ← Fiber.map_preimage_eq_image] - rfl⟩ + simp [sigmaIncl]⟩ variable (l : LocallyConstant S Y) [CompactSpace S] diff --git a/Mathlib/Topology/Germ.lean b/Mathlib/Topology/Germ.lean index 5b1e7856f5d62..35d47bcfa9b8a 100644 --- a/Mathlib/Topology/Germ.lean +++ b/Mathlib/Topology/Germ.lean @@ -30,9 +30,6 @@ to the corresponding germ of functions `X → Z` at `x ∈ X` resp. `Y → Z` at `f` is constant. -/ -variable {F G : Type*} [NormedAddCommGroup F] [NormedSpace ℝ F] - [NormedAddCommGroup G] [NormedSpace ℝ G] - open scoped Topology open Filter Set diff --git a/Mathlib/Topology/Gluing.lean b/Mathlib/Topology/Gluing.lean index d620e28015df4..c6d7656eb38bc 100644 --- a/Mathlib/Topology/Gluing.lean +++ b/Mathlib/Topology/Gluing.lean @@ -167,10 +167,8 @@ theorem eqvGen_of_π_eq let diagram := parallelPair 𝖣.diagram.fstSigmaMap 𝖣.diagram.sndSigmaMap ⋙ forget _ have : colimit.ι diagram one x = colimit.ι diagram one y := by dsimp only [coequalizer.π, ContinuousMap.toFun_eq_coe] at h - -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 - erw [← ι_preservesColimitsIso_hom, forget_map_eq_coe, types_comp_apply, h] + rw [← ι_preservesColimitsIso_hom, forget_map_eq_coe, types_comp_apply, h] simp - rfl have : (colimit.ι diagram _ ≫ colim.map _ ≫ (colimit.isoColimitCocone _).hom) _ = (colimit.ι diagram _ ≫ colim.map _ ≫ (colimit.isoColimitCocone _).hom) _ := @@ -216,8 +214,7 @@ theorem ι_eq_iff_rel (i j : D.J) (x : D.U i) (y : D.U j) : dsimp only at * -- Porting note: there were `subst e₁` and `subst e₂`, instead of the `rw` rw [← e₁, ← e₂] at * - erw [D.glue_condition_apply] -- now `erw` after #13170 - rfl -- now `rfl` after #13170 + rw [D.glue_condition_apply] theorem ι_injective (i : D.J) : Function.Injective (𝖣.ι i) := by intro x y h @@ -266,8 +263,7 @@ theorem preimage_image_eq_image (i j : D.J) (U : Set (𝖣.U i)) : generalize 𝖣.ι i '' U = U' -- next 4 lines were `simp` before #13170 simp only [GlueData.diagram_l, GlueData.diagram_r, Set.mem_preimage, coe_comp, Function.comp_apply] - erw [D.glue_condition_apply] - rfl + rw [D.glue_condition_apply] rw [← this, Set.image_preimage_eq_inter_range] symm apply Set.inter_eq_self_of_subset_left @@ -349,10 +345,7 @@ def MkCore.t' (h : MkCore.{u}) (i j k : h.J) : refine ⟨⟨⟨(h.t i j x.1.1).1, ?_⟩, h.t i j x.1.1⟩, rfl⟩ rcases x with ⟨⟨⟨x, hx⟩, ⟨x', hx'⟩⟩, rfl : x = x'⟩ exact h.t_inter _ ⟨x, hx⟩ hx' - -- Porting note: was `continuity`, see https://github.com/leanprover-community/mathlib4/issues/5030 - have : Continuous (h.t i j) := map_continuous (self := ContinuousMap.toContinuousMapClass) _ - set_option tactic.skipAssignedInstances false in - exact ((Continuous.subtype_mk (by fun_prop) _).prod_mk (by fun_prop)).subtype_mk _ + fun_prop /-- This is a constructor of `TopCat.GlueData` whose arguments are in terms of elements and intersections rather than subobjects and pullbacks. Please refer to `TopCat.GlueData.MkCore` for @@ -383,7 +376,7 @@ def mk' (h : MkCore.{u}) : TopCat.GlueData where simp only [Iso.inv_hom_id_assoc, Category.assoc, Category.id_comp] rw [← Iso.eq_inv_comp, Iso.inv_hom_id] ext1 ⟨⟨⟨x, hx⟩, ⟨x', hx'⟩⟩, rfl : x = x'⟩ - -- The next 9 tactics (up to `convert ...` were a single `rw` before leanprover/lean4#2644 + -- The next 6 tactics (up to `convert ...` were a single `rw` before leanprover/lean4#2644 -- rw [comp_app, ContinuousMap.coe_mk, comp_app, id_app, ContinuousMap.coe_mk, Subtype.mk_eq_mk, -- Prod.mk.inj_iff, Subtype.mk_eq_mk, Subtype.ext_iff, and_self_iff] erw [comp_app] --, comp_app, id_app] -- now `erw` after #13170 @@ -392,10 +385,7 @@ def mk' (h : MkCore.{u}) : TopCat.GlueData where erw [id_app] rw [ContinuousMap.coe_mk] erw [Subtype.mk_eq_mk] - rw [Prod.mk.inj_iff] - erw [Subtype.mk_eq_mk] - rw [Subtype.ext_iff] - rw [and_self_iff] + rw [Prod.mk.inj_iff, Subtype.mk_eq_mk, Subtype.ext_iff, and_self_iff] convert congr_arg Subtype.val (h.t_inv k i ⟨x, hx'⟩) using 3 refine Subtype.ext ?_ exact h.cocycle i j k ⟨x, hx⟩ hx' @@ -460,7 +450,7 @@ theorem fromOpenSubsetsGlue_isOpenMap : IsOpenMap (fromOpenSubsetsGlue U) := by use fromOpenSubsetsGlue U '' s ∩ Set.range (@Opens.inclusion' (TopCat.of α) (U i)) use Set.inter_subset_left constructor - · erw [← Set.image_preimage_eq_inter_range] + · rw [← Set.image_preimage_eq_inter_range] apply (Opens.openEmbedding (X := TopCat.of α) (U i)).isOpenMap convert hs i using 1 erw [← ι_fromOpenSubsetsGlue, coe_comp, Set.preimage_comp] diff --git a/Mathlib/Topology/Hom/Open.lean b/Mathlib/Topology/Hom/Open.lean index bec44e93eff1e..86051435726a8 100644 --- a/Mathlib/Topology/Hom/Open.lean +++ b/Mathlib/Topology/Hom/Open.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.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # Continuous open maps diff --git a/Mathlib/Topology/Homeomorph.lean b/Mathlib/Topology/Homeomorph.lean index bc14d3525fda0..6d33a57317001 100644 --- a/Mathlib/Topology/Homeomorph.lean +++ b/Mathlib/Topology/Homeomorph.lean @@ -54,11 +54,11 @@ theorem toEquiv_injective : Function.Injective (toEquiv : X ≃ₜ Y → X ≃ Y | ⟨_, _, _⟩, ⟨_, _, _⟩, rfl => rfl instance : EquivLike (X ≃ₜ Y) X Y where - coe := fun h => h.toEquiv - 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 <| DFunLike.ext' H + coe h := h.toEquiv + inv h := h.toEquiv.symm + left_inv h := h.left_inv + right_inv h := h.right_inv + coe_injective' _ _ H _ := toEquiv_injective <| DFunLike.ext' H instance : CoeFun (X ≃ₜ Y) fun _ ↦ X → Y := ⟨DFunLike.coe⟩ @@ -308,9 +308,12 @@ protected theorem t2Space [T2Space X] (h : X ≃ₜ Y) : T2Space Y := protected theorem t3Space [T3Space X] (h : X ≃ₜ Y) : T3Space Y := h.symm.embedding.t3Space -protected theorem denseEmbedding (h : X ≃ₜ Y) : DenseEmbedding h := +theorem isDenseEmbedding (h : X ≃ₜ Y) : IsDenseEmbedding h := { h.embedding with dense := h.surjective.denseRange } +@[deprecated (since := "2024-09-30")] +alias denseEmbedding := isDenseEmbedding + @[simp] theorem isOpen_preimage (h : X ≃ₜ Y) {s : Set Y} : IsOpen (h ⁻¹' s) ↔ IsOpen s := h.quotientMap.isOpen_preimage @@ -495,8 +498,6 @@ def sumCongr (h₁ : X ≃ₜ X') (h₂ : Y ≃ₜ Y') : X ⊕ Y ≃ₜ X' ⊕ Y /-- Product of two homeomorphisms. -/ def prodCongr (h₁ : X ≃ₜ X') (h₂ : Y ≃ₜ Y') : X × Y ≃ₜ X' × Y' where - continuous_toFun := h₁.continuous.prod_map h₂.continuous - continuous_invFun := h₁.symm.continuous.prod_map h₂.symm.continuous toEquiv := h₁.toEquiv.prodCongr h₂.toEquiv @[simp] @@ -693,9 +694,9 @@ section Distrib def sumProdDistrib : (X ⊕ Y) × Z ≃ₜ (X × Z) ⊕ (Y × Z) := Homeomorph.symm <| homeomorphOfContinuousOpen (Equiv.sumProdDistrib X Y Z).symm - ((continuous_inl.prod_map continuous_id).sum_elim - (continuous_inr.prod_map continuous_id)) <| - (isOpenMap_inl.prod IsOpenMap.id).sum_elim (isOpenMap_inr.prod IsOpenMap.id) + ((continuous_inl.prodMap continuous_id).sum_elim + (continuous_inr.prodMap continuous_id)) <| + (isOpenMap_inl.prodMap IsOpenMap.id).sum_elim (isOpenMap_inr.prodMap IsOpenMap.id) /-- `X × (Y ⊕ Z)` is homeomorphic to `X × Y ⊕ X × Z`. -/ def prodSumDistrib : X × (Y ⊕ Z) ≃ₜ (X × Y) ⊕ (X × Z) := @@ -709,7 +710,7 @@ def sigmaProdDistrib : (Σ i, X i) × Y ≃ₜ Σ i, X i × Y := Homeomorph.symm <| homeomorphOfContinuousOpen (Equiv.sigmaProdDistrib X Y).symm (continuous_sigma fun _ => continuous_sigmaMk.fst'.prod_mk continuous_snd) - (isOpenMap_sigma.2 fun _ => isOpenMap_sigmaMk.prod IsOpenMap.id) + (isOpenMap_sigma.2 fun _ => isOpenMap_sigmaMk.prodMap IsOpenMap.id) end Distrib @@ -901,7 +902,10 @@ protected lemma quotientMap : QuotientMap f := (hf.homeomorph f).quotientMap protected lemma embedding : Embedding f := (hf.homeomorph f).embedding protected lemma openEmbedding : OpenEmbedding f := (hf.homeomorph f).openEmbedding protected lemma closedEmbedding : ClosedEmbedding f := (hf.homeomorph f).closedEmbedding -protected lemma denseEmbedding : DenseEmbedding f := (hf.homeomorph f).denseEmbedding +lemma isDenseEmbedding : IsDenseEmbedding f := (hf.homeomorph f).isDenseEmbedding + +@[deprecated (since := "2024-09-30")] +alias denseEmbedding := isDenseEmbedding end IsHomeomorph @@ -946,7 +950,7 @@ lemma IsHomeomorph.sumMap {g : Z → W} (hf : IsHomeomorph f) (hg : IsHomeomorph IsHomeomorph (Sum.map f g) := ⟨hf.1.sum_map hg.1, hf.2.sumMap hg.2, hf.3.sum_map hg.3⟩ lemma IsHomeomorph.prodMap {g : Z → W} (hf : IsHomeomorph f) (hg : IsHomeomorph g) : - IsHomeomorph (Prod.map f g) := ⟨hf.1.prod_map hg.1, hf.2.prod hg.2, hf.3.prodMap hg.3⟩ + IsHomeomorph (Prod.map f g) := ⟨hf.1.prodMap hg.1, hf.2.prodMap hg.2, hf.3.prodMap hg.3⟩ lemma IsHomeomorph.sigmaMap {ι κ : Type*} {X : ι → Type*} {Y : κ → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, TopologicalSpace (Y i)] {f : ι → κ} diff --git a/Mathlib/Topology/Homotopy/Basic.lean b/Mathlib/Topology/Homotopy/Basic.lean index caf0e3a6983a5..e736983bd8031 100644 --- a/Mathlib/Topology/Homotopy/Basic.lean +++ b/Mathlib/Topology/Homotopy/Basic.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Shing Tak Lam -/ import Mathlib.Topology.Order.ProjIcc -import Mathlib.Topology.ContinuousFunction.Ordered +import Mathlib.Topology.ContinuousMap.Ordered import Mathlib.Topology.CompactOpen import Mathlib.Topology.UnitInterval diff --git a/Mathlib/Topology/Homotopy/Contractible.lean b/Mathlib/Topology/Homotopy/Contractible.lean index 34bf5c1a00185..42461b28209d2 100644 --- a/Mathlib/Topology/Homotopy/Contractible.lean +++ b/Mathlib/Topology/Homotopy/Contractible.lean @@ -91,9 +91,9 @@ protected theorem Homeomorph.contractibleSpace_iff (e : X ≃ₜ Y) : namespace ContractibleSpace -instance [Unique Y] : ContractibleSpace Y := by - have : ContractibleSpace (Unit) := ⟨⟨HomotopyEquiv.refl Unit⟩⟩ - apply (Homeomorph.homeomorphOfUnique Y Unit).contractibleSpace +instance [Nonempty Y] [Subsingleton Y] : ContractibleSpace Y := + let ⟨_⟩ := nonempty_unique Y + ⟨⟨(Homeomorph.homeomorphOfUnique Y Unit).toHomotopyEquiv⟩⟩ variable (X Y) in theorem hequiv [ContractibleSpace X] [ContractibleSpace Y] : diff --git a/Mathlib/Topology/Homotopy/HomotopyGroup.lean b/Mathlib/Topology/Homotopy/HomotopyGroup.lean index 93fad3a1199db..daaa41db02500 100644 --- a/Mathlib/Topology/Homotopy/HomotopyGroup.lean +++ b/Mathlib/Topology/Homotopy/HomotopyGroup.lean @@ -185,7 +185,7 @@ theorem continuous_toLoop (i : N) : Continuous (@toLoop N X _ x _ i) := Path.continuous_uncurry_iff.1 <| Continuous.subtype_mk (ContinuousMap.continuous_eval.comp <| - Continuous.prod_map + Continuous.prodMap (ContinuousMap.continuous_curry.comp <| (ContinuousMap.continuous_comp_left _).comp continuous_subtype_val) continuous_id) diff --git a/Mathlib/Topology/Inseparable.lean b/Mathlib/Topology/Inseparable.lean index 392ac4f52c773..a179072f0d072 100644 --- a/Mathlib/Topology/Inseparable.lean +++ b/Mathlib/Topology/Inseparable.lean @@ -5,6 +5,7 @@ Authors: Andrew Yang, Yury Kudryashov -/ import Mathlib.Tactic.TFAE import Mathlib.Topology.ContinuousOn +import Mathlib.Topology.Maps.OpenQuotient /-! # Inseparable points in a topological space @@ -548,6 +549,9 @@ theorem preimage_image_mk_open (hs : IsOpen s) : mk ⁻¹' (mk '' s) = s := by theorem isOpenMap_mk : IsOpenMap (mk : X → SeparationQuotient X) := fun s hs => quotientMap_mk.isOpen_preimage.1 <| by rwa [preimage_image_mk_open hs] +theorem isOpenQuotientMap_mk : IsOpenQuotientMap (mk : X → SeparationQuotient X) := + ⟨surjective_mk, continuous_mk, isOpenMap_mk⟩ + theorem preimage_image_mk_closed (hs : IsClosed s) : mk ⁻¹' (mk '' s) = s := by refine Subset.antisymm ?_ (subset_preimage_image _ _) rintro x ⟨y, hys, hxy⟩ @@ -599,14 +603,8 @@ theorem map_mk_nhdsWithin_preimage (s : Set (SeparationQuotient X)) (x : X) : rw [nhdsWithin, ← comap_principal, Filter.push_pull, nhdsWithin, map_mk_nhds] /-- The map `(x, y) ↦ (mk x, mk y)` is a quotient map. -/ -theorem quotientMap_prodMap_mk : QuotientMap (Prod.map mk mk : X × Y → _) := by - have hsurj : Surjective (Prod.map mk mk : X × Y → _) := surjective_mk.prodMap surjective_mk - refine quotientMap_iff.2 ⟨hsurj, fun s ↦ ?_⟩ - refine ⟨fun hs ↦ hs.preimage (continuous_mk.prod_map continuous_mk), fun hs ↦ ?_⟩ - refine isOpen_iff_mem_nhds.2 <| hsurj.forall.2 fun (x, y) h ↦ ?_ - rw [Prod.map_mk, nhds_prod_eq, ← map_mk_nhds, ← map_mk_nhds, Filter.prod_map_map_eq', - ← nhds_prod_eq, Filter.mem_map] - exact hs.mem_nhds h +theorem quotientMap_prodMap_mk : QuotientMap (Prod.map mk mk : X × Y → _) := + (isOpenQuotientMap_mk.prodMap isOpenQuotientMap_mk).quotientMap /-- Lift a map `f : X → α` such that `Inseparable x y → f x = f y` to a map `SeparationQuotient X → α`. -/ diff --git a/Mathlib/Topology/Instances/Complex.lean b/Mathlib/Topology/Instances/Complex.lean index 1bd41163d0387..717f60129dd83 100644 --- a/Mathlib/Topology/Instances/Complex.lean +++ b/Mathlib/Topology/Instances/Complex.lean @@ -39,7 +39,7 @@ theorem Complex.subfield_eq_of_closed {K : Subfield ℂ} (hc : IsClosed (K : Set simp only [Function.comp_apply, ofReal_ratCast, SetLike.mem_coe, SubfieldClass.ratCast_mem] nth_rw 1 [range_comp] refine subset_trans ?_ (image_closure_subset_closure_image continuous_ofReal) - rw [DenseRange.closure_range Rat.denseEmbedding_coe_real.dense] + rw [DenseRange.closure_range Rat.isDenseEmbedding_coe_real.dense] simp only [image_univ] rfl @@ -52,13 +52,13 @@ theorem Complex.uniformContinuous_ringHom_eq_id_or_conj (K : Subfield ℂ) {ψ : letI : TopologicalRing K.topologicalClosure := Subring.instTopologicalRing K.topologicalClosure.toSubring set ι : K → K.topologicalClosure := ⇑(Subfield.inclusion K.le_topologicalClosure) - have ui : UniformInducing ι := + have ui : IsUniformInducing ι := ⟨by - erw [uniformity_subtype, uniformity_subtype, Filter.comap_comap] + rw [uniformity_subtype, uniformity_subtype, Filter.comap_comap] congr ⟩ - let di := ui.denseInducing (?_ : DenseRange ι) + let di := ui.isDenseInducing (?_ : DenseRange ι) · -- extψ : closure(K) →+* ℂ is the extension of ψ : K →+* ℂ - let extψ := DenseInducing.extendRingHom ui di.dense hc + let extψ := IsDenseInducing.extendRingHom ui di.dense hc haveI hψ := (uniformContinuous_uniformly_extend ui di.dense hc).continuous cases' Complex.subfield_eq_of_closed (Subfield.isClosed_topologicalClosure K) with h h · left @@ -76,7 +76,7 @@ theorem Complex.uniformContinuous_ringHom_eq_id_or_conj (K : Subfield ℂ) {ψ : -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644 erw [RingHom.comp_apply, RingHom.comp_apply, hr, RingEquiv.toRingHom_eq_coe] at this convert this using 1 - · exact (DenseInducing.extend_eq di hc.continuous _).symm + · exact (IsDenseInducing.extend_eq di hc.continuous _).symm · rw [← ofReal.coe_rangeRestrict, hr] rfl obtain ⟨r, hr⟩ := SetLike.coe_mem (j (ι x)) @@ -94,11 +94,11 @@ theorem Complex.uniformContinuous_ringHom_eq_id_or_conj (K : Subfield ℂ) {ψ : · left ext1 z convert RingHom.congr_fun h z using 1 - exact (DenseInducing.extend_eq di hc.continuous z).symm + exact (IsDenseInducing.extend_eq di hc.continuous z).symm · right ext1 z convert RingHom.congr_fun h z using 1 - exact (DenseInducing.extend_eq di hc.continuous z).symm + exact (IsDenseInducing.extend_eq di hc.continuous z).symm · let j : { x // x ∈ closure (id '' { x | (K : Set ℂ) x }) } → (K.topologicalClosure : Set ℂ) := fun x => ⟨x, by @@ -106,7 +106,7 @@ theorem Complex.uniformContinuous_ringHom_eq_id_or_conj (K : Subfield ℂ) {ψ : simp only [id, Set.image_id'] rfl ⟩ convert DenseRange.comp (Function.Surjective.denseRange _) - (DenseEmbedding.subtype denseEmbedding_id (K : Set ℂ)).dense (by continuity : Continuous j) + (IsDenseEmbedding.id.subtype (K : Set ℂ)).dense (by continuity : Continuous j) rintro ⟨y, hy⟩ use ⟨y, by diff --git a/Mathlib/Topology/Instances/ENNReal.lean b/Mathlib/Topology/Instances/ENNReal.lean index fd6a716306a63..5623966b95601 100644 --- a/Mathlib/Topology/Instances/ENNReal.lean +++ b/Mathlib/Topology/Instances/ENNReal.lean @@ -91,7 +91,7 @@ theorem continuousAt_coe_iff {α : Type*} [TopologicalSpace α] {x : ℝ≥0} {f theorem nhds_coe_coe {r p : ℝ≥0} : 𝓝 ((r : ℝ≥0∞), (p : ℝ≥0∞)) = (𝓝 (r, p)).map fun p : ℝ≥0 × ℝ≥0 => (↑p.1, ↑p.2) := - ((openEmbedding_coe.prod openEmbedding_coe).map_nhds_eq (r, p)).symm + ((openEmbedding_coe.prodMap openEmbedding_coe).map_nhds_eq (r, p)).symm theorem continuous_ofReal : Continuous ENNReal.ofReal := (continuous_coe_iff.2 continuous_id).comp continuous_real_toNNReal @@ -435,34 +435,28 @@ theorem le_of_forall_lt_one_mul_le {x y : ℝ≥0∞} (h : ∀ a < 1, a * x ≤ rw [one_mul] at this exact le_of_tendsto this (eventually_nhdsWithin_iff.2 <| Eventually.of_forall h) +@[deprecated mul_iInf' (since := "2024-09-12")] 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 - · 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]⟩ - · rw [not_and_or] at H - cases isEmpty_or_nonempty ι - · rw [iInf_of_empty, iInf_of_empty, mul_top] - exact mt h0 (not_nonempty_iff.2 ‹_›) - · exact (ENNReal.mul_left_mono.map_ciInf_of_continuousAt - (ENNReal.continuousAt_const_mul H)).symm + (h0 : a = 0 → Nonempty ι) : ⨅ i, a * f i = a * ⨅ i, f i := .symm <| mul_iInf' h h0 +@[deprecated mul_iInf (since := "2024-09-12")] 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 := - iInf_mul_left' h fun _ => ‹Nonempty ι› + .symm <| mul_iInf h +@[deprecated iInf_mul' (since := "2024-09-12")] 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 + (h0 : a = 0 → Nonempty ι) : ⨅ i, f i * a = (⨅ i, f i) * a := .symm <| iInf_mul' h h0 +@[deprecated iInf_mul (since := "2024-09-12")] 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 := - iInf_mul_right' h fun _ => ‹Nonempty ι› + (h : a = ∞ → ⨅ i, f i = 0 → ∃ i, f i = 0) : ⨅ i, f i * a = (⨅ i, f i) * a := .symm <| iInf_mul h +@[deprecated inv_iInf (since := "2024-09-12")] theorem inv_map_iInf {ι : Sort*} {x : ι → ℝ≥0∞} : (iInf x)⁻¹ = ⨆ i, (x i)⁻¹ := OrderIso.invENNReal.map_iInf x +@[deprecated inv_iSup (since := "2024-09-12")] theorem inv_map_iSup {ι : Sort*} {x : ι → ℝ≥0∞} : (iSup x)⁻¹ = ⨅ i, (x i)⁻¹ := OrderIso.invENNReal.map_iSup x @@ -504,115 +498,10 @@ protected theorem Tendsto.div_const {f : Filter α} {m : α → ℝ≥0∞} {a b protected theorem tendsto_inv_nat_nhds_zero : Tendsto (fun n : ℕ => (n : ℝ≥0∞)⁻¹) atTop (𝓝 0) := ENNReal.inv_top ▸ ENNReal.tendsto_inv_iff.2 tendsto_nat_nhds_top -theorem iSup_add {ι : Sort*} {s : ι → ℝ≥0∞} [Nonempty ι] : iSup s + a = ⨆ b, s b + a := - Monotone.map_ciSup_of_continuousAt (continuousAt_id.add continuousAt_const) <| - monotone_id.add monotone_const - -theorem biSup_add' {ι : Sort*} {p : ι → Prop} (h : ∃ i, p i) {f : ι → ℝ≥0∞} : - (⨆ (i) (_ : p i), f i) + a = ⨆ (i) (_ : p i), f i + a := by - haveI : Nonempty { i // p i } := nonempty_subtype.2 h - simp only [iSup_subtype', iSup_add] - -theorem add_biSup' {ι : Sort*} {p : ι → Prop} (h : ∃ i, p i) {f : ι → ℝ≥0∞} : - (a + ⨆ (i) (_ : p i), f i) = ⨆ (i) (_ : p i), a + f i := by - simp only [add_comm a, biSup_add' h] - -theorem biSup_add {ι} {s : Set ι} (hs : s.Nonempty) {f : ι → ℝ≥0∞} : - (⨆ i ∈ s, f i) + a = ⨆ i ∈ s, f i + a := - biSup_add' hs - -theorem add_biSup {ι} {s : Set ι} (hs : s.Nonempty) {f : ι → ℝ≥0∞} : - (a + ⨆ i ∈ s, f i) = ⨆ i ∈ s, a + f i := - add_biSup' hs - -theorem sSup_add {s : Set ℝ≥0∞} (hs : s.Nonempty) : sSup s + a = ⨆ b ∈ s, b + a := by - rw [sSup_eq_iSup, biSup_add hs] - -theorem add_iSup {ι : Sort*} {s : ι → ℝ≥0∞} [Nonempty ι] : a + iSup s = ⨆ b, a + s b := by - rw [add_comm, iSup_add]; simp [add_comm] - -theorem iSup_add_iSup_le {ι ι' : Sort*} [Nonempty ι] [Nonempty ι'] {f : ι → ℝ≥0∞} {g : ι' → ℝ≥0∞} - {a : ℝ≥0∞} (h : ∀ i j, f i + g j ≤ a) : iSup f + iSup g ≤ a := by - simp_rw [iSup_add, add_iSup]; exact iSup₂_le h - -theorem biSup_add_biSup_le' {ι ι'} {p : ι → Prop} {q : ι' → Prop} (hp : ∃ i, p i) (hq : ∃ j, q j) - {f : ι → ℝ≥0∞} {g : ι' → ℝ≥0∞} {a : ℝ≥0∞} (h : ∀ i, p i → ∀ j, q j → f i + g j ≤ a) : - ((⨆ (i) (_ : p i), f i) + ⨆ (j) (_ : q j), g j) ≤ a := by - simp_rw [biSup_add' hp, add_biSup' hq] - exact iSup₂_le fun i hi => iSup₂_le (h i hi) - -theorem biSup_add_biSup_le {ι ι'} {s : Set ι} {t : Set ι'} (hs : s.Nonempty) (ht : t.Nonempty) - {f : ι → ℝ≥0∞} {g : ι' → ℝ≥0∞} {a : ℝ≥0∞} (h : ∀ i ∈ s, ∀ j ∈ t, f i + g j ≤ a) : - ((⨆ i ∈ s, f i) + ⨆ j ∈ t, g j) ≤ a := - biSup_add_biSup_le' hs ht h - -theorem iSup_add_iSup {ι : Sort*} {f g : ι → ℝ≥0∞} (h : ∀ i j, ∃ k, f i + g j ≤ f k + g k) : - iSup f + iSup g = ⨆ a, f a + g a := by - cases isEmpty_or_nonempty ι - · simp only [iSup_of_empty, bot_eq_zero, zero_add] - · refine le_antisymm ?_ (iSup_le fun a => add_le_add (le_iSup _ _) (le_iSup _ _)) - refine iSup_add_iSup_le fun i j => ?_ - rcases h i j with ⟨k, hk⟩ - exact le_iSup_of_le k hk - -theorem iSup_add_iSup_of_monotone {ι : Type*} [Preorder ι] [IsDirected ι (· ≤ ·)] - {f g : ι → ℝ≥0∞} (hf : Monotone f) (hg : Monotone g) : iSup f + iSup g = ⨆ a, f a + g a := - iSup_add_iSup fun i j ↦ (exists_ge_ge i j).imp fun _k ⟨hi, hj⟩ ↦ by gcongr <;> apply_rules - -theorem finsetSum_iSup {α ι : Type*} {s : Finset α} {f : α → ι → ℝ≥0∞} - (hf : ∀ i j, ∃ k, ∀ a, f a i ≤ f a k ∧ f a j ≤ f a k) : - ∑ a ∈ s, ⨆ i, f a i = ⨆ i, ∑ a ∈ s, f a i := by - induction s using Finset.cons_induction with - | empty => simp - | cons a s ha ihs => - simp_rw [Finset.sum_cons, ihs] - refine iSup_add_iSup fun i j ↦ (hf i j).imp fun k hk ↦ ?_ - gcongr - exacts [(hk a).1, (hk _).2] - -theorem finsetSum_iSup_of_monotone {α} {ι} [Preorder ι] [IsDirected ι (· ≤ ·)] - {s : Finset α} {f : α → ι → ℝ≥0∞} (hf : ∀ a, Monotone (f a)) : - (∑ a ∈ s, iSup (f a)) = ⨆ n, ∑ a ∈ s, f a n := - finsetSum_iSup fun i j ↦ (exists_ge_ge i j).imp fun _k ⟨hi, hj⟩ a ↦ ⟨hf a hi, hf a hj⟩ - -@[deprecated (since := "2024-07-14")] -alias finset_sum_iSup_nat := finsetSum_iSup_of_monotone - -theorem mul_iSup {ι : Sort*} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} : a * iSup f = ⨆ i, a * f i := by - by_cases hf : ∀ i, f i = 0 - · obtain rfl : f = fun _ => 0 := funext hf - simp only [iSup_zero_eq_zero, mul_zero] - · refine (monotone_id.const_mul' _).map_iSup_of_continuousAt ?_ (mul_zero a) - refine ENNReal.Tendsto.const_mul tendsto_id (Or.inl ?_) - exact mt iSup_eq_zero.1 hf - -theorem mul_sSup {s : Set ℝ≥0∞} {a : ℝ≥0∞} : a * sSup s = ⨆ i ∈ s, a * i := by - simp only [sSup_eq_iSup, mul_iSup] - -theorem iSup_mul {ι : Sort*} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} : iSup f * a = ⨆ i, f i * a := by - rw [mul_comm, mul_iSup]; congr; funext; rw [mul_comm] - -theorem smul_iSup {ι : Sort*} {R} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (f : ι → ℝ≥0∞) - (c : R) : (c • ⨆ i, f i) = ⨆ i, c • f i := by - -- Porting note: replaced `iSup _` with `iSup f` - simp only [← smul_one_mul c (f _), ← smul_one_mul c (iSup f), ENNReal.mul_iSup] - -theorem smul_sSup {R} [SMul R ℝ≥0∞] [IsScalarTower R ℝ≥0∞ ℝ≥0∞] (s : Set ℝ≥0∞) (c : R) : - c • sSup s = ⨆ i ∈ s, c • i := by - -- Porting note: replaced `_` with `s` - simp_rw [← smul_one_mul c (sSup s), ENNReal.mul_sSup, smul_one_mul] - -theorem iSup_div {ι : Sort*} {f : ι → ℝ≥0∞} {a : ℝ≥0∞} : iSup f / a = ⨆ i, f i / a := - iSup_mul - protected theorem tendsto_coe_sub {b : ℝ≥0∞} : Tendsto (fun b : ℝ≥0∞ => ↑r - b) (𝓝 b) (𝓝 (↑r - b)) := continuous_nnreal_sub.tendsto _ -theorem sub_iSup {ι : Sort*} [Nonempty ι] {b : ι → ℝ≥0∞} (hr : a < ∞) : - (a - ⨆ i, b i) = ⨅ i, a - b i := - antitone_const_tsub.map_ciSup_of_continuousAt (continuous_sub_left hr.ne).continuousAt - theorem exists_countable_dense_no_zero_top : ∃ s : Set ℝ≥0∞, s.Countable ∧ Dense s ∧ 0 ∉ s ∧ ∞ ∉ s := by obtain ⟨s, s_count, s_dense, hs⟩ : @@ -620,19 +509,7 @@ theorem exists_countable_dense_no_zero_top : exists_countable_dense_no_bot_top ℝ≥0∞ exact ⟨s, s_count, s_dense, fun h => hs.1 0 (by simp) h, fun h => hs.2 ∞ (by simp) h⟩ -theorem exists_lt_add_of_lt_add {x y z : ℝ≥0∞} (h : x < y + z) (hy : y ≠ 0) (hz : z ≠ 0) : - ∃ y' z', y' < y ∧ z' < z ∧ x < y' + z' := by - have : NeZero y := ⟨hy⟩ - have : NeZero z := ⟨hz⟩ - have A : Tendsto (fun p : ℝ≥0∞ × ℝ≥0∞ => p.1 + p.2) (𝓝[<] y ×ˢ 𝓝[<] z) (𝓝 (y + z)) := by - apply Tendsto.mono_left _ (Filter.prod_mono nhdsWithin_le_nhds nhdsWithin_le_nhds) - rw [← nhds_prod_eq] - exact tendsto_add - rcases ((A.eventually (lt_mem_nhds h)).and - (Filter.prod_mem_prod self_mem_nhdsWithin self_mem_nhdsWithin)).exists with - ⟨⟨y', z'⟩, hx, hy', hz'⟩ - exact ⟨y', z', hy', hz', hx⟩ - +@[deprecated ofReal_iInf (since := "2024-09-12")] theorem ofReal_cinfi (f : α → ℝ) [Nonempty α] : ENNReal.ofReal (⨅ i, f i) = ⨅ i, ENNReal.ofReal (f i) := by by_cases hf : BddBelow (range f) @@ -1526,5 +1403,3 @@ lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} ( end LimsupLiminf end ENNReal -- namespace - -set_option linter.style.longFile 1700 diff --git a/Mathlib/Topology/Instances/EReal.lean b/Mathlib/Topology/Instances/EReal.lean index 5ad8821215f37..4d970aa153cb8 100644 --- a/Mathlib/Topology/Instances/EReal.lean +++ b/Mathlib/Topology/Instances/EReal.lean @@ -70,7 +70,7 @@ theorem nhds_coe {r : ℝ} : 𝓝 (r : EReal) = (𝓝 r).map (↑) := theorem nhds_coe_coe {r p : ℝ} : 𝓝 ((r : EReal), (p : EReal)) = (𝓝 (r, p)).map fun p : ℝ × ℝ => (↑p.1, ↑p.2) := - ((openEmbedding_coe.prod openEmbedding_coe).map_nhds_eq (r, p)).symm + ((openEmbedding_coe.prodMap openEmbedding_coe).map_nhds_eq (r, p)).symm theorem tendsto_toReal {a : EReal} (ha : a ≠ ⊤) (h'a : a ≠ ⊥) : Tendsto EReal.toReal (𝓝 a) (𝓝 a.toReal) := by @@ -145,6 +145,41 @@ theorem tendsto_nhds_bot_iff_real {α : Type*} {m : α → EReal} {f : Filter α Tendsto m f (𝓝 ⊥) ↔ ∀ x : ℝ, ∀ᶠ a in f, m a < x := nhds_bot_basis.tendsto_right_iff.trans <| by simp only [true_implies, mem_Iio] +lemma nhdsWithin_top : 𝓝[≠] (⊤ : EReal) = (atTop).map Real.toEReal := by + apply (nhdsWithin_hasBasis nhds_top_basis_Ici _).ext (atTop_basis.map Real.toEReal) + · simp only [EReal.image_coe_Ici, true_and] + intro x hx + by_cases hx_bot : x = ⊥ + · simp [hx_bot] + lift x to ℝ using ⟨hx.ne_top, hx_bot⟩ + refine ⟨x, fun x ⟨h1, h2⟩ ↦ ?_⟩ + simp [h1, h2.ne_top] + · simp only [EReal.image_coe_Ici, true_implies] + refine fun x ↦ ⟨x, ⟨EReal.coe_lt_top x, fun x ⟨(h1 : _ ≤ x), h2⟩ ↦ ?_⟩⟩ + simp [h1, Ne.lt_top' fun a ↦ h2 a.symm] + +lemma nhdsWithin_bot : 𝓝[≠] (⊥ : EReal) = (atBot).map Real.toEReal := by + apply (nhdsWithin_hasBasis nhds_bot_basis_Iic _).ext (atBot_basis.map Real.toEReal) + · simp only [EReal.image_coe_Iic, Set.subset_compl_singleton_iff, Set.mem_Ioc, lt_self_iff_false, + bot_le, and_true, not_false_eq_true, true_and] + intro x hx + by_cases hx_top : x = ⊤ + · simp [hx_top] + lift x to ℝ using ⟨hx_top, hx.ne_bot⟩ + refine ⟨x, fun x ⟨h1, h2⟩ ↦ ?_⟩ + simp [h2, h1.ne_bot] + · simp only [EReal.image_coe_Iic, true_implies] + refine fun x ↦ ⟨x, ⟨EReal.bot_lt_coe x, fun x ⟨(h1 : x ≤ _), h2⟩ ↦ ?_⟩⟩ + simp [h1, Ne.bot_lt' fun a ↦ h2 a.symm] + +lemma tendsto_toReal_atTop : Tendsto EReal.toReal (𝓝[≠] ⊤) atTop := by + rw [nhdsWithin_top, tendsto_map'_iff] + exact tendsto_id + +lemma tendsto_toReal_atBot : Tendsto EReal.toReal (𝓝[≠] ⊥) atBot := by + rw [nhdsWithin_bot, tendsto_map'_iff] + exact tendsto_id + /-! ### Infs and Sups -/ variable {α : Type*} {u v : α → EReal} @@ -323,7 +358,7 @@ private lemma continuousAt_mul_symm1 {a b : EReal} simp rw [this] apply ContinuousAt.comp (Continuous.continuousAt continuous_neg) - <| ContinuousAt.comp _ (ContinuousAt.prod_map (Continuous.continuousAt continuous_neg) + <| ContinuousAt.comp _ (ContinuousAt.prodMap (Continuous.continuousAt continuous_neg) (Continuous.continuousAt continuous_id)) simp [h] diff --git a/Mathlib/Topology/Instances/Int.lean b/Mathlib/Topology/Instances/Int.lean index 4e93d2e862ea6..5ee25d7b929f2 100644 --- a/Mathlib/Topology/Instances/Int.lean +++ b/Mathlib/Topology/Instances/Int.lean @@ -39,13 +39,16 @@ theorem pairwise_one_le_dist : Pairwise fun m n : ℤ => 1 ≤ dist m n := by intro m n hne rw [dist_eq]; norm_cast; rwa [← zero_add (1 : ℤ), Int.add_one_le_iff, abs_pos, sub_ne_zero] -theorem uniformEmbedding_coe_real : UniformEmbedding ((↑) : ℤ → ℝ) := - uniformEmbedding_bot_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist +theorem isUniformEmbedding_coe_real : IsUniformEmbedding ((↑) : ℤ → ℝ) := + isUniformEmbedding_bot_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coe_real := isUniformEmbedding_coe_real theorem closedEmbedding_coe_real : ClosedEmbedding ((↑) : ℤ → ℝ) := closedEmbedding_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist -instance : MetricSpace ℤ := Int.uniformEmbedding_coe_real.comapMetricSpace _ +instance : MetricSpace ℤ := Int.isUniformEmbedding_coe_real.comapMetricSpace _ theorem preimage_ball (x : ℤ) (r : ℝ) : (↑) ⁻¹' ball (x : ℝ) r = ball x r := rfl diff --git a/Mathlib/Topology/Instances/NNReal.lean b/Mathlib/Topology/Instances/NNReal.lean index d6ef63c1b5f66..6f0a140493505 100644 --- a/Mathlib/Topology/Instances/NNReal.lean +++ b/Mathlib/Topology/Instances/NNReal.lean @@ -6,6 +6,7 @@ Authors: Johan Commelin import Mathlib.Data.NNReal.Star import Mathlib.Topology.Algebra.InfiniteSum.Order import Mathlib.Topology.Algebra.InfiniteSum.Ring +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Topology.Instances.Real import Mathlib.Topology.MetricSpace.Isometry diff --git a/Mathlib/Topology/Instances/Nat.lean b/Mathlib/Topology/Instances/Nat.lean index 2e4857faf7c51..e90ce1cbe65b7 100644 --- a/Mathlib/Topology/Instances/Nat.lean +++ b/Mathlib/Topology/Instances/Nat.lean @@ -31,13 +31,16 @@ theorem dist_cast_real (x y : ℕ) : dist (x : ℝ) y = dist x y := rfl theorem pairwise_one_le_dist : Pairwise fun m n : ℕ => 1 ≤ dist m n := fun _ _ hne => Int.pairwise_one_le_dist <| mod_cast hne -theorem uniformEmbedding_coe_real : UniformEmbedding ((↑) : ℕ → ℝ) := - uniformEmbedding_bot_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist +theorem isUniformEmbedding_coe_real : IsUniformEmbedding ((↑) : ℕ → ℝ) := + isUniformEmbedding_bot_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coe_real := isUniformEmbedding_coe_real theorem closedEmbedding_coe_real : ClosedEmbedding ((↑) : ℕ → ℝ) := closedEmbedding_of_pairwise_le_dist zero_lt_one pairwise_one_le_dist -instance : MetricSpace ℕ := Nat.uniformEmbedding_coe_real.comapMetricSpace _ +instance : MetricSpace ℕ := Nat.isUniformEmbedding_coe_real.comapMetricSpace _ theorem preimage_ball (x : ℕ) (r : ℝ) : (↑) ⁻¹' ball (x : ℝ) r = ball x r := rfl diff --git a/Mathlib/Topology/Instances/PNat.lean b/Mathlib/Topology/Instances/PNat.lean index 3a05c74ac7076..dd79778f35d9b 100644 --- a/Mathlib/Topology/Instances/PNat.lean +++ b/Mathlib/Topology/Instances/PNat.lean @@ -24,7 +24,10 @@ theorem dist_eq (x y : ℕ+) : dist x y = |(↑x : ℝ) - ↑y| := rfl @[simp, norm_cast] theorem dist_coe (x y : ℕ+) : dist (↑x : ℕ) (↑y : ℕ) = dist x y := rfl -theorem uniformEmbedding_coe : UniformEmbedding ((↑) : ℕ+ → ℕ) := uniformEmbedding_subtype_val +theorem isUniformEmbedding_coe : IsUniformEmbedding ((↑) : ℕ+ → ℕ) := isUniformEmbedding_subtype_val + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coe := isUniformEmbedding_coe instance : DiscreteTopology ℕ+ := inferInstanceAs (DiscreteTopology { n : ℕ // 0 < n }) diff --git a/Mathlib/Topology/Instances/Rat.lean b/Mathlib/Topology/Instances/Rat.lean index 1fd5e8eaa6966..715361b5de0d9 100644 --- a/Mathlib/Topology/Instances/Rat.lean +++ b/Mathlib/Topology/Instances/Rat.lean @@ -30,14 +30,20 @@ theorem dist_cast (x y : ℚ) : dist (x : ℝ) y = dist x y := theorem uniformContinuous_coe_real : UniformContinuous ((↑) : ℚ → ℝ) := uniformContinuous_comap -theorem uniformEmbedding_coe_real : UniformEmbedding ((↑) : ℚ → ℝ) := - uniformEmbedding_comap Rat.cast_injective +theorem isUniformEmbedding_coe_real : IsUniformEmbedding ((↑) : ℚ → ℝ) := + isUniformEmbedding_comap Rat.cast_injective -theorem denseEmbedding_coe_real : DenseEmbedding ((↑) : ℚ → ℝ) := - uniformEmbedding_coe_real.denseEmbedding Rat.denseRange_cast +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coe_real := isUniformEmbedding_coe_real + +theorem isDenseEmbedding_coe_real : IsDenseEmbedding ((↑) : ℚ → ℝ) := + isUniformEmbedding_coe_real.isDenseEmbedding Rat.denseRange_cast + +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_coe_real := isDenseEmbedding_coe_real theorem embedding_coe_real : Embedding ((↑) : ℚ → ℝ) := - denseEmbedding_coe_real.to_embedding + isDenseEmbedding_coe_real.to_embedding theorem continuous_coe_real : Continuous ((↑) : ℚ → ℝ) := uniformContinuous_coe_real.continuous @@ -48,8 +54,11 @@ end Rat theorem Nat.dist_cast_rat (x y : ℕ) : dist (x : ℚ) y = dist x y := by rw [← Nat.dist_cast_real, ← Rat.dist_cast]; congr -theorem Nat.uniformEmbedding_coe_rat : UniformEmbedding ((↑) : ℕ → ℚ) := - uniformEmbedding_bot_of_pairwise_le_dist zero_lt_one <| by simpa using Nat.pairwise_one_le_dist +theorem Nat.isUniformEmbedding_coe_rat : IsUniformEmbedding ((↑) : ℕ → ℚ) := + isUniformEmbedding_bot_of_pairwise_le_dist zero_lt_one <| by simpa using Nat.pairwise_one_le_dist + +@[deprecated (since := "2024-10-01")] +alias Nat.uniformEmbedding_coe_rat := Nat.isUniformEmbedding_coe_rat theorem Nat.closedEmbedding_coe_rat : ClosedEmbedding ((↑) : ℕ → ℚ) := closedEmbedding_of_pairwise_le_dist zero_lt_one <| by simpa using Nat.pairwise_one_le_dist @@ -58,8 +67,11 @@ theorem Nat.closedEmbedding_coe_rat : ClosedEmbedding ((↑) : ℕ → ℚ) := theorem Int.dist_cast_rat (x y : ℤ) : dist (x : ℚ) y = dist x y := by rw [← Int.dist_cast_real, ← Rat.dist_cast]; congr -theorem Int.uniformEmbedding_coe_rat : UniformEmbedding ((↑) : ℤ → ℚ) := - uniformEmbedding_bot_of_pairwise_le_dist zero_lt_one <| by simpa using Int.pairwise_one_le_dist +theorem Int.isUniformEmbedding_coe_rat : IsUniformEmbedding ((↑) : ℤ → ℚ) := + isUniformEmbedding_bot_of_pairwise_le_dist zero_lt_one <| by simpa using Int.pairwise_one_le_dist + +@[deprecated (since := "2024-10-01")] +alias Int.uniformEmbedding_coe_rat := Int.isUniformEmbedding_coe_rat theorem Int.closedEmbedding_coe_rat : ClosedEmbedding ((↑) : ℤ → ℚ) := closedEmbedding_of_pairwise_le_dist zero_lt_one <| by simpa using Int.pairwise_one_le_dist @@ -69,10 +81,10 @@ namespace Rat instance : NoncompactSpace ℚ := Int.closedEmbedding_coe_rat.noncompactSpace theorem uniformContinuous_add : UniformContinuous fun p : ℚ × ℚ => p.1 + p.2 := - Rat.uniformEmbedding_coe_real.toUniformInducing.uniformContinuous_iff.2 <| by + Rat.isUniformEmbedding_coe_real.isUniformInducing.uniformContinuous_iff.2 <| by simp only [Function.comp_def, Rat.cast_add] exact Real.uniformContinuous_add.comp - (Rat.uniformContinuous_coe_real.prod_map Rat.uniformContinuous_coe_real) + (Rat.uniformContinuous_coe_real.prodMap Rat.uniformContinuous_coe_real) theorem uniformContinuous_neg : UniformContinuous (@Neg.neg ℚ _) := Metric.uniformContinuous_iff.2 fun ε ε0 => @@ -94,7 +106,7 @@ instance : TopologicalRing ℚ := inferInstance nonrec theorem totallyBounded_Icc (a b : ℚ) : TotallyBounded (Icc a b) := by simpa only [preimage_cast_Icc] - using totallyBounded_preimage Rat.uniformEmbedding_coe_real.toUniformInducing + using totallyBounded_preimage Rat.isUniformEmbedding_coe_real.isUniformInducing (totallyBounded_Icc (a : ℝ) b) end Rat diff --git a/Mathlib/Topology/Instances/RatLemmas.lean b/Mathlib/Topology/Instances/RatLemmas.lean index b94351980b416..1f633201490d0 100644 --- a/Mathlib/Topology/Instances/RatLemmas.lean +++ b/Mathlib/Topology/Instances/RatLemmas.lean @@ -36,10 +36,10 @@ local notation "ℚ∞" => OnePoint ℚ namespace Rat -variable {p q : ℚ} {s t : Set ℚ} +variable {p : ℚ} {s : Set ℚ} theorem interior_compact_eq_empty (hs : IsCompact s) : interior s = ∅ := - denseEmbedding_coe_real.toDenseInducing.interior_compact_eq_empty dense_irrational hs + isDenseEmbedding_coe_real.toIsDenseInducing.interior_compact_eq_empty dense_irrational hs theorem dense_compl_compact (hs : IsCompact s) : Dense sᶜ := interior_eq_empty_iff_dense_compl.1 (interior_compact_eq_empty hs) @@ -72,7 +72,7 @@ theorem not_secondCountableTopology_opc : ¬SecondCountableTopology ℚ∞ := by exact not_firstCountableTopology_opc inferInstance instance : TotallyDisconnectedSpace ℚ := by - clear p q s t + clear p s refine ⟨fun s hsu hs x hx y hy => ?_⟩; clear hsu by_contra! H : x ≠ y wlog hlt : x < y diff --git a/Mathlib/Topology/Instances/Real.lean b/Mathlib/Topology/Instances/Real.lean index 5b895c2cdeb63..16325c2f3e0ab 100644 --- a/Mathlib/Topology/Instances/Real.lean +++ b/Mathlib/Topology/Instances/Real.lean @@ -3,16 +3,17 @@ 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.Data.Real.Star -import Mathlib.Algebra.Algebra.Basic +import Mathlib.Algebra.Module.Rat +import Mathlib.Algebra.Module.Submodule.Lattice import Mathlib.Algebra.Periodic +import Mathlib.Data.Real.Star import Mathlib.Topology.Algebra.Order.Archimedean import Mathlib.Topology.Algebra.Order.Field -import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.Algebra.Star +import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.Instances.Int -import Mathlib.Topology.Order.Bornology import Mathlib.Topology.Metrizable.Basic +import Mathlib.Topology.Order.Bornology /-! # Topological properties of ℝ diff --git a/Mathlib/Topology/Instances/RealVectorSpace.lean b/Mathlib/Topology/Instances/RealVectorSpace.lean index a7eaa801c1d9f..5d4327d792021 100644 --- a/Mathlib/Topology/Instances/RealVectorSpace.lean +++ b/Mathlib/Topology/Instances/RealVectorSpace.lean @@ -23,7 +23,7 @@ theorem map_real_smul {G} [FunLike G E F] [AddMonoidHomClass G E F] (f : G) (hf (c : ℝ) (x : E) : f (c • x) = c • f x := suffices (fun c : ℝ => f (c • x)) = fun c : ℝ => c • f x from congr_fun this c - Rat.denseEmbedding_coe_real.dense.equalizer (hf.comp <| continuous_id.smul continuous_const) + Rat.isDenseEmbedding_coe_real.dense.equalizer (hf.comp <| continuous_id.smul continuous_const) (continuous_id.smul continuous_const) (funext fun r => map_ratCast_smul f ℝ ℝ r x) namespace AddMonoidHom diff --git a/Mathlib/Topology/KrullDimension.lean b/Mathlib/Topology/KrullDimension.lean index c76906356f367..b5eee2e982ae4 100644 --- a/Mathlib/Topology/KrullDimension.lean +++ b/Mathlib/Topology/KrullDimension.lean @@ -12,16 +12,52 @@ import Mathlib.Topology.Sets.Closeds The Krull dimension of a topological space is the order theoretic Krull dimension applied to the collection of all its subsets that are closed and irreducible. Unfolding this definition, it is the length of longest series of closed irreducible subsets ordered by inclusion. - -TODO: The Krull dimension of `Spec(R)` equals the Krull dimension of `R`, for `R` a commutative - ring. -/ -open TopologicalSpace +open TopologicalSpace Order /-- The Krull dimension of a topological space is the supremum of lengths of chains of closed irreducible sets. -/ noncomputable def topologicalKrullDim (T : Type*) [TopologicalSpace T] : WithBot ℕ∞ := - Order.krullDim (IrreducibleCloseds T) + krullDim (IrreducibleCloseds T) + +variable {X Y : Type*} [TopologicalSpace X] [TopologicalSpace Y] + +/-- +Map induced on irreducible closed subsets by a closed continuous map `f`. +This is just a wrapper around the image of `f` together with proofs that it +preserves irreducibility (by continuity) and closedness (since `f` is closed). +-/ +def IrreducibleCloseds.map {f : X → Y} (hf1 : Continuous f) (hf2 : IsClosedMap f) + (c : IrreducibleCloseds X) : + IrreducibleCloseds Y where + carrier := f '' c + is_irreducible' := c.is_irreducible'.image f hf1.continuousOn + is_closed' := hf2 c c.is_closed' + +/-- +Taking images under a closed embedding is strictly monotone on the preorder of irreducible closeds. +-/ +lemma IrreducibleCloseds.map_strictMono {f : X → Y} (hf : ClosedEmbedding f) : + StrictMono (IrreducibleCloseds.map hf.continuous hf.isClosedMap) := + fun ⦃_ _⦄ UltV ↦ hf.inj.image_strictMono UltV + +/-- +If `f : X → Y` is a closed embedding, then the Krull dimension of `X` is less than or equal +to the Krull dimension of `Y`. +-/ +theorem ClosedEmbedding.topologicalKrullDim_le (f : X → Y) (hf : ClosedEmbedding f) : + topologicalKrullDim X ≤ topologicalKrullDim Y := + krullDim_le_of_strictMono _ (IrreducibleCloseds.map_strictMono hf) + +/-- The topological Krull dimension is invariant under homeomorphisms -/ +theorem IsHomeomorph.topologicalKrullDim_eq (f : X → Y) (h : IsHomeomorph f) : + topologicalKrullDim X = topologicalKrullDim Y := + have fwd : topologicalKrullDim X ≤ topologicalKrullDim Y := + ClosedEmbedding.topologicalKrullDim_le f h.closedEmbedding + have bwd : topologicalKrullDim Y ≤ topologicalKrullDim X := + ClosedEmbedding.topologicalKrullDim_le (h.homeomorph f).symm + (h.homeomorph f).symm.closedEmbedding + le_antisymm fwd bwd diff --git a/Mathlib/Topology/LocalAtTarget.lean b/Mathlib/Topology/LocalAtTarget.lean index 5970438a142e8..184b90a9c30e4 100644 --- a/Mathlib/Topology/LocalAtTarget.lean +++ b/Mathlib/Topology/LocalAtTarget.lean @@ -23,7 +23,7 @@ open TopologicalSpace Set Filter open Topology Filter variable {α β : Type*} [TopologicalSpace α] [TopologicalSpace β] {f : α → β} -variable {s : Set β} {ι : Type*} {U : ι → Opens β} +variable {ι : Type*} {U : ι → Opens β} theorem Set.restrictPreimage_inducing (s : Set β) (h : Inducing f) : Inducing (s.restrictPreimage f) := by @@ -150,8 +150,8 @@ theorem inducing_iff_inducing_of_iSup_eq_top (h : Continuous f) : (show f x ∈ iSup U by rw [hU] trivial) - erw [← OpenEmbedding.map_nhds_eq (h.1 _ (U i).2).openEmbedding_subtype_val ⟨x, hi⟩] - rw [(H i) ⟨x, hi⟩, Filter.subtype_coe_map_comap, Function.comp_apply, Subtype.coe_mk, + rw [← OpenEmbedding.map_nhds_eq (h.1 _ (U i).2).openEmbedding_subtype_val ⟨x, hi⟩, + (H i) ⟨x, hi⟩, Filter.subtype_coe_map_comap, Function.comp_apply, Subtype.coe_mk, inf_eq_left, Filter.le_principal_iff] exact Filter.preimage_mem_comap ((U i).2.mem_nhds hi) diff --git a/Mathlib/Topology/LocallyFinite.lean b/Mathlib/Topology/LocallyFinite.lean index f8fbbee18a97d..fef472c111a08 100644 --- a/Mathlib/Topology/LocallyFinite.lean +++ b/Mathlib/Topology/LocallyFinite.lean @@ -197,7 +197,7 @@ theorem LocallyFinite.sum_elim {g : ι' → Set X} (hf : LocallyFinite f) (hg : theorem locallyFinite_option {f : Option ι → Set X} : LocallyFinite f ↔ LocallyFinite (f ∘ some) := by - rw [← (Equiv.optionEquivSumPUnit.{_, 0} ι).symm.locallyFinite_comp_iff, locallyFinite_sum] + rw [← (Equiv.optionEquivSumPUnit.{0, _} ι).symm.locallyFinite_comp_iff, locallyFinite_sum] simp only [locallyFinite_of_finite, and_true] rfl diff --git a/Mathlib/Topology/Maps/OpenQuotient.lean b/Mathlib/Topology/Maps/OpenQuotient.lean new file mode 100644 index 0000000000000..88433f7a190fd --- /dev/null +++ b/Mathlib/Topology/Maps/OpenQuotient.lean @@ -0,0 +1,64 @@ +/- +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.Topology.Maps.Basic + +/-! +# Open quotient maps + +An open quotient map is an open map `f : X → Y` which is both an open map and a quotient map. +Equivalently, it is a surjective continuous open map. +We use the latter characterization as a definition. + +Many important quotient maps are open quotient maps, including + +- the quotient map from a topological space to its quotient by the action of a group; +- the quotient map from a topological group to its quotient by a normal subgroup; +- the quotient map from a topological spaace to its separation quotient. + +Contrary to general quotient maps, +the category of open quotient maps is closed under `Prod.map`. +-/ + +open Function Set Filter +open scoped Topology + +variable {X Y Z : Type*} [TopologicalSpace X] [TopologicalSpace Y] [TopologicalSpace Z] {f : X → Y} + +namespace IsOpenQuotientMap + +protected theorem id : IsOpenQuotientMap (id : X → X) := ⟨surjective_id, continuous_id, .id⟩ + +/-- An open quotient map is a quotient map. -/ +theorem quotientMap (h : IsOpenQuotientMap f) : QuotientMap f := + h.isOpenMap.to_quotientMap h.continuous h.surjective + +theorem iff_isOpenMap_quotientMap : IsOpenQuotientMap f ↔ IsOpenMap f ∧ QuotientMap f := + ⟨fun h ↦ ⟨h.isOpenMap, h.quotientMap⟩, fun ⟨ho, hq⟩ ↦ ⟨hq.surjective, hq.continuous, ho⟩⟩ + +theorem of_isOpenMap_quotientMap (ho : IsOpenMap f) (hq : QuotientMap f) : + IsOpenQuotientMap f := + iff_isOpenMap_quotientMap.2 ⟨ho, hq⟩ + +theorem comp {g : Y → Z} (hg : IsOpenQuotientMap g) (hf : IsOpenQuotientMap f) : + IsOpenQuotientMap (g ∘ f) := + ⟨.comp hg.1 hf.1, .comp hg.2 hf.2, .comp hg.3 hf.3⟩ + +theorem map_nhds_eq (h : IsOpenQuotientMap f) (x : X) : map f (𝓝 x) = 𝓝 (f x) := + le_antisymm h.continuous.continuousAt <| h.isOpenMap.nhds_le _ + +theorem continuous_comp_iff (h : IsOpenQuotientMap f) {g : Y → Z} : + Continuous (g ∘ f) ↔ Continuous g := + h.quotientMap.continuous_iff.symm + +theorem continuousAt_comp_iff (h : IsOpenQuotientMap f) {g : Y → Z} {x : X} : + ContinuousAt (g ∘ f) x ↔ ContinuousAt g (f x) := by + simp only [ContinuousAt, ← h.map_nhds_eq, tendsto_map'_iff, comp_def] + +theorem dense_preimage_iff (h : IsOpenQuotientMap f) {s : Set Y} : Dense (f ⁻¹' s) ↔ Dense s := + ⟨fun hs ↦ h.surjective.denseRange.dense_of_mapsTo h.continuous hs (mapsTo_preimage _ _), + fun hs ↦ hs.preimage h.isOpenMap⟩ + +end IsOpenQuotientMap diff --git a/Mathlib/Topology/Maps/Proper/Basic.lean b/Mathlib/Topology/Maps/Proper/Basic.lean index 4132dd33262f6..00bd0a3bd8677 100644 --- a/Mathlib/Topology/Maps/Proper/Basic.lean +++ b/Mathlib/Topology/Maps/Proper/Basic.lean @@ -174,12 +174,12 @@ lemma isProperMap_of_comp_of_t2 [T2Space Y] (hf : Continuous f) (hg : Continuous exact ⟨x, hx⟩ /-- A binary product of proper maps is proper. -/ -lemma IsProperMap.prod_map {g : Z → W} (hf : IsProperMap f) (hg : IsProperMap g) : +lemma IsProperMap.prodMap {g : Z → W} (hf : IsProperMap f) (hg : IsProperMap g) : IsProperMap (Prod.map f g) := by simp_rw [isProperMap_iff_ultrafilter] at hf hg ⊢ constructor -- Continuity is clear. - · exact hf.1.prod_map hg.1 + · exact hf.1.prodMap hg.1 -- Let `𝒰 : Ultrafilter (X × Z)`, and assume that `f × g` tends to some `(y, w) : Y × W` -- along `𝒰`. · intro 𝒰 ⟨y, w⟩ hyw @@ -197,6 +197,8 @@ lemma IsProperMap.prod_map {g : Z → W} (hf : IsProperMap f) (hg : IsProperMap rw [nhds_prod_eq, le_prod] exact ⟨hx, hz⟩ +@[deprecated (since := "2024-10-06")] alias IsProperMap.prod_map := IsProperMap.prodMap + /-- Any product of proper maps is proper. -/ lemma IsProperMap.pi_map {X Y : ι → Type*} [∀ i, TopologicalSpace (X i)] [∀ i, TopologicalSpace (Y i)] {f : (i : ι) → X i → Y i} (h : ∀ i, IsProperMap (f i)) : @@ -416,7 +418,7 @@ easier to use because it allows `Z` to live in any universe. -/ theorem IsProperMap.universally_closed (Z) [TopologicalSpace Z] (h : IsProperMap f) : IsClosedMap (Prod.map f id : X × Z → Y × Z) := -- `f × id` is proper as a product of proper maps, hence closed. - (h.prod_map isProperMap_id).isClosedMap + (h.prodMap isProperMap_id).isClosedMap /-- A map `f : X → Y` is proper if and only if it is continuous and the map `(Prod.map f id : X × Filter X → Y × Filter X)` is closed. This is stronger than diff --git a/Mathlib/Topology/MetricSpace/Algebra.lean b/Mathlib/Topology/MetricSpace/Algebra.lean index c2d744b24f070..e185b9abdc3ba 100644 --- a/Mathlib/Topology/MetricSpace/Algebra.lean +++ b/Mathlib/Topology/MetricSpace/Algebra.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Heather Macbeth -/ import Mathlib.Topology.Algebra.MulAction +import Mathlib.Topology.Algebra.UniformMulAction import Mathlib.Topology.MetricSpace.Lipschitz +import Mathlib.Topology.Algebra.SeparationQuotient /-! # Compatibility of algebraic operations with metric space structures @@ -143,6 +145,11 @@ instance (priority := 100) BoundedSMul.continuousSMul : ContinuousSMul α β whe gcongr _ < ε := hδε +instance (priority := 100) BoundedSMul.toUniformContinuousConstSMul : + UniformContinuousConstSMul α β := + ⟨fun c => ((lipschitzWith_iff_dist_le_mul (K := nndist c 0)).2 fun _ _ => + dist_smul_pair c _ _).uniformContinuous⟩ + -- this instance could be deduced from `NormedSpace.boundedSMul`, but we prove it separately -- here so that it is available earlier in the hierarchy instance Real.boundedSMul : BoundedSMul ℝ ℝ where @@ -207,5 +214,11 @@ instance Prod.instBoundedSMul {α β γ : Type*} [PseudoMetricSpace α] [PseudoM max_le ((dist_pair_smul _ _ _).trans <| mul_le_mul_of_nonneg_left (le_max_left _ _) dist_nonneg) ((dist_pair_smul _ _ _).trans <| mul_le_mul_of_nonneg_left (le_max_right _ _) dist_nonneg) +instance {α β : Type*} + [PseudoMetricSpace α] [PseudoMetricSpace β] [Zero α] [Zero β] [SMul α β] [BoundedSMul α β] : + BoundedSMul α (SeparationQuotient β) where + dist_smul_pair' _ := Quotient.ind₂ <| dist_smul_pair _ + dist_pair_smul' _ _ := Quotient.ind <| dist_pair_smul _ _ + -- We don't have the `SMul α γ → SMul β δ → SMul (α × β) (γ × δ)` instance, but if we did, then -- `BoundedSMul α γ → BoundedSMul β δ → BoundedSMul (α × β) (γ × δ)` would hold diff --git a/Mathlib/Topology/MetricSpace/Antilipschitz.lean b/Mathlib/Topology/MetricSpace/Antilipschitz.lean index 88e3996a46af3..67c88ebcb3216 100644 --- a/Mathlib/Topology/MetricSpace/Antilipschitz.lean +++ b/Mathlib/Topology/MetricSpace/Antilipschitz.lean @@ -143,18 +143,22 @@ theorem comap_uniformity_le (hf : AntilipschitzWith K f) : (𝓤 β).comap (Prod rw [mul_comm] exact ENNReal.mul_lt_of_lt_div hx -protected theorem uniformInducing (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : - UniformInducing f := +theorem isUniformInducing (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : + IsUniformInducing f := ⟨le_antisymm hf.comap_uniformity_le hfc.le_comap⟩ -protected theorem uniformEmbedding {α : Type*} {β : Type*} [EMetricSpace α] [PseudoEMetricSpace β] - {K : ℝ≥0} {f : α → β} (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : - UniformEmbedding f := - ⟨hf.uniformInducing hfc, hf.injective⟩ +@[deprecated (since := "2024-10-05")] +alias uniformInducing := isUniformInducing + +lemma isUniformEmbedding {α β : Type*} [EMetricSpace α] [PseudoEMetricSpace β] {K : ℝ≥0} {f : α → β} + (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : IsUniformEmbedding f := + ⟨hf.isUniformInducing hfc, hf.injective⟩ + +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding theorem isComplete_range [CompleteSpace α] (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : IsComplete (range f) := - (hf.uniformInducing hfc).isComplete_range + (hf.isUniformInducing hfc).isComplete_range theorem isClosed_range {α β : Type*} [PseudoEMetricSpace α] [EMetricSpace β] [CompleteSpace α] {f : α → β} {K : ℝ≥0} (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : @@ -164,7 +168,7 @@ theorem isClosed_range {α β : Type*} [PseudoEMetricSpace α] [EMetricSpace β] theorem closedEmbedding {α : Type*} {β : Type*} [EMetricSpace α] [EMetricSpace β] {K : ℝ≥0} {f : α → β} [CompleteSpace α] (hf : AntilipschitzWith K f) (hfc : UniformContinuous f) : ClosedEmbedding f := - { (hf.uniformEmbedding hfc).embedding with isClosed_range := hf.isClosed_range hfc } + { (hf.isUniformEmbedding hfc).embedding with isClosed_range := hf.isClosed_range hfc } theorem subtype_coe (s : Set α) : AntilipschitzWith 1 ((↑) : s → α) := AntilipschitzWith.id.restrict s diff --git a/Mathlib/Topology/MetricSpace/Basic.lean b/Mathlib/Topology/MetricSpace/Basic.lean index f3b2468b6e50b..185ec4912deba 100644 --- a/Mathlib/Topology/MetricSpace/Basic.lean +++ b/Mathlib/Topology/MetricSpace/Basic.lean @@ -32,11 +32,14 @@ instance (priority := 100) _root_.MetricSpace.instT0Space : T0Space γ where /-- A map between metric spaces is a uniform embedding if and only if the distance between `f x` and `f y` is controlled in terms of the distance between `x` and `y` and conversely. -/ -theorem uniformEmbedding_iff' [MetricSpace β] {f : γ → β} : - UniformEmbedding f ↔ +theorem isUniformEmbedding_iff' [MetricSpace β] {f : γ → β} : + IsUniformEmbedding f ↔ (∀ ε > 0, ∃ δ > 0, ∀ {a b : γ}, dist a b < δ → dist (f a) (f b) < ε) ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : γ}, dist (f a) (f b) < ε → dist a b < δ := by - rw [uniformEmbedding_iff_uniformInducing, uniformInducing_iff, uniformContinuous_iff] + rw [isUniformEmbedding_iff_isUniformInducing, isUniformInducing_iff, uniformContinuous_iff] + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_iff' := isUniformEmbedding_iff' /-- If a `PseudoMetricSpace` is a T₀ space, then it is a `MetricSpace`. -/ abbrev _root_.MetricSpace.ofT0PseudoMetricSpace (α : Type*) [PseudoMetricSpace α] [T0Space α] : @@ -60,10 +63,13 @@ theorem closedEmbedding_of_pairwise_le_dist {α : Type*} [TopologicalSpace α] [ /-- If `f : β → α` sends any two distinct points to points at distance at least `ε > 0`, then `f` is a uniform embedding with respect to the discrete uniformity on `β`. -/ -theorem uniformEmbedding_bot_of_pairwise_le_dist {β : Type*} {ε : ℝ} (hε : 0 < ε) {f : β → α} +theorem isUniformEmbedding_bot_of_pairwise_le_dist {β : Type*} {ε : ℝ} (hε : 0 < ε) {f : β → α} (hf : Pairwise fun x y => ε ≤ dist (f x) (f y)) : - @UniformEmbedding _ _ ⊥ (by infer_instance) f := - uniformEmbedding_of_spaced_out (dist_mem_uniformity hε) <| by simpa using hf + @IsUniformEmbedding _ _ ⊥ (by infer_instance) f := + isUniformEmbedding_of_spaced_out (dist_mem_uniformity hε) <| by simpa using hf + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_bot_of_pairwise_le_dist := isUniformEmbedding_bot_of_pairwise_le_dist end Metric @@ -94,10 +100,13 @@ abbrev MetricSpace.induced {γ β} (f : γ → β) (hf : Function.Injective f) ( /-- Pull back a metric space structure by a uniform embedding. This is a version of `MetricSpace.induced` useful in case if the domain already has a `UniformSpace` structure. -/ -abbrev UniformEmbedding.comapMetricSpace {α β} [UniformSpace α] [m : MetricSpace β] (f : α → β) - (h : UniformEmbedding f) : MetricSpace α := +abbrev IsUniformEmbedding.comapMetricSpace {α β} [UniformSpace α] [m : MetricSpace β] (f : α → β) + (h : IsUniformEmbedding f) : MetricSpace α := .replaceUniformity (.induced f h.inj m) h.comap_uniformity.symm +@[deprecated (since := "2024-10-03")] +alias UniformEmbedding.comapMetricSpace := IsUniformEmbedding.comapMetricSpace + /-- Pull back a metric space structure by an embedding. This is a version of `MetricSpace.induced` useful in case if the domain already has a `TopologicalSpace` structure. -/ abbrev Embedding.comapMetricSpace {α β} [TopologicalSpace α] [m : MetricSpace β] (f : α → β) diff --git a/Mathlib/Topology/MetricSpace/Bilipschitz.lean b/Mathlib/Topology/MetricSpace/Bilipschitz.lean index 432fad174bbe3..0e69f60fc5dbc 100644 --- a/Mathlib/Topology/MetricSpace/Bilipschitz.lean +++ b/Mathlib/Topology/MetricSpace/Bilipschitz.lean @@ -55,7 +55,7 @@ instance : UniformSpace α := (inferInstance : UniformSpace β).comap f in order to avoid abuse of the definitional equality `α := β`. -/ lemma uniformity_eq_of_bilipschitz (hf₁ : AntilipschitzWith K₁ f) (hf₂ : LipschitzWith K₂ f) : 𝓤[(inferInstance : UniformSpace β).comap f] = 𝓤 α := - hf₁.uniformInducing hf₂.uniformContinuous |>.comap_uniformity + hf₁.isUniformInducing hf₂.uniformContinuous |>.comap_uniformity end Uniformity diff --git a/Mathlib/Topology/MetricSpace/Closeds.lean b/Mathlib/Topology/MetricSpace/Closeds.lean index 67b9d4cbf3244..2dd3375fbcd8e 100644 --- a/Mathlib/Topology/MetricSpace/Closeds.lean +++ b/Mathlib/Topology/MetricSpace/Closeds.lean @@ -232,9 +232,12 @@ instance NonemptyCompacts.emetricSpace : EMetricSpace (NonemptyCompacts α) wher rwa [s.isCompact.isClosed.closure_eq, t.isCompact.isClosed.closure_eq] at this /-- `NonemptyCompacts.toCloseds` is a uniform embedding (as it is an isometry) -/ -theorem NonemptyCompacts.ToCloseds.uniformEmbedding : - UniformEmbedding (@NonemptyCompacts.toCloseds α _ _) := - Isometry.uniformEmbedding fun _ _ => rfl +theorem NonemptyCompacts.ToCloseds.isUniformEmbedding : + IsUniformEmbedding (@NonemptyCompacts.toCloseds α _ _) := + Isometry.isUniformEmbedding fun _ _ => rfl + +@[deprecated (since := "2024-10-01")] +alias NonemptyCompacts.ToCloseds.uniformEmbedding := NonemptyCompacts.ToCloseds.isUniformEmbedding /-- The range of `NonemptyCompacts.toCloseds` is closed in a complete space -/ theorem NonemptyCompacts.isClosed_in_closeds [CompleteSpace α] : @@ -278,14 +281,14 @@ theorem NonemptyCompacts.isClosed_in_closeds [CompleteSpace α] : from the same statement for closed subsets -/ instance NonemptyCompacts.completeSpace [CompleteSpace α] : CompleteSpace (NonemptyCompacts α) := (completeSpace_iff_isComplete_range - NonemptyCompacts.ToCloseds.uniformEmbedding.toUniformInducing).2 <| + NonemptyCompacts.ToCloseds.isUniformEmbedding.isUniformInducing).2 <| NonemptyCompacts.isClosed_in_closeds.isComplete /-- In a compact space, the type of nonempty compact subsets is compact. This follows from the same statement for closed subsets -/ instance NonemptyCompacts.compactSpace [CompactSpace α] : CompactSpace (NonemptyCompacts α) := ⟨by - rw [NonemptyCompacts.ToCloseds.uniformEmbedding.embedding.isCompact_iff, image_univ] + rw [NonemptyCompacts.ToCloseds.isUniformEmbedding.embedding.isCompact_iff, image_univ] exact NonemptyCompacts.isClosed_in_closeds.isCompact⟩ /-- In a second countable space, the type of nonempty compact subsets is second countable -/ diff --git a/Mathlib/Topology/MetricSpace/Completion.lean b/Mathlib/Topology/MetricSpace/Completion.lean index 1ffdfa1fba1b7..97c5f07d31c6e 100644 --- a/Mathlib/Topology/MetricSpace/Completion.lean +++ b/Mathlib/Topology/MetricSpace/Completion.lean @@ -6,6 +6,8 @@ Authors: Sébastien Gouëzel import Mathlib.Topology.UniformSpace.Completion import Mathlib.Topology.MetricSpace.Isometry import Mathlib.Topology.MetricSpace.Lipschitz +import Mathlib.Topology.MetricSpace.Algebra +import Mathlib.Topology.Algebra.GroupCompletion import Mathlib.Topology.Instances.Real /-! @@ -168,6 +170,27 @@ theorem coe_isometry : Isometry ((↑) : α → Completion α) := protected theorem edist_eq (x y : α) : edist (x : Completion α) y = edist x y := coe_isometry x y +instance {M} [Zero M] [Zero α] [SMul M α] [PseudoMetricSpace M] [BoundedSMul M α] : + BoundedSMul M (Completion α) where + dist_smul_pair' c x₁ x₂ := by + induction x₁, x₂ using induction_on₂ with + | hp => + exact isClosed_le + ((continuous_fst.const_smul _).dist (continuous_snd.const_smul _)) + (continuous_const.mul (continuous_fst.dist continuous_snd)) + | ih x₁ x₂ => + rw [← coe_smul, ← coe_smul, Completion.dist_eq, Completion.dist_eq] + exact dist_smul_pair c x₁ x₂ + dist_pair_smul' c₁ c₂ x := by + induction x using induction_on with + | hp => + exact isClosed_le + ((continuous_const_smul _).dist (continuous_const_smul _)) + (continuous_const.mul (continuous_id.dist continuous_const)) + | ih x => + rw [← coe_smul, ← coe_smul, Completion.dist_eq, ← coe_zero, Completion.dist_eq] + exact dist_pair_smul c₁ c₂ x + end UniformSpace.Completion open UniformSpace Completion NNReal diff --git a/Mathlib/Topology/MetricSpace/Dilation.lean b/Mathlib/Topology/MetricSpace/Dilation.lean index c68a245846375..a2b542947d55f 100644 --- a/Mathlib/Topology/MetricSpace/Dilation.lean +++ b/Mathlib/Topology/MetricSpace/Dilation.lean @@ -66,7 +66,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*) [PseudoEMetricSpace α] [PseudoEMetricSpace β] +class DilationClass (F : Type*) (α β : outParam Type*) [PseudoEMetricSpace α] [PseudoEMetricSpace β] [FunLike F α β] : Prop where edist_eq' : ∀ f : F, ∃ r : ℝ≥0, r ≠ 0 ∧ ∀ x y : α, edist (f x) (f y) = r * edist x y @@ -370,12 +370,15 @@ theorem cancel_left {g : β →ᵈ γ} {f₁ f₂ : α →ᵈ β} (hg : Injectiv ⟨fun h => Dilation.ext fun x => hg <| by rw [← comp_apply, h, comp_apply], fun h => h ▸ rfl⟩ /-- A dilation from a metric space is a uniform inducing map -/ -protected theorem uniformInducing : UniformInducing (f : α → β) := - (antilipschitz f).uniformInducing (lipschitz f).uniformContinuous +theorem isUniformInducing : IsUniformInducing (f : α → β) := + (antilipschitz f).isUniformInducing (lipschitz f).uniformContinuous + +@[deprecated (since := "2024-10-05")] +alias uniformInducing := isUniformInducing theorem tendsto_nhds_iff {ι : Type*} {g : ι → α} {a : Filter ι} {b : α} : Filter.Tendsto g a (𝓝 b) ↔ Filter.Tendsto ((f : α → β) ∘ g) a (𝓝 (f b)) := - (Dilation.uniformInducing f).inducing.tendsto_nhds_iff + (Dilation.isUniformInducing f).inducing.tendsto_nhds_iff /-- A dilation is continuous. -/ theorem toContinuous : Continuous (f : α → β) := @@ -406,11 +409,11 @@ theorem mapsTo_emetric_closedBall (x : α) (r' : ℝ≥0∞) : theorem comp_continuousOn_iff {γ} [TopologicalSpace γ] {g : γ → α} {s : Set γ} : ContinuousOn ((f : α → β) ∘ g) s ↔ ContinuousOn g s := - (Dilation.uniformInducing f).inducing.continuousOn_iff.symm + (Dilation.isUniformInducing f).inducing.continuousOn_iff.symm theorem comp_continuous_iff {γ} [TopologicalSpace γ] {g : γ → α} : Continuous ((f : α → β) ∘ g) ↔ Continuous g := - (Dilation.uniformInducing f).inducing.continuous_iff.symm + (Dilation.isUniformInducing f).inducing.continuous_iff.symm end PseudoEmetricDilation @@ -420,14 +423,16 @@ variable [EMetricSpace α] variable [FunLike F α β] /-- A dilation from a metric space is a uniform embedding -/ -protected theorem uniformEmbedding [PseudoEMetricSpace β] [DilationClass F α β] (f : F) : - UniformEmbedding f := - (antilipschitz f).uniformEmbedding (lipschitz f).uniformContinuous +lemma isUniformEmbedding [PseudoEMetricSpace β] [DilationClass F α β] (f : F) : + IsUniformEmbedding f := + (antilipschitz f).isUniformEmbedding (lipschitz f).uniformContinuous + +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding /-- A dilation from a metric space is an embedding -/ protected theorem embedding [PseudoEMetricSpace β] [DilationClass F α β] (f : F) : Embedding (f : α → β) := - (Dilation.uniformEmbedding f).embedding + (Dilation.isUniformEmbedding f).embedding /-- A dilation from a complete emetric space is a closed embedding -/ protected theorem closedEmbedding [CompleteSpace α] [EMetricSpace β] [DilationClass F α β] (f : F) : diff --git a/Mathlib/Topology/MetricSpace/Gluing.lean b/Mathlib/Topology/MetricSpace/Gluing.lean index 53a7579e013fa..e3f3f1233ca43 100644 --- a/Mathlib/Topology/MetricSpace/Gluing.lean +++ b/Mathlib/Topology/MetricSpace/Gluing.lean @@ -243,8 +243,7 @@ private theorem Sum.mem_uniformity (s : Set ((X ⊕ Y) × (X ⊕ Y))) : · cases not_le_of_lt (lt_of_lt_of_le h (min_le_right _ _)) Sum.one_le_dist_inr_inl · exact hY (lt_of_lt_of_le h (le_trans (min_le_left _ _) (min_le_right _ _))) · rintro ⟨ε, ε0, H⟩ - constructor <;> rw [Filter.mem_sets, Filter.mem_map, mem_uniformity_dist] <;> - exact ⟨ε, ε0, fun h => H _ _ h⟩ + constructor <;> rw [Filter.mem_map, mem_uniformity_dist] <;> exact ⟨ε, ε0, fun h => H _ _ h⟩ /-- The distance on the disjoint union indeed defines a metric space. All the distance properties follow from our choice of the distance. The harder work is to show that the uniform structure @@ -432,7 +431,7 @@ protected theorem completeSpace [∀ i, CompleteSpace (E i)] : CompleteSpace (Σ set U := { p : (Σk, E k) × Σk, E k | dist p.1 p.2 < 1 } have hc : ∀ i, IsComplete (s i) := fun i => by simp only [s, ← range_sigmaMk] - exact (isometry_mk i).uniformInducing.isComplete_range + exact (isometry_mk i).isUniformInducing.isComplete_range have hd : ∀ (i j), ∀ x ∈ s i, ∀ y ∈ s j, (x, y) ∈ U → i = j := fun i j x hx y hy hxy => (Eq.symm hx).trans ((fst_eq_of_dist_lt_one _ _ hxy).trans hy) refine completeSpace_of_isComplete_univ ?_ diff --git a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean index f343b3d1c3901..9a6979a644bb1 100644 --- a/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean +++ b/Mathlib/Topology/MetricSpace/GromovHausdorffRealized.lean @@ -5,7 +5,7 @@ Authors: Sébastien Gouëzel -/ import Mathlib.Topology.MetricSpace.Gluing import Mathlib.Topology.MetricSpace.HausdorffDistance -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded /-! # The Gromov-Hausdorff distance is realized diff --git a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean index 1018155f553a7..46a5798a92a07 100644 --- a/Mathlib/Topology/MetricSpace/HausdorffDimension.lean +++ b/Mathlib/Topology/MetricSpace/HausdorffDimension.lean @@ -84,7 +84,7 @@ Hausdorff measure, Hausdorff dimension, dimension open scoped MeasureTheory ENNReal NNReal Topology -open MeasureTheory MeasureTheory.Measure Set TopologicalSpace FiniteDimensional Filter +open MeasureTheory MeasureTheory.Measure Set TopologicalSpace Module Filter variable {ι X Y : Type*} [EMetricSpace X] [EMetricSpace Y] @@ -441,7 +441,7 @@ theorem dimH_univ_pi_fin (n : ℕ) : dimH (univ : Set (Fin n → ℝ)) = n := by theorem dimH_of_mem_nhds {x : E} {s : Set E} (h : s ∈ 𝓝 x) : dimH s = finrank ℝ E := by have e : E ≃L[ℝ] Fin (finrank ℝ E) → ℝ := - ContinuousLinearEquiv.ofFinrankEq (FiniteDimensional.finrank_fin_fun ℝ).symm + ContinuousLinearEquiv.ofFinrankEq (Module.finrank_fin_fun ℝ).symm rw [← e.dimH_image] refine le_antisymm ?_ ?_ · exact (dimH_mono (subset_univ _)).trans_eq (dimH_univ_pi_fin _) @@ -459,7 +459,7 @@ theorem dimH_univ_eq_finrank : dimH (univ : Set E) = finrank ℝ E := dimH_of_mem_nhds (@univ_mem _ (𝓝 0)) theorem dimH_univ : dimH (univ : Set ℝ) = 1 := by - rw [dimH_univ_eq_finrank ℝ, FiniteDimensional.finrank_self, Nat.cast_one] + rw [dimH_univ_eq_finrank ℝ, Module.finrank_self, Nat.cast_one] variable {E} diff --git a/Mathlib/Topology/MetricSpace/HolderNorm.lean b/Mathlib/Topology/MetricSpace/HolderNorm.lean new file mode 100644 index 0000000000000..2081edf7d838d --- /dev/null +++ b/Mathlib/Topology/MetricSpace/HolderNorm.lean @@ -0,0 +1,265 @@ +/- +Copyright (c) 2024 Kexing Ying. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Kexing Ying +-/ +import Mathlib.Topology.MetricSpace.Holder + +/-! +# Hölder norm + +This file defines the Hölder (semi-)norm for Hölder functions alongside some basic properties. +The `r`-Hölder norm of a function `f : X → Y` between two metric spaces is the least non-negative +real number `C` for which `f` is `r`-Hölder continuous with constant `C`, i.e. it is the least `C` +for which `WithHolder C r f` is true. + +## Main definitions + +* `eHolderNorm r f`: `r`-Hölder (semi-)norm in `ℝ≥0∞` of a function `f`. +* `nnHolderNorm r f`: `r`-Hölder (semi-)norm in `ℝ≥0` of a function `f`. +* `MemHolder r f`: Predicate for a function `f` being `r`-Hölder continuous. + +## Main results + +* `eHolderNorm_eq_zero`: the Hölder norm of a function is zero if and only if it is constant. +* `MemHolder.holderWith`: The Hölder norm of a Hölder function `f` is a Hölder constant of `f`. + +## Tags + +Hölder norm, Hoelder norm, Holder norm + +-/ + +variable {X Y Z : Type*} + +open Filter Set + +open NNReal ENNReal Topology + +section PseudoEMetricSpace + +variable [PseudoEMetricSpace X] [PseudoEMetricSpace Y] {r : ℝ≥0} {f : X → Y} + +/-- The `r`-Hölder (semi-)norm in `ℝ≥0∞` of a function `f` is the least non-negative real +number `C` for which `f` is `r`-Hölder continuous with constant `C`. This is `∞` if no such +non-negative real exists. -/ +noncomputable +def eHolderNorm (r : ℝ≥0) (f : X → Y) : ℝ≥0∞ := ⨅ (C) (_ : HolderWith C r f), C + +/-- The `r`-Hölder (semi)norm in `ℝ≥0`. -/ +noncomputable +def nnHolderNorm (r : ℝ≥0) (f : X → Y) : ℝ≥0 := (eHolderNorm r f).toNNReal + +/-- A function `f` is `MemHolder r f` if it is Hölder continuous. Namely, `f` has a finite +`r`-Hölder constant. This is equivalent to `f` having finite Hölder norm. +c.f. `memHolder_iff`. -/ +def MemHolder (r : ℝ≥0) (f : X → Y) : Prop := ∃ C, HolderWith C r f + +lemma HolderWith.memHolder {C : ℝ≥0} (hf : HolderWith C r f) : MemHolder r f := ⟨C, hf⟩ + +@[simp] lemma eHolderNorm_lt_top : eHolderNorm r f < ∞ ↔ MemHolder r f := by + refine ⟨fun h => ?_, + fun hf => let ⟨C, hC⟩ := hf; iInf_lt_top.2 ⟨C, iInf_lt_top.2 ⟨hC, coe_lt_top⟩⟩⟩ + simp_rw [eHolderNorm, iInf_lt_top] at h + exact let ⟨C, hC, _⟩ := h; ⟨C, hC⟩ + +lemma eHolderNorm_ne_top : eHolderNorm r f ≠ ∞ ↔ MemHolder r f := by + rw [← eHolderNorm_lt_top, lt_top_iff_ne_top] + +@[simp] lemma eHolderNorm_eq_top : eHolderNorm r f = ∞ ↔ ¬ MemHolder r f := by + rw [← eHolderNorm_ne_top, not_not] + +protected alias ⟨_, MemHolder.eHolderNorm_lt_top⟩ := eHolderNorm_lt_top +protected alias ⟨_, MemHolder.eHolderNorm_ne_top⟩ := eHolderNorm_ne_top + +lemma coe_nnHolderNorm_le_eHolderNorm {r : ℝ≥0} {f : X → Y} : + (nnHolderNorm r f : ℝ≥0∞) ≤ eHolderNorm r f := + coe_toNNReal_le_self + +variable (X) in +@[simp] +lemma eHolderNorm_const (r : ℝ≥0) (c : Y) : eHolderNorm r (Function.const X c) = 0 := by + rw [eHolderNorm, ← ENNReal.bot_eq_zero, iInf₂_eq_bot] + exact fun C' hC' => ⟨0, .const, hC'⟩ + +variable (X) in +@[simp] +lemma eHolderNorm_zero [Zero Y] (r : ℝ≥0) : eHolderNorm r (0 : X → Y) = 0 := + eHolderNorm_const X r 0 + +variable (X) in +@[simp] +lemma nnHolderNorm_const (r : ℝ≥0) (c : Y) : nnHolderNorm r (Function.const X c) = 0 := by + refine le_antisymm (ENNReal.coe_le_coe.1 <| + le_trans coe_nnHolderNorm_le_eHolderNorm ?_) (zero_le _) + rw [eHolderNorm_const] + rfl + +variable (X) in +@[simp] +lemma nnHolderNorm_zero [Zero Y] (r : ℝ≥0) : nnHolderNorm r (0 : X → Y) = 0 := + nnHolderNorm_const X r 0 + +attribute [simp] eHolderNorm_const eHolderNorm_zero + +lemma eHolderNorm_of_isEmpty [hX : IsEmpty X] : + eHolderNorm r f = 0 := by + rw [eHolderNorm, ← ENNReal.bot_eq_zero, iInf₂_eq_bot] + exact fun ε hε => ⟨0, .of_isEmpty, hε⟩ + +lemma HolderWith.eHolderNorm_le {C : ℝ≥0} (hf : HolderWith C r f) : + eHolderNorm r f ≤ C := + iInf₂_le C hf + +/-- See also `memHolder_const` for the version with the spelling `fun _ ↦ c`. -/ +@[simp] +lemma memHolder_const {c : Y} : MemHolder r (Function.const X c) := + (HolderWith.const (C := 0)).memHolder + +/-- Version of `memHolder_const` with the spelling `fun _ ↦ c` for the constant function. -/ +@[simp] +lemma memHolder_const' {c : Y} : MemHolder r (fun _ ↦ c : X → Y) := + memHolder_const + +@[simp] +lemma memHolder_zero [Zero Y] : MemHolder r (0 : X → Y) := + memHolder_const + +end PseudoEMetricSpace + +section MetricSpace + +variable [MetricSpace X] [EMetricSpace Y] + +lemma eHolderNorm_eq_zero {r : ℝ≥0} {f : X → Y} : + eHolderNorm r f = 0 ↔ ∀ x₁ x₂, f x₁ = f x₂ := by + constructor + · refine fun h x₁ x₂ => ?_ + by_cases hx : x₁ = x₂ + · rw [hx] + · rw [eHolderNorm, ← ENNReal.bot_eq_zero, iInf₂_eq_bot] at h + rw [← edist_eq_zero, ← le_zero_iff] + refine le_of_forall_lt' fun b hb => ?_ + obtain ⟨C, hC, hC'⟩ := h (b / edist x₁ x₂ ^ (r : ℝ)) + (ENNReal.div_pos hb.ne.symm (ENNReal.rpow_lt_top_of_nonneg zero_le_coe + (edist_lt_top x₁ x₂).ne).ne) + exact lt_of_le_of_lt (hC x₁ x₂) <| ENNReal.mul_lt_of_lt_div hC' + · intro h + cases' isEmpty_or_nonempty X with hX hX + · haveI := hX + exact eHolderNorm_of_isEmpty + · rw [← eHolderNorm_const X r (f hX.some)] + congr + simp [funext_iff, h _ hX.some] + +lemma MemHolder.holderWith {r : ℝ≥0} {f : X → Y} (hf : MemHolder r f) : + HolderWith (nnHolderNorm r f) r f := by + intros x₁ x₂ + by_cases hx : x₁ = x₂ + · simp only [hx, edist_self, zero_le] + rw [nnHolderNorm, eHolderNorm, coe_toNNReal] + swap; exact hf.eHolderNorm_lt_top.ne + have h₁ : edist x₁ x₂ ^ (r : ℝ) ≠ 0 := + (Ne.symm <| ne_of_lt <| ENNReal.rpow_pos (edist_pos.2 hx) (edist_lt_top x₁ x₂).ne) + have h₂ : edist x₁ x₂ ^ (r : ℝ) ≠ ∞ := by + simp [(edist_lt_top x₁ x₂).ne] + rw [← ENNReal.div_le_iff h₁ h₂] + refine le_iInf₂ fun C hC => ?_ + rw [ENNReal.div_le_iff h₁ h₂] + exact hC x₁ x₂ + +lemma memHolder_iff_holderWith {r : ℝ≥0} {f : X → Y} : + MemHolder r f ↔ HolderWith (nnHolderNorm r f) r f := + ⟨MemHolder.holderWith, HolderWith.memHolder⟩ + +lemma MemHolder.coe_nnHolderNorm_eq_eHolderNorm + {r : ℝ≥0} {f : X → Y} (hf : MemHolder r f) : + (nnHolderNorm r f : ℝ≥0∞) = eHolderNorm r f := by + rw [nnHolderNorm, coe_toNNReal] + exact ne_of_lt <| lt_of_le_of_lt hf.holderWith.eHolderNorm_le <| coe_lt_top + +lemma HolderWith.nnholderNorm_le {C r : ℝ≥0} {f : X → Y} (hf : HolderWith C r f) : + nnHolderNorm r f ≤ C := by + rw [← ENNReal.coe_le_coe, hf.memHolder.coe_nnHolderNorm_eq_eHolderNorm] + exact hf.eHolderNorm_le + +lemma MemHolder.comp {r s : ℝ≥0} {Z : Type*} [MetricSpace Z] {f : Z → X} {g : X → Y} + (hf : MemHolder r f) (hg : MemHolder s g) : MemHolder (s * r) (g ∘ f) := + (hg.holderWith.comp hf.holderWith).memHolder + +lemma MemHolder.nnHolderNorm_eq_zero {r : ℝ≥0} {f : X → Y} (hf : MemHolder r f) : + nnHolderNorm r f = 0 ↔ ∀ x₁ x₂, f x₁ = f x₂ := by + rw [← ENNReal.coe_eq_zero, hf.coe_nnHolderNorm_eq_eHolderNorm, eHolderNorm_eq_zero] + +end MetricSpace + +section SeminormedAddCommGroup + +variable [MetricSpace X] [NormedAddCommGroup Y] +variable {C r : ℝ≥0} {f g : X → Y} + +lemma MemHolder.add (hf : MemHolder r f) (hg : MemHolder r g) : MemHolder r (f + g) := + (hf.holderWith.add hg.holderWith).memHolder + +lemma MemHolder.smul {𝕜} [NormedDivisionRing 𝕜] [Module 𝕜 Y] [BoundedSMul 𝕜 Y] + {c : 𝕜} (hf : MemHolder r f) : MemHolder r (c • f) := + (hf.holderWith.smul c).memHolder + +lemma MemHolder.nsmul [Module ℝ Y] [BoundedSMul ℝ Y] (n : ℕ) (hf : MemHolder r f) : + MemHolder r (n • f) := by + simp [← Nat.cast_smul_eq_nsmul (R := ℝ), hf.smul] + +lemma MemHolder.nnHolderNorm_add_le (hf : MemHolder r f) (hg : MemHolder r g) : + nnHolderNorm r (f + g) ≤ nnHolderNorm r f + nnHolderNorm r g := + (hf.add hg).holderWith.nnholderNorm_le.trans <| + coe_le_coe.2 (hf.holderWith.add hg.holderWith).nnholderNorm_le + +lemma eHolderNorm_add_le : + eHolderNorm r (f + g) ≤ eHolderNorm r f + eHolderNorm r g := by + by_cases hfg : MemHolder r f ∧ MemHolder r g + · obtain ⟨hf, hg⟩ := hfg + rw [← hf.coe_nnHolderNorm_eq_eHolderNorm, ← hg.coe_nnHolderNorm_eq_eHolderNorm, + ← (hf.add hg).coe_nnHolderNorm_eq_eHolderNorm, ← coe_add, ENNReal.coe_le_coe] + exact hf.nnHolderNorm_add_le hg + · rw [Classical.not_and_iff_or_not_not, ← eHolderNorm_eq_top, ← eHolderNorm_eq_top] at hfg + obtain (h | h) := hfg + all_goals simp [h] + +lemma eHolderNorm_smul {α} [NormedDivisionRing α] [Module α Y] [BoundedSMul α Y] (c : α) : + eHolderNorm r (c • f) = ‖c‖₊ * eHolderNorm r f := by + by_cases hc : ‖c‖₊ = 0 + · rw [nnnorm_eq_zero] at hc + simp [hc] + by_cases hf : MemHolder r f + · refine le_antisymm ((hf.holderWith.smul c).eHolderNorm_le.trans ?_) <| mul_le_of_le_div' ?_ + · rw [coe_mul, hf.coe_nnHolderNorm_eq_eHolderNorm, mul_comm] + · rw [← (hf.holderWith.smul c).memHolder.coe_nnHolderNorm_eq_eHolderNorm, ← coe_div hc] + refine HolderWith.eHolderNorm_le fun x₁ x₂ => ?_ + rw [coe_div hc, ← ENNReal.mul_div_right_comm, + ENNReal.le_div_iff_mul_le (Or.inl <| coe_ne_zero.2 hc) <| Or.inl coe_ne_top, + mul_comm, ← smul_eq_mul, ← ENNReal.smul_def, ← edist_smul₀, ← Pi.smul_apply, + ← Pi.smul_apply] + exact hf.smul.holderWith x₁ x₂ + · rw [← eHolderNorm_eq_top] at hf + rw [hf, mul_top <| coe_ne_zero.2 hc, eHolderNorm_eq_top] + rw [nnnorm_eq_zero] at hc + intro h + have := h.smul (c := c⁻¹) + rw [inv_smul_smul₀ hc] at this + exact this.eHolderNorm_lt_top.ne hf + +lemma MemHolder.nnHolderNorm_smul {α} [NormedDivisionRing α] [Module α Y] [BoundedSMul α Y] + (hf : MemHolder r f) (c : α) : + nnHolderNorm r (c • f) = ‖c‖₊ * nnHolderNorm r f := by + rw [← ENNReal.coe_inj, coe_mul, hf.coe_nnHolderNorm_eq_eHolderNorm, + hf.smul.coe_nnHolderNorm_eq_eHolderNorm, eHolderNorm_smul] + +lemma eHolderNorm_nsmul [Module ℝ Y] [BoundedSMul ℝ Y] (n : ℕ) : + eHolderNorm r (n • f) = n • eHolderNorm r f := by + simp [← Nat.cast_smul_eq_nsmul (R := ℝ), eHolderNorm_smul] + +lemma MemHolder.nnHolderNorm_nsmul [Module ℝ Y] [BoundedSMul ℝ Y] (n : ℕ) (hf : MemHolder r f) : + nnHolderNorm r (n • f) = n • nnHolderNorm r f := by + simp [← Nat.cast_smul_eq_nsmul (R := ℝ), hf.nnHolderNorm_smul] + +end SeminormedAddCommGroup diff --git a/Mathlib/Topology/MetricSpace/Infsep.lean b/Mathlib/Topology/MetricSpace/Infsep.lean index 027a2e3139f9c..e451f9e7817b3 100644 --- a/Mathlib/Topology/MetricSpace/Infsep.lean +++ b/Mathlib/Topology/MetricSpace/Infsep.lean @@ -171,7 +171,7 @@ end EDist section PseudoEMetricSpace -variable [PseudoEMetricSpace α] {x y z : α} {s t : Set α} +variable [PseudoEMetricSpace α] {x y z : α} {s : Set α} theorem einfsep_pair (hxy : x ≠ y) : ({x, y} : Set α).einfsep = edist x y := by nth_rw 1 [← min_self (edist x y)] @@ -238,7 +238,7 @@ end PseudoMetricSpace section EMetricSpace -variable [EMetricSpace α] {x y z : α} {s t : Set α} {C : ℝ≥0∞} {sC : Set ℝ≥0∞} +variable [EMetricSpace α] {s : Set α} theorem einfsep_pos_of_finite [Finite s] : 0 < s.einfsep := by cases nonempty_fintype s @@ -312,7 +312,7 @@ end EDist section PseudoEMetricSpace -variable [PseudoEMetricSpace α] {x y : α} {s : Set α} +variable [PseudoEMetricSpace α] {x y : α} theorem infsep_pair_eq_toReal : ({x, y} : Set α).infsep = (edist x y).toReal := by by_cases hxy : x = y diff --git a/Mathlib/Topology/MetricSpace/IsometricSMul.lean b/Mathlib/Topology/MetricSpace/IsometricSMul.lean index 1d8b4a236200b..8bbc25f34f0ab 100644 --- a/Mathlib/Topology/MetricSpace/IsometricSMul.lean +++ b/Mathlib/Topology/MetricSpace/IsometricSMul.lean @@ -405,19 +405,19 @@ instance ULift.isometricSMul' : IsometricSMul M (ULift X) := @[to_additive] instance {ι} {X : ι → Type*} [Fintype ι] [∀ i, SMul M (X i)] [∀ i, PseudoEMetricSpace (X i)] [∀ i, IsometricSMul M (X i)] : IsometricSMul M (∀ i, X i) := - ⟨fun c => isometry_dcomp (fun _ => (c • ·)) fun i => isometry_smul (X i) c⟩ + ⟨fun c => .piMap (fun _ => (c • ·)) fun i => isometry_smul (X i) c⟩ @[to_additive] instance Pi.isometricSMul' {ι} {M X : ι → Type*} [Fintype ι] [∀ i, SMul (M i) (X i)] [∀ i, PseudoEMetricSpace (X i)] [∀ i, IsometricSMul (M i) (X i)] : IsometricSMul (∀ i, M i) (∀ i, X i) := - ⟨fun c => isometry_dcomp (fun i => (c i • ·)) fun _ => isometry_smul _ _⟩ + ⟨fun c => .piMap (fun i => (c i • ·)) fun _ => isometry_smul _ _⟩ @[to_additive] instance Pi.isometricSMul'' {ι} {M : ι → Type*} [Fintype ι] [∀ i, Mul (M i)] [∀ i, PseudoEMetricSpace (M i)] [∀ i, IsometricSMul (M i)ᵐᵒᵖ (M i)] : IsometricSMul (∀ i, M i)ᵐᵒᵖ (∀ i, M i) := - ⟨fun c => isometry_dcomp (fun i (x : M i) => x * c.unop i) fun _ => isometry_mul_right _⟩ + ⟨fun c => .piMap (fun i (x : M i) => x * c.unop i) fun _ => isometry_mul_right _⟩ instance Additive.isometricVAdd : IsometricVAdd (Additive M) X := ⟨fun c => isometry_smul X (toMul c)⟩ diff --git a/Mathlib/Topology/MetricSpace/Isometry.lean b/Mathlib/Topology/MetricSpace/Isometry.lean index fc48af3ac67e9..0640a68f619aa 100644 --- a/Mathlib/Topology/MetricSpace/Isometry.lean +++ b/Mathlib/Topology/MetricSpace/Isometry.lean @@ -84,10 +84,12 @@ theorem prod_map {δ} [PseudoEMetricSpace δ] {f : α → β} {g : γ → δ} (h (hg : Isometry g) : Isometry (Prod.map f g) := fun x y => by simp only [Prod.edist_eq, Prod.map_fst, hf.edist_eq, Prod.map_snd, hg.edist_eq] -theorem _root_.isometry_dcomp {ι} [Fintype ι] {α β : ι → Type*} [∀ i, PseudoEMetricSpace (α i)] +protected theorem piMap {ι} [Fintype ι] {α β : ι → Type*} [∀ i, PseudoEMetricSpace (α i)] [∀ i, PseudoEMetricSpace (β i)] (f : ∀ i, α i → β i) (hf : ∀ i, Isometry (f i)) : - Isometry (fun g : (i : ι) → α i => fun i => f i (g i)) := fun x y => by - simp only [edist_pi_def, (hf _).edist_eq] + Isometry (Pi.map f) := fun x y => by + simp only [edist_pi_def, (hf _).edist_eq, Pi.map_apply] + +@[deprecated (since := "2024-10-06")] alias _root_.isometry_dcomp := Isometry.piMap /-- The composition of isometries is an isometry. -/ theorem comp {g : β → γ} {f : α → β} (hg : Isometry g) (hf : Isometry f) : Isometry (g ∘ f) := @@ -98,12 +100,15 @@ protected theorem uniformContinuous (hf : Isometry f) : UniformContinuous f := hf.lipschitz.uniformContinuous /-- An isometry from a metric space is a uniform inducing map -/ -protected theorem uniformInducing (hf : Isometry f) : UniformInducing f := - hf.antilipschitz.uniformInducing hf.uniformContinuous +theorem isUniformInducing (hf : Isometry f) : IsUniformInducing f := + hf.antilipschitz.isUniformInducing hf.uniformContinuous + +@[deprecated (since := "2024-10-05")] +alias uniformInducing := isUniformInducing theorem tendsto_nhds_iff {ι : Type*} {f : α → β} {g : ι → α} {a : Filter ι} {b : α} (hf : Isometry f) : Filter.Tendsto g a (𝓝 b) ↔ Filter.Tendsto (f ∘ g) a (𝓝 (f b)) := - hf.uniformInducing.inducing.tendsto_nhds_iff + hf.isUniformInducing.inducing.tendsto_nhds_iff /-- An isometry is continuous. -/ protected theorem continuous (hf : Isometry f) : Continuous f := @@ -144,11 +149,11 @@ theorem _root_.isometry_subtype_coe {s : Set α} : Isometry ((↑) : s → α) : theorem comp_continuousOn_iff {γ} [TopologicalSpace γ] (hf : Isometry f) {g : γ → α} {s : Set γ} : ContinuousOn (f ∘ g) s ↔ ContinuousOn g s := - hf.uniformInducing.inducing.continuousOn_iff.symm + hf.isUniformInducing.inducing.continuousOn_iff.symm theorem comp_continuous_iff {γ} [TopologicalSpace γ] (hf : Isometry f) {g : γ → α} : Continuous (f ∘ g) ↔ Continuous g := - hf.uniformInducing.inducing.continuous_iff.symm + hf.isUniformInducing.inducing.continuous_iff.symm end PseudoEmetricIsometry @@ -162,12 +167,14 @@ protected theorem injective (h : Isometry f) : Injective f := h.antilipschitz.injective /-- An isometry from an emetric space is a uniform embedding -/ -protected theorem uniformEmbedding (hf : Isometry f) : UniformEmbedding f := - hf.antilipschitz.uniformEmbedding hf.lipschitz.uniformContinuous +lemma isUniformEmbedding (hf : Isometry f) : IsUniformEmbedding f := + hf.antilipschitz.isUniformEmbedding hf.lipschitz.uniformContinuous + +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding /-- An isometry from an emetric space is an embedding -/ protected theorem embedding (hf : Isometry f) : Embedding f := - hf.uniformEmbedding.embedding + hf.isUniformEmbedding.embedding /-- An isometry from a complete emetric space is a closed embedding -/ theorem closedEmbedding [CompleteSpace α] [EMetricSpace γ] {f : α → γ} (hf : Isometry f) : @@ -226,11 +233,14 @@ end Isometry -- namespace /-- A uniform embedding from a uniform space to a metric space is an isometry with respect to the induced metric space structure on the source space. -/ -theorem UniformEmbedding.to_isometry {α β} [UniformSpace α] [MetricSpace β] {f : α → β} - (h : UniformEmbedding f) : (letI := h.comapMetricSpace f; Isometry f) := +theorem IsUniformEmbedding.to_isometry {α β} [UniformSpace α] [MetricSpace β] {f : α → β} + (h : IsUniformEmbedding f) : (letI := h.comapMetricSpace f; Isometry f) := let _ := h.comapMetricSpace f Isometry.of_dist_eq fun _ _ => rfl +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.to_isometry := IsUniformEmbedding.to_isometry + /-- An embedding from a topological space to a metric space is an isometry with respect to the induced metric space structure on the source space. -/ theorem Embedding.to_isometry {α β} [TopologicalSpace α] [MetricSpace β] {f : α → β} @@ -465,7 +475,7 @@ theorem mul_apply (e₁ e₂ : α ≃ᵢ α) (x : α) : (e₁ * e₂) x = e₁ ( theorem completeSpace_iff (e : α ≃ᵢ β) : CompleteSpace α ↔ CompleteSpace β := by simp only [completeSpace_iff_isComplete_univ, ← e.range_eq_univ, ← image_univ, - isComplete_image_iff e.isometry.uniformInducing] + isComplete_image_iff e.isometry.isUniformInducing] protected theorem completeSpace [CompleteSpace β] (e : α ≃ᵢ β) : CompleteSpace α := e.completeSpace_iff.2 ‹_› diff --git a/Mathlib/Topology/MetricSpace/Kuratowski.lean b/Mathlib/Topology/MetricSpace/Kuratowski.lean index 8063585c24d8e..5a21609d09845 100644 --- a/Mathlib/Topology/MetricSpace/Kuratowski.lean +++ b/Mathlib/Topology/MetricSpace/Kuratowski.lean @@ -19,16 +19,16 @@ noncomputable section open Set Metric TopologicalSpace NNReal ENNReal lp Function -universe u v w +universe u -variable {α : Type u} {β : Type v} {γ : Type w} +variable {α : Type u} namespace KuratowskiEmbedding /-! ### Any separable metric space can be embedded isometrically in ℓ^∞(ℕ, ℝ) -/ -variable {f g : ℓ^∞(ℕ)} {n : ℕ} {C : ℝ} [MetricSpace α] (x : ℕ → α) (a b : α) +variable {n : ℕ} [MetricSpace α] (x : ℕ → α) (a : α) /-- A metric space can be embedded in `l^∞(ℝ)` via the distances to points in a fixed countable set, if this set is dense. This map is given in `kuratowskiEmbedding`, diff --git a/Mathlib/Topology/MetricSpace/PiNat.lean b/Mathlib/Topology/MetricSpace/PiNat.lean index 8c9627c5ed747..bfd470b9972da 100644 --- a/Mathlib/Topology/MetricSpace/PiNat.lean +++ b/Mathlib/Topology/MetricSpace/PiNat.lean @@ -51,7 +51,7 @@ noncomputable section open Topology TopologicalSpace Set Metric Filter Function -attribute [local simp] pow_le_pow_iff_right one_lt_two inv_le_inv zero_le_two zero_lt_two +attribute [local simp] pow_le_pow_iff_right one_lt_two inv_le_inv₀ zero_le_two zero_lt_two variable {E : ℕ → Type*} @@ -264,7 +264,7 @@ theorem dist_triangle_nonarch (x y z : ∀ n, E n) : dist x z ≤ max (dist x y) · simp rcases eq_or_ne y z with (rfl | hyz) · simp - simp only [dist_eq_of_ne, hxz, hxy, hyz, inv_le_inv, one_div, inv_pow, zero_lt_two, Ne, + simp only [dist_eq_of_ne, hxz, hxy, hyz, inv_le_inv₀, one_div, inv_pow, zero_lt_two, Ne, not_false_iff, le_max_iff, pow_le_pow_iff_right, one_lt_two, pow_pos, min_le_iff.1 (min_firstDiff_le x y z hxz)] @@ -294,7 +294,7 @@ theorem apply_eq_of_dist_lt {x y : ∀ n, E n} {n : ℕ} (h : dist x y < (1 / 2) rcases eq_or_ne x y with (rfl | hne) · rfl have : n < firstDiff x y := by - simpa [dist_eq_of_ne hne, inv_lt_inv, pow_lt_pow_iff_right, one_lt_two] using h + simpa [dist_eq_of_ne hne, inv_lt_inv₀, pow_lt_pow_iff_right, one_lt_two] using h exact apply_eq_of_lt_firstDiff (hi.trans_lt this) /-- A function to a pseudo-metric-space is `1`-Lipschitz if and only if points in the same cylinder diff --git a/Mathlib/Topology/MetricSpace/Polish.lean b/Mathlib/Topology/MetricSpace/Polish.lean index 66175bc090fb4..6db429aedccbf 100644 --- a/Mathlib/Topology/MetricSpace/Polish.lean +++ b/Mathlib/Topology/MetricSpace/Polish.lean @@ -146,7 +146,7 @@ theorem _root_.ClosedEmbedding.polishSpace [TopologicalSpace α] [TopologicalSpa letI : MetricSpace α := hf.toEmbedding.comapMetricSpace f haveI : SecondCountableTopology α := hf.toEmbedding.secondCountableTopology have : CompleteSpace α := by - rw [completeSpace_iff_isComplete_range hf.toEmbedding.to_isometry.uniformInducing] + rw [completeSpace_iff_isComplete_range hf.toEmbedding.to_isometry.isUniformInducing] exact hf.isClosed_range.isComplete infer_instance diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean b/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean index 65722ebb2e6b9..550dee230352d 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Basic.lean @@ -61,24 +61,34 @@ namespace Metric -- instantiate pseudometric space as a topology variable {x y z : α} {δ ε ε₁ ε₂ : ℝ} {s : Set α} -nonrec theorem uniformInducing_iff [PseudoMetricSpace β] {f : α → β} : - UniformInducing f ↔ UniformContinuous f ∧ +nonrec theorem isUniformInducing_iff [PseudoMetricSpace β] {f : α → β} : + IsUniformInducing f ↔ UniformContinuous f ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, dist (f a) (f b) < ε → dist a b < δ := - uniformInducing_iff'.trans <| Iff.rfl.and <| + isUniformInducing_iff'.trans <| Iff.rfl.and <| ((uniformity_basis_dist.comap _).le_basis_iff uniformity_basis_dist).trans <| by simp only [subset_def, Prod.forall, gt_iff_lt, preimage_setOf_eq, Prod.map_apply, mem_setOf] -nonrec theorem uniformEmbedding_iff [PseudoMetricSpace β] {f : α → β} : - UniformEmbedding f ↔ Function.Injective f ∧ UniformContinuous f ∧ +@[deprecated (since := "2024-10-05")] +alias uniformInducing_iff := isUniformInducing_iff + +nonrec theorem isUniformEmbedding_iff [PseudoMetricSpace β] {f : α → β} : + IsUniformEmbedding f ↔ Function.Injective f ∧ UniformContinuous f ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, dist (f a) (f b) < ε → dist a b < δ := by - rw [uniformEmbedding_iff, and_comm, uniformInducing_iff] + rw [isUniformEmbedding_iff, and_comm, isUniformInducing_iff] + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_iff := isUniformEmbedding_iff /-- If a map between pseudometric spaces is a uniform embedding then the distance between `f x` and `f y` is controlled in terms of the distance between `x` and `y`. -/ -theorem controlled_of_uniformEmbedding [PseudoMetricSpace β] {f : α → β} (h : UniformEmbedding f) : +theorem controlled_of_isUniformEmbedding [PseudoMetricSpace β] {f : α → β} + (h : IsUniformEmbedding f) : (∀ ε > 0, ∃ δ > 0, ∀ {a b : α}, dist a b < δ → dist (f a) (f b) < ε) ∧ ∀ δ > 0, ∃ ε > 0, ∀ {a b : α}, dist (f a) (f b) < ε → dist a b < δ := - ⟨uniformContinuous_iff.1 h.uniformContinuous, (uniformEmbedding_iff.1 h).2.2⟩ + ⟨uniformContinuous_iff.1 h.uniformContinuous, (isUniformEmbedding_iff.1 h).2.2⟩ + +@[deprecated (since := "2024-10-01")] +alias controlled_of_uniformEmbedding := controlled_of_isUniformEmbedding theorem totallyBounded_iff {s : Set α} : TotallyBounded s ↔ ∀ ε > 0, ∃ t : Set α, t.Finite ∧ s ⊆ ⋃ y ∈ t, ball y ε := diff --git a/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean b/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean index 3ad6637ff4565..764f2c2b7f1f1 100644 --- a/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean +++ b/Mathlib/Topology/MetricSpace/Pseudo/Constructions.lean @@ -44,10 +44,13 @@ def Inducing.comapPseudoMetricSpace {α β} [TopologicalSpace α] [m : PseudoMet /-- Pull back a pseudometric space structure by a uniform inducing map. This is a version of `PseudoMetricSpace.induced` useful in case if the domain already has a `UniformSpace` structure. -/ -def UniformInducing.comapPseudoMetricSpace {α β} [UniformSpace α] [m : PseudoMetricSpace β] - (f : α → β) (h : UniformInducing f) : PseudoMetricSpace α := +def IsUniformInducing.comapPseudoMetricSpace {α β} [UniformSpace α] [m : PseudoMetricSpace β] + (f : α → β) (h : IsUniformInducing f) : PseudoMetricSpace α := .replaceUniformity (.induced f m) h.comap_uniformity.symm +@[deprecated (since := "2024-10-08")] alias UniformInducing.comapPseudoMetricSpace := + IsUniformInducing.comapPseudoMetricSpace + instance Subtype.pseudoMetricSpace {p : α → Prop} : PseudoMetricSpace (Subtype p) := PseudoMetricSpace.induced Subtype.val ‹_› diff --git a/Mathlib/Topology/MetricSpace/ShrinkingLemma.lean b/Mathlib/Topology/MetricSpace/ShrinkingLemma.lean index 058f2115e3541..b7b081e3fb55d 100644 --- a/Mathlib/Topology/MetricSpace/ShrinkingLemma.lean +++ b/Mathlib/Topology/MetricSpace/ShrinkingLemma.lean @@ -27,7 +27,7 @@ open Set Metric open Topology variable {α : Type u} {ι : Type v} [MetricSpace α] [ProperSpace α] {c : ι → α} -variable {x : α} {r : ℝ} {s : Set α} +variable {s : Set α} /-- **Shrinking lemma** for coverings by open balls in a proper metric space. A point-finite open cover of a closed subset of a proper metric space by open balls can be shrunk to a new cover by diff --git a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean index c274fbbc8e376..50b3c349f536c 100644 --- a/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean +++ b/Mathlib/Topology/MetricSpace/ThickenedIndicator.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Kalle Kytölä -/ import Mathlib.Data.ENNReal.Basic -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded import Mathlib.Topology.MetricSpace.Thickening /-! @@ -128,7 +128,7 @@ theorem thickenedIndicatorAux_tendsto_indicator_closure {δseq : ℕ → ℝ} specialize δseq_lim ε ε_pos simp only [dist_zero_right, Real.norm_eq_abs, eventually_atTop] at δseq_lim rcases δseq_lim with ⟨N, hN⟩ - apply @tendsto_atTop_of_eventually_const _ _ _ _ _ _ _ N + apply tendsto_atTop_of_eventually_const (i₀ := N) intro n n_large have key : x ∉ thickening ε E := by simpa only [thickening, mem_setOf_eq, not_lt] using ε_lt.le refine le_antisymm ?_ bot_le diff --git a/Mathlib/Topology/MetricSpace/Ultra/Basic.lean b/Mathlib/Topology/MetricSpace/Ultra/Basic.lean index 5b00adb8cfda9..ceccb0c003e73 100644 --- a/Mathlib/Topology/MetricSpace/Ultra/Basic.lean +++ b/Mathlib/Topology/MetricSpace/Ultra/Basic.lean @@ -50,6 +50,18 @@ lemma dist_triangle_max : dist x z ≤ max (dist x y) (dist y z) := namespace IsUltrametricDist +/-- All triangles are isosceles in an ultrametric space. -/ +lemma dist_eq_max_of_dist_ne_dist (h : dist x y ≠ dist y z) : + dist x z = max (dist x y) (dist y z) := by + apply le_antisymm (dist_triangle_max x y z) + rcases h.lt_or_lt with h | h + · rw [max_eq_right h.le] + apply (le_max_iff.mp <| dist_triangle_max y x z).resolve_left + simpa only [not_le, dist_comm x y] using h + · rw [max_eq_left h.le, dist_comm x y, dist_comm x z] + apply (le_max_iff.mp <| dist_triangle_max y z x).resolve_left + simpa only [not_le, dist_comm x y] using h + instance subtype (p : X → Prop) : IsUltrametricDist (Subtype p) := ⟨fun _ _ _ ↦ by simpa [Subtype.dist_eq] using dist_triangle_max _ _ _⟩ diff --git a/Mathlib/Topology/MetricSpace/Ultra/ContinuousMaps.lean b/Mathlib/Topology/MetricSpace/Ultra/ContinuousMaps.lean new file mode 100644 index 0000000000000..62dd5bf7c5b27 --- /dev/null +++ b/Mathlib/Topology/MetricSpace/Ultra/ContinuousMaps.lean @@ -0,0 +1,22 @@ +/- +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.Topology.ContinuousMap.Compact +import Mathlib.Topology.MetricSpace.Ultra.Basic + +/-! +# Ultrametric structure on continuous maps +-/ + +/-- Continuous maps from a compact space to an ultrametric space are an ultrametric space. -/ +instance ContinuousMap.isUltrametricDist {X Y : Type*} + [TopologicalSpace X] [CompactSpace X] [MetricSpace Y] [IsUltrametricDist Y] : + IsUltrametricDist C(X, Y) := by + constructor + intro f g h + rw [ContinuousMap.dist_le (by positivity)] + refine fun x ↦ (dist_triangle_max (f x) (g x) (h x)).trans (max_le_max ?_ ?_) <;> + exact ContinuousMap.dist_apply_le_dist x diff --git a/Mathlib/Topology/MetricSpace/Ultra/TotallySeparated.lean b/Mathlib/Topology/MetricSpace/Ultra/TotallySeparated.lean new file mode 100644 index 0000000000000..09edc0330ec3e --- /dev/null +++ b/Mathlib/Topology/MetricSpace/Ultra/TotallySeparated.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2024 Yakov Pechersky. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Yakov Pechersky, David Loeffler +-/ +import Mathlib.Topology.MetricSpace.Defs +import Mathlib.Topology.MetricSpace.Ultra.Basic + +/-! +# Ultrametric spaces are totally separated + +In a metric space with an ultrametric, the space is totally separated, hence totally disconnected. + +## Tags + +ultrametric, nonarchimedean, totally separated, totally disconnected +-/ +open Metric IsUltrametricDist + +instance {X : Type*} [MetricSpace X] [IsUltrametricDist X] : TotallySeparatedSpace X := + totallySeparatedSpace_iff_exists_isClopen.mpr fun x y h ↦ by + obtain ⟨r, hr, hr'⟩ := exists_between (dist_pos.mpr h) + refine ⟨_, IsUltrametricDist.isClopen_ball x r, ?_, ?_⟩ + · simp only [mem_ball, dist_self, hr] + · simp only [Set.mem_compl, mem_ball, dist_comm, not_lt, hr'.le] + +example {X : Type*} [MetricSpace X] [IsUltrametricDist X] : TotallyDisconnectedSpace X := + inferInstance diff --git a/Mathlib/Topology/Metrizable/Uniformity.lean b/Mathlib/Topology/Metrizable/Uniformity.lean index efdf16b745cec..3dc4176d75c21 100644 --- a/Mathlib/Topology/Metrizable/Uniformity.lean +++ b/Mathlib/Topology/Metrizable/Uniformity.lean @@ -158,8 +158,8 @@ theorem le_two_mul_dist_ofPreNNDist (d : X → X → ℝ≥0) (dist_self : ∀ x ← Option.coe_def, Option.toList_some, take_append_of_le_length hMl.le, getElem_cons_succ] · exact single_le_sum (fun x _ => zero_le x) _ (mem_iff_get.2 ⟨⟨M, hM_lt⟩, getElem_zipWith⟩) · rcases hMl.eq_or_lt with (rfl | hMl) - · simp only [getElem_append_right' le_rfl, sub_self, getElem_singleton, dist_self, zero_le] - rw [getElem_append _ hMl] + · simp only [getElem_append_right le_rfl, sub_self, getElem_singleton, dist_self, zero_le] + rw [getElem_append_left hMl] have hlen : length (drop (M + 1) l) = length l - (M + 1) := length_drop _ _ have hlen_lt : length l - (M + 1) < length l := Nat.sub_lt_of_pos_le M.succ_pos hMl refine (ihn _ hlen_lt _ y _ hlen).trans ?_ diff --git a/Mathlib/Topology/Metrizable/Urysohn.lean b/Mathlib/Topology/Metrizable/Urysohn.lean index f136cbf094264..bddb6a6ead668 100644 --- a/Mathlib/Topology/Metrizable/Urysohn.lean +++ b/Mathlib/Topology/Metrizable/Urysohn.lean @@ -5,7 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Analysis.SpecificLimits.Basic import Mathlib.Topology.UrysohnsLemma -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded import Mathlib.Topology.Metrizable.Basic /-! # Urysohn's Metrization Theorem diff --git a/Mathlib/Topology/NoetherianSpace.lean b/Mathlib/Topology/NoetherianSpace.lean index 88d07a7493deb..9c2e714b18849 100644 --- a/Mathlib/Topology/NoetherianSpace.lean +++ b/Mathlib/Topology/NoetherianSpace.lean @@ -43,12 +43,10 @@ variable (α β : Type*) [TopologicalSpace α] [TopologicalSpace β] namespace TopologicalSpace /-- Type class for noetherian spaces. It is defined to be spaces whose open sets satisfies ACC. -/ -@[mk_iff] -class NoetherianSpace : Prop where - wellFounded_opens : WellFounded ((· > ·) : Opens α → Opens α → Prop) +abbrev NoetherianSpace : Prop := WellFoundedGT (Opens α) theorem noetherianSpace_iff_opens : NoetherianSpace α ↔ ∀ s : Opens α, IsCompact (s : Set α) := by - rw [noetherianSpace_iff, CompleteLattice.wellFounded_iff_isSupFiniteCompact, + rw [NoetherianSpace, CompleteLattice.wellFoundedGT_iff_isSupFiniteCompact, CompleteLattice.isSupFiniteCompact_iff_all_elements_compact] exact forall_congr' Opens.isCompactElement_iff @@ -78,12 +76,12 @@ variable (α) open List in theorem noetherianSpace_TFAE : TFAE [NoetherianSpace α, - WellFounded fun s t : Closeds α => s < t, + WellFoundedLT (Closeds α), ∀ s : Set α, IsCompact s, ∀ s : Opens α, IsCompact (s : Set α)] := by tfae_have 1 ↔ 2 := by - refine (noetherianSpace_iff α).trans (Opens.compl_bijective.2.wellFounded_iff ?_) - exact (@OrderIso.compl (Set α)).lt_iff_lt.symm + simp_rw [isWellFounded_iff] + exact Opens.compl_bijective.2.wellFounded_iff (@OrderIso.compl (Set α)).lt_iff_lt.symm tfae_have 1 ↔ 4 := noetherianSpace_iff_opens α tfae_have 1 → 3 := @NoetherianSpace.isCompact α _ tfae_have 3 → 4 := fun h s => h s @@ -94,9 +92,13 @@ variable {α} theorem noetherianSpace_iff_isCompact : NoetherianSpace α ↔ ∀ s : Set α, IsCompact s := (noetherianSpace_TFAE α).out 0 2 +instance [NoetherianSpace α] : WellFoundedLT (Closeds α) := + Iff.mp ((noetherianSpace_TFAE α).out 0 1) ‹_› + +@[deprecated (since := "2024-10-07")] theorem NoetherianSpace.wellFounded_closeds [NoetherianSpace α] : WellFounded fun s t : Closeds α => s < t := - Iff.mp ((noetherianSpace_TFAE α).out 0 1) ‹_› + wellFounded_lt instance {α} : NoetherianSpace (CofiniteTopology α) := by simp only [noetherianSpace_iff_isCompact, isCompact_iff_ultrafilter_le_nhds, @@ -153,7 +155,7 @@ instance (priority := 100) Finite.to_noetherianSpace [Finite α] : NoetherianSpa /-- In a Noetherian space, every closed set is a finite union of irreducible closed sets. -/ theorem NoetherianSpace.exists_finite_set_closeds_irreducible [NoetherianSpace α] (s : Closeds α) : ∃ S : Set (Closeds α), S.Finite ∧ (∀ t ∈ S, IsIrreducible (t : Set α)) ∧ s = sSup S := by - apply wellFounded_closeds.induction s; clear s + apply wellFounded_lt.induction s; clear s intro s H rcases eq_or_ne s ⊥ with rfl | h₀ · use ∅; simp diff --git a/Mathlib/Topology/Order.lean b/Mathlib/Topology/Order.lean index fbb1957b3b9ee..c1c9b629e8592 100644 --- a/Mathlib/Topology/Order.lean +++ b/Mathlib/Topology/Order.lean @@ -89,9 +89,6 @@ lemma tendsto_nhds_generateFrom_iff {β : Type*} {m : α → β} {f : Filter α} simp only [nhds_generateFrom, @forall_swap (b ∈ _), tendsto_iInf, mem_setOf_eq, and_imp, tendsto_principal]; rfl -@[deprecated (since := "2023-12-24")] -alias ⟨_, tendsto_nhds_generateFrom⟩ := tendsto_nhds_generateFrom_iff - /-- Construct a topology on α given the filter of neighborhoods of each point of α. -/ protected def mkOfNhds (n : α → Filter α) : TopologicalSpace α where IsOpen s := ∀ a ∈ s, s ∈ n a @@ -621,9 +618,6 @@ lemma continuous_generateFrom_iff {t : TopologicalSpace α} {b : Set (Set β)} : rw [continuous_iff_coinduced_le, le_generateFrom_iff_subset_isOpen] simp only [isOpen_coinduced, preimage_id', subset_def, mem_setOf] -@[deprecated (since := "2023-12-24")] -alias ⟨_, continuous_generateFrom⟩ := continuous_generateFrom_iff - @[continuity, fun_prop] theorem continuous_induced_dom {t : TopologicalSpace β} : Continuous[induced f t, t] f := continuous_iff_le_induced.2 le_rfl diff --git a/Mathlib/Topology/Order/Hom/Basic.lean b/Mathlib/Topology/Order/Hom/Basic.lean index 11dc84c396d3c..b0e27200893c5 100644 --- a/Mathlib/Topology/Order/Hom/Basic.lean +++ b/Mathlib/Topology/Order/Hom/Basic.lean @@ -4,7 +4,8 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yaël Dillies -/ import Mathlib.Order.Hom.Basic -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.Basic +import Mathlib.Topology.ContinuousMap.Defs /-! # Continuous order homomorphisms diff --git a/Mathlib/Topology/Order/LawsonTopology.lean b/Mathlib/Topology/Order/LawsonTopology.lean index 4c730963736e1..945cc85292c34 100644 --- a/Mathlib/Topology/Order/LawsonTopology.lean +++ b/Mathlib/Topology/Order/LawsonTopology.lean @@ -49,7 +49,7 @@ Lawson topology, preorder open Set TopologicalSpace -variable {α β : Type*} +variable {α : Type*} namespace Topology @@ -94,8 +94,7 @@ protected theorem isTopologicalBasis : TopologicalSpace.IsTopologicalBasis (laws convert IsTopologicalBasis.inf_induced IsLower.isTopologicalBasis (isTopologicalBasis_opens (α := WithScott α)) WithLower.toLower WithScott.toScott - erw [@topology_eq_lawson α _ _ _] - rw [lawson] + rw [@topology_eq_lawson α _ _ _, lawson] apply (congrArg₂ Inf.inf _) _ · letI _ := lower α; exact @IsLower.withLowerHomeomorph α ‹_› (lower α) ⟨rfl⟩ |>.inducing.induced letI _ := scott α; exact @IsScott.withScottHomeomorph α _ (scott α) ⟨rfl⟩ |>.inducing.induced @@ -144,7 +143,7 @@ instance instIsLawson : IsLawson (WithLawson α) := ⟨rfl⟩ /-- If `α` is equipped with the Lawson topology, then it is homeomorphic to `WithLawson α`. -/ def homeomorph [TopologicalSpace α] [IsLawson α] : WithLawson α ≃ₜ α := - ofLawson.toHomeomorphOfInducing ⟨by erw [@IsLawson.topology_eq_lawson α _ _, induced_id]; rfl⟩ + ofLawson.toHomeomorphOfInducing ⟨by erw [IsLawson.topology_eq_lawson (α := α), induced_id]; rfl⟩ theorem isOpen_preimage_ofLawson {S : Set α} : IsOpen (ofLawson ⁻¹' S) ↔ (lawson α).IsOpen S := Iff.rfl diff --git a/Mathlib/Topology/Order/LowerUpperTopology.lean b/Mathlib/Topology/Order/LowerUpperTopology.lean index ddf4767a9c335..95dc12c92c61f 100644 --- a/Mathlib/Topology/Order/LowerUpperTopology.lean +++ b/Mathlib/Topology/Order/LowerUpperTopology.lean @@ -263,10 +263,6 @@ lemma continuous_iff_Ici [TopologicalSpace β] {f : β → α} : obtain rfl := IsLower.topology_eq α simp [continuous_generateFrom_iff] -/-- A function `f : β → α` with lower topology in the codomain is continuous provided that the -preimage of every interval `Set.Ici a` is a closed set. -/ -@[deprecated (since := "2023-12-24")] alias ⟨_, continuous_of_Ici⟩ := continuous_iff_Ici - end Preorder section PartialOrder @@ -399,13 +395,6 @@ lemma continuous_iff_Iic [TopologicalSpace β] {f : β → α} : Continuous f ↔ ∀ a, IsClosed (f ⁻¹' (Iic a)) := IsLower.continuous_iff_Ici (α := αᵒᵈ) -/-- A function `f : β → α` with upper topology in the codomain is continuous -provided that the preimage of every interval `Set.Iic a` is a closed set. -/ -@[deprecated (since := "2023-12-24")] -lemma continuous_of_Iic [TopologicalSpace β] {f : β → α} (h : ∀ a, IsClosed (f ⁻¹' (Iic a))) : - Continuous f := - continuous_iff_Iic.2 h - end Preorder diff --git a/Mathlib/Topology/Order/OrderClosed.lean b/Mathlib/Topology/Order/OrderClosed.lean index 7a476daeaf513..e2763d592bc24 100644 --- a/Mathlib/Topology/Order/OrderClosed.lean +++ b/Mathlib/Topology/Order/OrderClosed.lean @@ -543,7 +543,7 @@ namespace Subtype -- todo: add `OrderEmbedding.orderClosedTopology` instance {p : α → Prop} : OrderClosedTopology (Subtype p) := have this : Continuous fun p : Subtype p × Subtype p => ((p.fst : α), (p.snd : α)) := - continuous_subtype_val.prod_map continuous_subtype_val + continuous_subtype_val.prodMap continuous_subtype_val OrderClosedTopology.mk (t.isClosed_le'.preimage this) end Subtype diff --git a/Mathlib/Topology/Order/ScottTopology.lean b/Mathlib/Topology/Order/ScottTopology.lean index 6f26fd5939149..747074b163cfb 100644 --- a/Mathlib/Topology/Order/ScottTopology.lean +++ b/Mathlib/Topology/Order/ScottTopology.lean @@ -107,7 +107,7 @@ lemma dirSupClosed_Iic (a : α) : DirSupClosed (Iic a) := fun _d _ _ _a ha ↦ ( end Preorder section CompleteLattice -variable [CompleteLattice α] {s t : Set α} +variable [CompleteLattice α] {s : Set α} lemma dirSupInacc_iff_forall_sSup : DirSupInacc s ↔ ∀ ⦃d⦄, d.Nonempty → DirectedOn (· ≤ ·) d → sSup d ∈ s → (d ∩ s).Nonempty := by @@ -124,7 +124,7 @@ namespace Topology /-! ### Scott-Hausdorff topology -/ section ScottHausdorff -variable [Preorder α] {s : Set α} +variable [Preorder α] /-- The Scott-Hausdorff topology. @@ -164,7 +164,7 @@ variable {α} lemma isOpen_iff : IsOpen s ↔ ∀ ⦃d : Set α⦄, d.Nonempty → DirectedOn (· ≤ ·) d → ∀ ⦃a : α⦄, IsLUB d a → - a ∈ s → ∃ b ∈ d, Ici b ∩ d ⊆ s := by erw [topology_eq_scottHausdorff (α := α)]; rfl + a ∈ s → ∃ b ∈ d, Ici b ∩ d ⊆ s := by rw [topology_eq_scottHausdorff (α := α)]; rfl lemma dirSupInacc_of_isOpen (h : IsOpen s) : DirSupInacc s := fun d hd₁ hd₂ a hda hd₃ ↦ by @@ -225,7 +225,7 @@ lemma topology_eq : ‹_› = scott α := topology_eq_scott variable {α} {s : Set α} {a : α} lemma isOpen_iff_isUpperSet_and_scottHausdorff_open : - IsOpen s ↔ IsUpperSet s ∧ IsOpen[scottHausdorff α] s := by erw [topology_eq α]; rfl + IsOpen s ↔ IsUpperSet s ∧ IsOpen[scottHausdorff α] s := by rw [topology_eq α]; rfl lemma isOpen_iff_isUpperSet_and_dirSupInacc : IsOpen s ↔ IsUpperSet s ∧ DirSupInacc s := by rw [isOpen_iff_isUpperSet_and_scottHausdorff_open] diff --git a/Mathlib/Topology/Order/UpperLowerSetTopology.lean b/Mathlib/Topology/Order/UpperLowerSetTopology.lean index 5aa350f222cbb..02681dbd9f86d 100644 --- a/Mathlib/Topology/Order/UpperLowerSetTopology.lean +++ b/Mathlib/Topology/Order/UpperLowerSetTopology.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Christopher Hoskin -/ import Mathlib.Topology.AlexandrovDiscrete -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Topology.Order.LowerUpperTopology /-! diff --git a/Mathlib/Topology/PartitionOfUnity.lean b/Mathlib/Topology/PartitionOfUnity.lean index bdc558694b1cd..661a124cbc7d4 100644 --- a/Mathlib/Topology/PartitionOfUnity.lean +++ b/Mathlib/Topology/PartitionOfUnity.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Algebra.BigOperators.Finprod -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra import Mathlib.Topology.Compactness.Paracompact import Mathlib.Topology.ShrinkingLemma import Mathlib.Topology.UrysohnsLemma @@ -139,7 +139,7 @@ variable {E : Type*} [AddCommMonoid E] [SMulWithZero ℝ E] [TopologicalSpace E] instance : FunLike (PartitionOfUnity ι X s) ι C(X, ℝ) where coe := toFun - coe_injective' := fun f g h ↦ by cases f; cases g; congr + coe_injective' f g h := by cases f; cases g; congr protected theorem locallyFinite : LocallyFinite fun i => support (f i) := f.locallyFinite' @@ -311,7 +311,7 @@ variable {s : Set X} (f : BumpCovering ι X s) instance : FunLike (BumpCovering ι X s) ι C(X, ℝ) where coe := toFun - coe_injective' := fun f g h ↦ by cases f; cases g; congr + coe_injective' f g h := by cases f; cases g; congr protected theorem locallyFinite : LocallyFinite fun i => support (f i) := f.locallyFinite' diff --git a/Mathlib/Topology/Perfect.lean b/Mathlib/Topology/Perfect.lean index 31622ec28846e..c390399234943 100644 --- a/Mathlib/Topology/Perfect.lean +++ b/Mathlib/Topology/Perfect.lean @@ -93,7 +93,7 @@ A topological space `X` is said to be perfect if its universe is a perfect set. Equivalently, this means that `𝓝[≠] x ≠ ⊥` for every point `x : X`. -/ @[mk_iff perfectSpace_def] -class PerfectSpace : Prop := +class PerfectSpace : Prop where univ_preperfect : Preperfect (Set.univ : Set α) theorem PerfectSpace.univ_perfect [PerfectSpace α] : Perfect (Set.univ : Set α) := diff --git a/Mathlib/Topology/Separation.lean b/Mathlib/Topology/Separation.lean index 2f7f8cfdcd660..98e4bd5cdac2f 100644 --- a/Mathlib/Topology/Separation.lean +++ b/Mathlib/Topology/Separation.lean @@ -1451,7 +1451,7 @@ theorem Set.InjOn.exists_mem_nhdsSet {X Y : Type*} [TopologicalSpace X] [Topolog · rcases loc x hx with ⟨u, hu, hf⟩ exact Filter.mem_of_superset (prod_mem_nhds hu hu) <| forall_prod_set.2 hf · suffices ∀ᶠ z in 𝓝 (x, y), f z.1 ≠ f z.2 from this.mono fun _ hne h ↦ absurd h hne - refine (fc x hx).prod_map' (fc y hy) <| isClosed_diagonal.isOpen_compl.mem_nhds ?_ + refine (fc x hx).prodMap' (fc y hy) <| isClosed_diagonal.isOpen_compl.mem_nhds ?_ exact inj.ne hx hy hne rw [← eventually_nhdsSet_iff_forall, sc.nhdsSet_prod_eq sc] at this exact eventually_prod_self_iff.1 this @@ -2560,7 +2560,7 @@ theorem nhds_basis_clopen (x : X) : (𝓝 x).HasBasis (fun s : Set X => x ∈ s rintro ⟨s, hs, hxs⟩ ⟨t, ht, hxt⟩ exact ⟨⟨s ∩ t, hs.inter ht, ⟨hxs, hxt⟩⟩, inter_subset_left, inter_subset_right⟩ have h_nhd : ∀ y ∈ ⋂ s : N, s.val, U ∈ 𝓝 y := fun y y_in => by - erw [hx, mem_singleton_iff] at y_in + rw [hx, mem_singleton_iff] at y_in rwa [y_in] exact exists_subset_nhds_of_compactSpace hdir hNcl h_nhd · rintro ⟨V, ⟨hxV, -, V_op⟩, hUV : V ⊆ U⟩ diff --git a/Mathlib/Topology/Sets/Opens.lean b/Mathlib/Topology/Sets/Opens.lean index 5e2b0453cc80e..cf7ecc4c6353c 100644 --- a/Mathlib/Topology/Sets/Opens.lean +++ b/Mathlib/Topology/Sets/Opens.lean @@ -6,7 +6,7 @@ Authors: Johannes Hölzl, Mario Carneiro, Floris van Doorn import Mathlib.Order.Hom.CompleteLattice import Mathlib.Topology.Bases import Mathlib.Topology.Homeomorph -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Order.CompactlyGenerated.Basic import Mathlib.Order.Copy diff --git a/Mathlib/Topology/Sets/Order.lean b/Mathlib/Topology/Sets/Order.lean index f787206f3f3ad..1a139b07f9633 100644 --- a/Mathlib/Topology/Sets/Order.lean +++ b/Mathlib/Topology/Sets/Order.lean @@ -15,7 +15,7 @@ In this file we define the type of clopen upper sets. open Set TopologicalSpace -variable {α β : Type*} [TopologicalSpace α] [LE α] [TopologicalSpace β] [LE β] +variable {α : Type*} [TopologicalSpace α] [LE α] /-! ### Compact open sets -/ diff --git a/Mathlib/Topology/Sheaves/LocalPredicate.lean b/Mathlib/Topology/Sheaves/LocalPredicate.lean index c27257e4a8618..c9213520cca76 100644 --- a/Mathlib/Topology/Sheaves/LocalPredicate.lean +++ b/Mathlib/Topology/Sheaves/LocalPredicate.lean @@ -217,11 +217,9 @@ def stalkToFiber (P : LocalPredicate T) (x : X) : (subsheafToTypes P).presheaf.s -- Porting note (#11119): removed `simp` attribute, -- due to left hand side is not in simple normal form. -theorem stalkToFiber_germ (P : LocalPredicate T) (U : Opens X) (x : U) (f) : - stalkToFiber P x ((subsheafToTypes P).presheaf.germ x f) = f.1 x := by - dsimp [Presheaf.germ, stalkToFiber] - cases x - simp +theorem stalkToFiber_germ (P : LocalPredicate T) (U : Opens X) (x : X) (hx : x ∈ U) (f) : + stalkToFiber P x ((subsheafToTypes P).presheaf.germ U x hx f) = f.1 ⟨x, hx⟩ := by + simp [Presheaf.germ, stalkToFiber] /-- The `stalkToFiber` map is surjective at `x` if every point in the fiber `T x` has an allowed section passing through it. @@ -231,8 +229,8 @@ theorem stalkToFiber_surjective (P : LocalPredicate T) (x : X) Function.Surjective (stalkToFiber P x) := fun t => by rcases w t with ⟨U, f, h, rfl⟩ fconstructor - · exact (subsheafToTypes P).presheaf.germ ⟨x, U.2⟩ ⟨f, h⟩ - · exact stalkToFiber_germ _ U.1 ⟨x, U.2⟩ ⟨f, h⟩ + · exact (subsheafToTypes P).presheaf.germ _ x U.2 ⟨f, h⟩ + · exact stalkToFiber_germ P U.1 x U.2 ⟨f, h⟩ /-- The `stalkToFiber` map is injective at `x` if any two allowed sections which agree at `x` agree on some neighborhood of `x`. @@ -247,8 +245,8 @@ theorem stalkToFiber_injective (P : LocalPredicate T) (x : X) -- We promise to provide all the ingredients of the proof later: let Q : ∃ (W : (OpenNhds x)ᵒᵖ) (s : ∀ w : (unop W).1, T w) (hW : P.pred s), - tU = (subsheafToTypes P).presheaf.germ ⟨x, (unop W).2⟩ ⟨s, hW⟩ ∧ - tV = (subsheafToTypes P).presheaf.germ ⟨x, (unop W).2⟩ ⟨s, hW⟩ := + tU = (subsheafToTypes P).presheaf.germ _ x (unop W).2 ⟨s, hW⟩ ∧ + tV = (subsheafToTypes P).presheaf.germ _ x (unop W).2 ⟨s, hW⟩ := ?_ · choose W s hW e using Q exact e.1.trans e.2.symm diff --git a/Mathlib/Topology/Sheaves/LocallySurjective.lean b/Mathlib/Topology/Sheaves/LocallySurjective.lean index 9293f95add655..1e4b5176e114b 100644 --- a/Mathlib/Topology/Sheaves/LocallySurjective.lean +++ b/Mathlib/Topology/Sheaves/LocallySurjective.lean @@ -85,11 +85,11 @@ theorem locally_surjective_iff_surjective_on_stalks (T : ℱ ⟶ 𝒢) : -- on which there exists s ∈ Γ_ ℱ V mapping to t |_ V. rcases hT.imageSieve_mem t x hxU with ⟨V, ι, ⟨s, h_eq⟩, hxV⟩ -- Then the germ of s maps to g. - use ℱ.germ ⟨x, hxV⟩ s + use ℱ.germ _ x hxV s -- Porting note: `convert` went too deep and swapped LHS and RHS of the remaining goal relative -- to lean 3. - convert stalkFunctor_map_germ_apply V ⟨x, hxV⟩ T s using 1 - simpa [h_eq] using (germ_res_apply 𝒢 ι ⟨x, hxV⟩ t).symm + convert stalkFunctor_map_germ_apply V x hxV T s using 1 + simpa [h_eq] using (germ_res_apply 𝒢 ι x hxV t).symm · /- human proof: Let U be an open set, t ∈ Γ ℱ U a section, x ∈ U a point. By surjectivity on stalks, the germ of t is the image of @@ -98,14 +98,14 @@ theorem locally_surjective_iff_surjective_on_stalks (T : ℱ ⟶ 𝒢) : we have T(s) |_ W = t |_ W. -/ constructor intro U t x hxU - set t_x := 𝒢.germ ⟨x, hxU⟩ t with ht_x + set t_x := 𝒢.germ _ x hxU t with ht_x obtain ⟨s_x, hs_x : ((stalkFunctor C x).map T) s_x = t_x⟩ := hT x t_x obtain ⟨V, hxV, s, rfl⟩ := ℱ.germ_exist x s_x -- rfl : ℱ.germ x s = s_x have key_W := 𝒢.germ_eq x hxV hxU (T.app _ s) t <| by convert hs_x using 1 symm - convert stalkFunctor_map_germ_apply _ _ _ s + convert stalkFunctor_map_germ_apply _ _ _ _ s obtain ⟨W, hxW, hWV, hWU, h_eq⟩ := key_W refine ⟨W, hWU, ⟨ℱ.map hWV.op s, ?_⟩, hxW⟩ convert h_eq using 1 diff --git a/Mathlib/Topology/Sheaves/Operations.lean b/Mathlib/Topology/Sheaves/Operations.lean index 85cb01ea80e1a..c982c9d8e3618 100644 --- a/Mathlib/Topology/Sheaves/Operations.lean +++ b/Mathlib/Topology/Sheaves/Operations.lean @@ -81,14 +81,14 @@ sections whose restriction onto each stalk falls in the given submonoid. -/ @[simps] noncomputable def submonoidPresheafOfStalk (S : ∀ x : X, Submonoid (F.stalk x)) : F.SubmonoidPresheaf where - obj U := ⨅ x : U.unop, Submonoid.comap (F.germ x) (S x) + obj U := ⨅ x : U.unop, Submonoid.comap (F.germ U.unop x.1 x.2) (S x) map {U V} i := by intro s hs simp only [Submonoid.mem_comap, Submonoid.mem_iInf] at hs ⊢ intro x - change (F.map i.unop.op ≫ F.germ x) s ∈ _ + change (F.map i.unop.op ≫ F.germ V.unop x.1 x.2) s ∈ _ rw [F.germ_res] - exact hs ⟨_,_⟩ + exact hs ⟨_, i.unop.le x.2⟩ noncomputable instance : Inhabited F.SubmonoidPresheaf := ⟨F.submonoidPresheafOfStalk fun _ => ⊥⟩ @@ -121,11 +121,9 @@ instance (F : X.Sheaf CommRingCat.{w}) : Mono F.presheaf.toTotalQuotientPresheaf refine IsLocalization.injective (M := m) (S := Localization m) ?_ intro s hs t e apply section_ext F (unop U) - intro x + intro x hx rw [map_zero] - apply Submonoid.mem_iInf.mp hs x - -- Porting note: added `dsimp` to make `rw [← map_mul]` work - dsimp + apply Submonoid.mem_iInf.mp hs ⟨x, hx⟩ rw [← map_mul, e, map_zero] end Presheaf diff --git a/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean b/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean index 23061bd8b782f..6049ed866f9d8 100644 --- a/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean +++ b/Mathlib/Topology/Sheaves/PresheafOfFunctions.lean @@ -6,7 +6,7 @@ Authors: Kim Morrison import Mathlib.CategoryTheory.Yoneda import Mathlib.Topology.Sheaves.Presheaf import Mathlib.Topology.Category.TopCommRingCat -import Mathlib.Topology.ContinuousFunction.Algebra +import Mathlib.Topology.ContinuousMap.Algebra /-! # Presheaves of functions diff --git a/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean b/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean index 34b950b76fec8..5103d691a3229 100644 --- a/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean +++ b/Mathlib/Topology/Sheaves/SheafCondition/EqualizerProducts.lean @@ -263,7 +263,7 @@ def coneEquivInverseObj (c : Limits.Cone (SheafConditionEqualizerProducts.diagra rintro rfl rcases x with (⟨i⟩ | ⟨⟩) <;> rcases y with (⟨⟩ | ⟨j, j⟩) <;> rcases f' with ⟨⟩ · dsimp - erw [F.map_id] + rw [F.map_id] simp · dsimp simp only [Category.id_comp, Category.assoc] @@ -284,7 +284,7 @@ def coneEquivInverseObj (c : Limits.Cone (SheafConditionEqualizerProducts.diagra simp rfl · dsimp - erw [F.map_id] + rw [F.map_id] simp } /-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/ diff --git a/Mathlib/Topology/Sheaves/Sheafify.lean b/Mathlib/Topology/Sheaves/Sheafify.lean index 423700fb192c9..36740da226f9a 100644 --- a/Mathlib/Topology/Sheaves/Sheafify.lean +++ b/Mathlib/Topology/Sheaves/Sheafify.lean @@ -44,8 +44,8 @@ namespace Sheafify The prelocal predicate on functions into the stalks, asserting that the function is equal to a germ. -/ def isGerm : PrelocalPredicate fun x => F.stalk x where - pred {U} f := ∃ g : F.obj (op U), ∀ x : U, f x = F.germ x g - res := fun i _ ⟨g, p⟩ => ⟨F.map i.op g, fun x => (p (i x)).trans (F.germ_res_apply i x g).symm⟩ + pred {U} f := ∃ g : F.obj (op U), ∀ x : U, f x = F.germ U x.1 x.2 g + res := fun i _ ⟨g, p⟩ => ⟨F.map i.op g, fun x ↦ (p (i x)).trans (F.germ_res_apply i x x.2 g).symm⟩ /-- The local predicate on functions into the stalks, asserting that the function is locally equal to a germ. @@ -66,12 +66,12 @@ sending each section to its germs. (This forms the unit of the adjunction.) -/ def toSheafify : F ⟶ F.sheafify.1 where - app U f := ⟨fun x => F.germ x f, PrelocalPredicate.sheafifyOf ⟨f, fun x => rfl⟩⟩ + app U f := ⟨fun x => F.germ _ x x.2 f, PrelocalPredicate.sheafifyOf ⟨f, fun x => rfl⟩⟩ naturality U U' f := by ext x apply Subtype.ext -- Porting note: Added `apply` ext ⟨u, m⟩ - exact germ_res_apply F f.unop ⟨u, m⟩ x + exact germ_res_apply F f.unop u m x /-- The natural morphism from the stalk of the sheafification to the original stalk. In `sheafifyStalkIso` we show this is an isomorphism. @@ -85,7 +85,7 @@ theorem stalkToFiber_surjective (x : X) : Function.Surjective (F.stalkToFiber x) obtain ⟨U, m, s, rfl⟩ := F.germ_exist _ t use ⟨U, m⟩ fconstructor - · exact fun y => F.germ y s + · exact fun y => F.germ _ _ y.2 s · exact ⟨PrelocalPredicate.sheafifyOf ⟨s, fun _ => rfl⟩, rfl⟩ theorem stalkToFiber_injective (x : X) : Function.Injective (F.stalkToFiber x) := by @@ -94,9 +94,9 @@ theorem stalkToFiber_injective (x : X) : Function.Injective (F.stalkToFiber x) : rcases hU ⟨x, U.2⟩ with ⟨U', mU, iU, gU, wU⟩ rcases hV ⟨x, V.2⟩ with ⟨V', mV, iV, gV, wV⟩ have wUx := wU ⟨x, mU⟩ - dsimp at wUx; erw [wUx] at e; clear wUx + dsimp at wUx; rw [wUx] at e; clear wUx have wVx := wV ⟨x, mV⟩ - dsimp at wVx; erw [wVx] at e; clear wVx + dsimp at wVx; rw [wVx] at e; clear wVx rcases F.germ_eq x mU mV gU gV e with ⟨W, mW, iU', iV', (e' : F.map iU'.op gU = F.map iV'.op gV)⟩ use ⟨W ⊓ (U' ⊓ V'), ⟨mW, mU, mV⟩⟩ refine ⟨?_, ?_, ?_⟩ @@ -108,7 +108,7 @@ theorem stalkToFiber_injective (x : X) : Function.Injective (F.stalkToFiber x) : specialize wU ⟨w.1, w.2.2.1⟩ specialize wV ⟨w.1, w.2.2.2⟩ dsimp at wU wV ⊢ - erw [wU, ← F.germ_res iU' ⟨w, w.2.1⟩, wV, ← F.germ_res iV' ⟨w, w.2.1⟩, + rw [wU, ← F.germ_res iU' w w.2.1, wV, ← F.germ_res iV' w w.2.1, CategoryTheory.types_comp_apply, CategoryTheory.types_comp_apply, e'] /-- The isomorphism between a stalk of the sheafification and the original stalk. diff --git a/Mathlib/Topology/Sheaves/Skyscraper.lean b/Mathlib/Topology/Sheaves/Skyscraper.lean index 9cdd092a962a9..a1bfb6d86c2ef 100644 --- a/Mathlib/Topology/Sheaves/Skyscraper.lean +++ b/Mathlib/Topology/Sheaves/Skyscraper.lean @@ -52,7 +52,7 @@ point, then the skyscraper presheaf `𝓕` with value `A` is defined by `U ↦ A def skyscraperPresheaf : Presheaf C X where obj U := if p₀ ∈ unop U then A else terminal C map {U V} i := - if h : p₀ ∈ unop V then eqToHom <| by dsimp; erw [if_pos h, if_pos (leOfHom i.unop h)] + if h : p₀ ∈ unop V then eqToHom <| by dsimp; rw [if_pos h, if_pos (by simpa using i.unop.le h)] else ((if_neg h).symm.ndrec terminalIsTerminal).from _ map_id U := (em (p₀ ∈ U.unop)).elim (fun h => dif_pos h) fun h => @@ -161,6 +161,12 @@ noncomputable def skyscraperPresheafStalkOfSpecializes [HasColimits C] {y : X} ( (skyscraperPresheaf p₀ A).stalk y ≅ A := colimit.isoColimitCocone ⟨_, skyscraperPresheafCoconeIsColimitOfSpecializes p₀ A h⟩ +@[reassoc (attr := simp)] +lemma germ_skyscraperPresheafStalkOfSpecializes_hom [HasColimits C] {y : X} (h : p₀ ⤳ y) (U hU) : + (skyscraperPresheaf p₀ A).germ U y hU ≫ + (skyscraperPresheafStalkOfSpecializes p₀ A h).hom = eqToHom (if_pos (h.mem_open U.2 hU)) := + colimit.isoColimitCocone_ι_hom _ _ + /-- The cocone at `*` for the stalk functor of `skyscraperPresheaf p₀ A` when `y ∉ closure {p₀}` -/ @[simps] @@ -247,7 +253,7 @@ if `p₀ ∉ U`. def toSkyscraperPresheaf {𝓕 : Presheaf C X} {c : C} (f : 𝓕.stalk p₀ ⟶ c) : 𝓕 ⟶ skyscraperPresheaf p₀ c where app U := - if h : p₀ ∈ U.unop then 𝓕.germ ⟨p₀, h⟩ ≫ f ≫ eqToHom (if_pos h).symm + if h : p₀ ∈ U.unop then 𝓕.germ _ p₀ h ≫ f ≫ eqToHom (if_pos h).symm else ((if_neg h).symm.ndrec terminalIsTerminal).from _ naturality U V inc := by -- Porting note: don't know why original proof fell short of working, add `aesop_cat` finished @@ -256,10 +262,47 @@ def toSkyscraperPresheaf {𝓕 : Presheaf C X} {c : C} (f : 𝓕.stalk p₀ ⟶ by_cases hV : p₀ ∈ V.unop · have hU : p₀ ∈ U.unop := leOfHom inc.unop hV split_ifs - erw [← Category.assoc, 𝓕.germ_res inc.unop, Category.assoc, Category.assoc, eqToHom_trans] + rw [← Category.assoc, 𝓕.germ_res' inc, Category.assoc, Category.assoc, eqToHom_trans] · split_ifs exact ((if_neg hV).symm.ndrec terminalIsTerminal).hom_ext .. +/-- If `f : 𝓕 ⟶ skyscraperPresheaf p₀ c` is a natural transformation, then there is a morphism +`𝓕.stalk p₀ ⟶ c` defined as the morphism from colimit to cocone at `c`. +-/ +def fromStalk {𝓕 : Presheaf C X} {c : C} (f : 𝓕 ⟶ skyscraperPresheaf p₀ c) : 𝓕.stalk p₀ ⟶ c := + let χ : Cocone ((OpenNhds.inclusion p₀).op ⋙ 𝓕) := + Cocone.mk c <| + { app := fun U => f.app ((OpenNhds.inclusion p₀).op.obj U) ≫ eqToHom (if_pos U.unop.2) + naturality := fun U V inc => by + dsimp only [Functor.const_obj_map, Functor.const_obj_obj, Functor.comp_map, + Functor.comp_obj, Functor.op_obj, skyscraperPresheaf_obj] + rw [Category.comp_id, ← Category.assoc, comp_eqToHom_iff, Category.assoc, + eqToHom_trans, f.naturality, skyscraperPresheaf_map] + have hV : p₀ ∈ (OpenNhds.inclusion p₀).obj V.unop := V.unop.2 + simp only [dif_pos hV] } + colimit.desc _ χ + +@[reassoc (attr := simp)] +lemma germ_fromStalk {𝓕 : Presheaf C X} {c : C} (f : 𝓕 ⟶ skyscraperPresheaf p₀ c) (U) (hU) : + 𝓕.germ U p₀ hU ≫ fromStalk p₀ f = f.app (op U) ≫ eqToHom (if_pos hU) := + colimit.ι_desc _ _ + +theorem to_skyscraper_fromStalk {𝓕 : Presheaf C X} {c : C} (f : 𝓕 ⟶ skyscraperPresheaf p₀ c) : + toSkyscraperPresheaf p₀ (fromStalk _ f) = f := by + apply NatTrans.ext + ext U + dsimp + split_ifs with h + · rw [← Category.assoc, germ_fromStalk, Category.assoc, eqToHom_trans, eqToHom_refl, + Category.comp_id] + · exact ((if_neg h).symm.ndrec terminalIsTerminal).hom_ext .. + +theorem fromStalk_to_skyscraper {𝓕 : Presheaf C X} {c : C} (f : 𝓕.stalk p₀ ⟶ c) : + fromStalk p₀ (toSkyscraperPresheaf _ f) = f := by + refine 𝓕.stalk_hom_ext fun U hxU ↦ ?_ + rw [germ_fromStalk, toSkyscraperPresheaf_app, dif_pos hxU, Category.assoc, Category.assoc, + eqToHom_trans, eqToHom_refl, Category.comp_id, Presheaf.germ] + /-- The unit in `Presheaf.stalkFunctor ⊣ skyscraperPresheafFunctor` -/ @[simps] @@ -269,9 +312,8 @@ protected def unit : naturality 𝓕 𝓖 f := by ext U; dsimp 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] - erw [colimit.ι_map]; rfl + · simp only [Category.id_comp, Category.assoc, eqToHom_trans_assoc, eqToHom_refl, + Presheaf.stalkFunctor_map_germ_assoc, Presheaf.stalkFunctor_obj] · apply ((if_neg h).symm.ndrec terminalIsTerminal).hom_ext /-- The counit in `Presheaf.stalkFunctor ⊣ skyscraperPresheafFunctor` @@ -280,14 +322,7 @@ protected def unit : protected def counit : skyscraperPresheafFunctor p₀ ⋙ (Presheaf.stalkFunctor C p₀ : Presheaf C X ⥤ C) ⟶ 𝟭 C where app c := (skyscraperPresheafStalkOfSpecializes p₀ c specializes_rfl).hom - naturality x y f := colimit.hom_ext fun U => by - erw [← Category.assoc, colimit.ι_map, colimit.isoColimitCocone_ι_hom_assoc, - skyscraperPresheafCoconeOfSpecializes_ι_app (h := specializes_rfl), Category.assoc, - colimit.ι_desc, whiskeringLeft_obj_map, whiskerLeft_app, SkyscraperPresheafFunctor.map'_app, - dif_pos U.unop.2, skyscraperPresheafCoconeOfSpecializes_ι_app (h := specializes_rfl), - comp_eqToHom_iff, Category.assoc, eqToHom_comp_iff, ← Category.assoc, eqToHom_trans, - eqToHom_refl, Category.id_comp, comp_eqToHom_iff, Category.assoc, eqToHom_trans, eqToHom_refl, - Category.comp_id, CategoryTheory.Functor.id_map] + naturality x y f := TopCat.Presheaf.stalk_hom_ext _ fun U hxU ↦ by simp [hxU] end StalkSkyscraperPresheafAdjunctionAuxs diff --git a/Mathlib/Topology/Sheaves/Stalks.lean b/Mathlib/Topology/Sheaves/Stalks.lean index d1e8867ba7f1a..74df85eb39c03 100644 --- a/Mathlib/Topology/Sheaves/Stalks.lean +++ b/Mathlib/Topology/Sheaves/Stalks.lean @@ -89,46 +89,76 @@ theorem stalkFunctor_obj (ℱ : X.Presheaf C) (x : X) : (stalkFunctor C x).obj /-- The germ of a section of a presheaf over an open at a point of that open. -/ -def germ (F : X.Presheaf C) {U : Opens X} (x : U) : F.obj (op U) ⟶ stalk F x := - colimit.ι ((OpenNhds.inclusion x.1).op ⋙ F) (op ⟨U, x.2⟩) +def germ (F : X.Presheaf C) (U : Opens X) (x : X) (hx : x ∈ U) : F.obj (op U) ⟶ stalk F x := + colimit.ι ((OpenNhds.inclusion x).op ⋙ F) (op ⟨U, hx⟩) /-- The germ of a global section of a presheaf at a point. -/ def Γgerm (F : X.Presheaf C) (x : X) : F.obj (op ⊤) ⟶ stalk F x := - F.germ ⟨x, show x ∈ ⊤ by trivial⟩ + F.germ ⊤ x True.intro +@[reassoc] +theorem germ_res (F : X.Presheaf C) {U V : Opens X} (i : U ⟶ V) (x : X) (hx : x ∈ U) : + F.map i.op ≫ F.germ U x hx = F.germ V x (i.le hx) := + let i' : (⟨U, hx⟩ : OpenNhds x) ⟶ ⟨V, i.le hx⟩ := i + colimit.w ((OpenNhds.inclusion x).op ⋙ F) i'.op + +/-- A variant of `germ_res` with `op V ⟶ op U` +so that the LHS is more general and simp fires more easier. -/ @[reassoc (attr := simp)] -theorem germ_res (F : X.Presheaf C) {U V : Opens X} (i : U ⟶ V) (x : U) : - F.map i.op ≫ germ F x = germ F (i x : V) := - let i' : (⟨U, x.2⟩ : OpenNhds x.1) ⟶ ⟨V, (i x : V).2⟩ := i - colimit.w ((OpenNhds.inclusion x.1).op ⋙ F) i'.op +theorem germ_res' (F : X.Presheaf C) {U V : Opens X} (i : op V ⟶ op U) (x : X) (hx : x ∈ U) : + F.map i ≫ F.germ U x hx = F.germ V x (i.unop.le hx) := + let i' : (⟨U, hx⟩ : OpenNhds x) ⟶ ⟨V, i.unop.le hx⟩ := i.unop + colimit.w ((OpenNhds.inclusion x).op ⋙ F) i'.op @[reassoc] -lemma map_germ_eq_Γgerm (F : X.Presheaf C) {U : Opens X} {i : U ⟶ ⊤} (x : U) : - F.map i.op ≫ germ F x = Γgerm F (i x) := - germ_res F i x +lemma map_germ_eq_Γgerm (F : X.Presheaf C) {U : Opens X} {i : U ⟶ ⊤} (x : X) (hx : x ∈ U) : + F.map i.op ≫ F.germ U x hx = F.Γgerm x := + germ_res F i x hx + +attribute [local instance] ConcreteCategory.instFunLike in +theorem germ_res_apply (F : X.Presheaf C) + {U V : Opens X} (i : U ⟶ V) (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + F.germ U x hx (F.map i.op s) = F.germ V x (i.le hx) s := by rw [← comp_apply, germ_res] --- Porting note: `@[elementwise]` did not generate the best lemma when applied to `germ_res` attribute [local instance] ConcreteCategory.instFunLike in -theorem germ_res_apply (F : X.Presheaf C) {U V : Opens X} (i : U ⟶ V) (x : U) [ConcreteCategory C] - (s) : germ F x (F.map i.op s) = germ F (i x) s := by rw [← comp_apply, germ_res] +theorem germ_res_apply' (F : X.Presheaf C) + {U V : Opens X} (i : op V ⟶ op U) (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + F.germ U x hx (F.map i s) = F.germ V x (i.unop.le hx) s := by rw [← comp_apply, germ_res'] attribute [local instance] ConcreteCategory.instFunLike in -lemma Γgerm_res_apply (F : X.Presheaf C) {U : Opens X} {i : U ⟶ ⊤} (x : U) [ConcreteCategory C] - (s) : germ F x (F.map i.op s) = Γgerm F x.val s := germ_res_apply F i x s +lemma Γgerm_res_apply (F : X.Presheaf C) + {U : Opens X} {i : U ⟶ ⊤} (x : X) (hx : x ∈ U) [ConcreteCategory C] (s) : + F.germ U x hx (F.map i.op s) = F.Γgerm x s := F.germ_res_apply i x hx s /-- A morphism from the stalk of `F` at `x` to some object `Y` is completely determined by its composition with the `germ` morphisms. -/ @[ext] theorem stalk_hom_ext (F : X.Presheaf C) {x} {Y : C} {f₁ f₂ : F.stalk x ⟶ Y} - (ih : ∀ (U : Opens X) (hxU : x ∈ U), F.germ ⟨x, hxU⟩ ≫ f₁ = F.germ ⟨x, hxU⟩ ≫ f₂) : f₁ = f₂ := + (ih : ∀ (U : Opens X) (hxU : x ∈ U), F.germ U x hxU ≫ f₁ = F.germ U x hxU ≫ f₂) : f₁ = f₂ := colimit.hom_ext fun U => by induction' U using Opposite.rec with U; cases' U with U hxU; exact ih U hxU -@[reassoc (attr := simp), elementwise (attr := simp)] -theorem stalkFunctor_map_germ {F G : X.Presheaf C} (U : Opens X) (x : U) (f : F ⟶ G) : - germ F x ≫ (stalkFunctor C x.1).map f = f.app (op U) ≫ germ G x := - colimit.ι_map (whiskerLeft (OpenNhds.inclusion x.1).op f) (op ⟨U, x.2⟩) +@[reassoc (attr := simp)] +theorem stalkFunctor_map_germ {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) : + F.germ U x hx ≫ (stalkFunctor C x).map f = f.app (op U) ≫ G.germ U x hx := + colimit.ι_map (whiskerLeft (OpenNhds.inclusion x).op f) (op ⟨U, hx⟩) + +attribute [local instance] ConcreteCategory.instFunLike in +theorem stalkFunctor_map_germ_apply [ConcreteCategory C] + {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) (s) : + (stalkFunctor C x).map f (F.germ U x hx s) = G.germ U x hx (f.app (op U) s) := by + rw [← comp_apply, ← stalkFunctor_map_germ] + exact (comp_apply _ _ _).symm + +-- a variant of `stalkFunctor_map_germ_apply` that makes simpNF happy. +attribute [local instance] ConcreteCategory.instFunLike in +@[simp] +theorem stalkFunctor_map_germ_apply' [ConcreteCategory C] + {F G : X.Presheaf C} (U : Opens X) (x : X) (hx : x ∈ U) (f : F ⟶ G) (s) : + DFunLike.coe (F := F.stalk x ⟶ G.stalk x) ((stalkFunctor C x).map f) (F.germ U x hx s) = + G.germ U x hx (f.app (op U) s) := + stalkFunctor_map_germ_apply U x hx f s variable (C) @@ -143,8 +173,8 @@ def stalkPushforward (f : X ⟶ Y) (F : X.Presheaf C) (x : X) : (f _* F).stalk ( @[reassoc (attr := simp), elementwise (attr := simp)] theorem stalkPushforward_germ (f : X ⟶ Y) (F : X.Presheaf C) (U : Opens Y) - (x : (Opens.map f).obj U) : - (f _* F).germ ⟨(f : X → Y) (x : X), x.2⟩ ≫ F.stalkPushforward C f x = F.germ x := by + (x : X) (hx : f x ∈ U) : + (f _* F).germ U (f x) hx ≫ F.stalkPushforward C f x = F.germ ((Opens.map f).obj U) x hx := by simp [germ, stalkPushforward] -- Here are two other potential solutions, suggested by @fpvandoorn at @@ -217,19 +247,19 @@ def stalkPullbackHom (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) : @[reassoc (attr := simp)] lemma germ_stalkPullbackHom (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) (U : Opens Y) (hU : f x ∈ U) : - F.germ ⟨f x, hU⟩ ≫ stalkPullbackHom C f F x = + F.germ U (f x) hU ≫ stalkPullbackHom C f F x = ((pushforwardPullbackAdjunction C f).unit.app F).app _ ≫ - ((pullback C f).obj F).germ ⟨x, show x ∈ (Opens.map f).obj U from hU⟩ := by + ((pullback C f).obj F).germ ((Opens.map f).obj U) x hU := by simp [stalkPullbackHom, germ, stalkFunctor, stalkPushforward] /-- The morphism `(f⁻¹ℱ)(U) ⟶ ℱ_{f(x)}` for some `U ∋ x`. -/ -def germToPullbackStalk (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : U) : - ((pullback C f).obj F).obj (op U) ⟶ F.stalk ((f : X → Y) (x : X)) := +def germToPullbackStalk (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : X) (hx : x ∈ U) : + ((pullback C f).obj F).obj (op U) ⟶ F.stalk (f x) := ((Opens.map f).op.isPointwiseLeftKanExtensionLanUnit F (op U)).desc { pt := F.stalk ((f : X → Y) (x : X)) ι := - { app := fun V => F.germ ⟨((f : X → Y) (x : X)), V.hom.unop.le x.2⟩ - naturality := fun _ _ i => by erw [Category.comp_id]; exact F.germ_res i.left.unop _ } } + { app := fun V => F.germ _ (f x) (V.hom.unop.le hx) + naturality := fun _ _ i => by simp } } variable {C} in @[ext] @@ -248,20 +278,20 @@ lemma pullback_obj_obj_ext {Z : C} {f : X ⟶ Y} {F : Y.Presheaf C} (U : (Opens @[reassoc (attr := simp)] lemma pushforwardPullbackAdjunction_unit_pullback_map_germToPullbackStalk - (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : U) (V : Opens Y) + (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : X) (hx : x ∈ U) (V : Opens Y) (hV : U ≤ (Opens.map f).obj V) : ((pushforwardPullbackAdjunction C f).unit.app F).app (op V) ≫ - ((pullback C f).obj F).map (homOfLE hV).op ≫ germToPullbackStalk C f F U x = - F.germ ⟨f x, hV x.2⟩ := by + ((pullback C f).obj F).map (homOfLE hV).op ≫ germToPullbackStalk C f F U x hx = + F.germ _ (f x) (hV hx) := by simpa [pushforwardPullbackAdjunction] using ((Opens.map f).op.isPointwiseLeftKanExtensionLanUnit F (op U)).fac _ (CostructuredArrow.mk (homOfLE hV).op) @[reassoc (attr := simp)] lemma germToPullbackStalk_stalkPullbackHom - (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : U) : - germToPullbackStalk C f F U x ≫ stalkPullbackHom C f F x = - ((pullback C f).obj F).germ x := by + (f : X ⟶ Y) (F : Y.Presheaf C) (U : Opens X) (x : X) (hx : x ∈ U) : + germToPullbackStalk C f F U x hx ≫ stalkPullbackHom C f F x = + ((pullback C f).obj F).germ _ x hx := by ext V hV dsimp simp only [pushforwardPullbackAdjunction_unit_pullback_map_germToPullbackStalk_assoc, @@ -269,11 +299,11 @@ lemma germToPullbackStalk_stalkPullbackHom @[reassoc (attr := simp)] lemma pushforwardPullbackAdjunction_unit_app_app_germToPullbackStalk - (f : X ⟶ Y) (F : Y.Presheaf C) (V : (Opens Y)ᵒᵖ) (x : (Opens.map f).obj V.unop) : - ((pushforwardPullbackAdjunction C f).unit.app F).app V ≫ germToPullbackStalk C f F _ x = - F.germ ⟨f x, x.2⟩ := by + (f : X ⟶ Y) (F : Y.Presheaf C) (V : (Opens Y)ᵒᵖ) (x : X) (hx : f x ∈ V.unop) : + ((pushforwardPullbackAdjunction C f).unit.app F).app V ≫ germToPullbackStalk C f F _ x hx = + F.germ _ (f x) hx := by simpa using pushforwardPullbackAdjunction_unit_pullback_map_germToPullbackStalk - C f F ((Opens.map f).obj V.unop) x V.unop (by rfl) + C f F ((Opens.map f).obj V.unop) x hx V.unop (by rfl) /-- The morphism `(f⁻¹ℱ)ₓ ⟶ ℱ_{f(x)}`. -/ def stalkPullbackInv (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) : @@ -281,7 +311,7 @@ def stalkPullbackInv (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) : colimit.desc ((OpenNhds.inclusion x).op ⋙ (Presheaf.pullback C f).obj F) { pt := F.stalk (f x) ι := - { app := fun U => F.germToPullbackStalk _ f (unop U).1 ⟨x, (unop U).2⟩ + { app := fun U => F.germToPullbackStalk _ f (unop U).1 x (unop U).2 naturality := fun U V i => by dsimp ext W hW @@ -292,8 +322,8 @@ def stalkPullbackInv (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) : @[reassoc (attr := simp)] lemma germ_stalkPullbackInv (f : X ⟶ Y) (F : Y.Presheaf C) (x : X) (V : Opens X) (hV : x ∈ V) : - ((pullback C f).obj F).germ ⟨x, hV⟩ ≫ stalkPullbackInv C f F x = - F.germToPullbackStalk _ f V ⟨x, hV⟩ := by + ((pullback C f).obj F).germ _ x hV ≫ stalkPullbackInv C f F x = + F.germToPullbackStalk _ f V x hV := by apply colimit.ι_desc /-- The isomorphism `ℱ_{f(x)} ≅ (f⁻¹ℱ)ₓ`. -/ @@ -332,14 +362,12 @@ noncomputable def stalkSpecializes (F : X.Presheaf C) {x y : X} (h : x ⤳ y) : exact colimit.w ((OpenNhds.inclusion x).op ⋙ F) (show V' ⟶ U' from i.unop).op @[reassoc (attr := simp), elementwise nosimp] -theorem germ_stalkSpecializes (F : X.Presheaf C) {U : Opens X} {y : U} {x : X} (h : x ⤳ y) : - F.germ y ≫ F.stalkSpecializes h = F.germ (⟨x, h.mem_open U.isOpen y.prop⟩ : U) := +theorem germ_stalkSpecializes (F : X.Presheaf C) + {U : Opens X} {y : X} (hy : y ∈ U) {x : X} (h : x ⤳ y) : + F.germ U y hy ≫ F.stalkSpecializes h = F.germ U x (h.mem_open U.isOpen hy) := colimit.ι_desc _ _ -@[reassoc, elementwise nosimp] -theorem germ_stalkSpecializes' (F : X.Presheaf C) {U : Opens X} {x y : X} (h : x ⤳ y) - (hy : y ∈ U) : F.germ ⟨y, hy⟩ ≫ F.stalkSpecializes h = F.germ ⟨x, h.mem_open U.isOpen hy⟩ := - colimit.ι_desc _ _ +@[deprecated (since := "2024-07-30")] alias germ_stalkSpecializes' := germ_stalkSpecializes @[simp] theorem stalkSpecializes_refl {C : Type*} [Category C] [Limits.HasColimits C] {X : TopCat} @@ -391,8 +419,8 @@ attribute [local instance] ConcreteCategory.hasCoeToSort ConcreteCategory.instFu theorem germ_ext (F : X.Presheaf C) {U V : Opens X} {x : X} {hxU : x ∈ U} {hxV : x ∈ V} (W : Opens X) (hxW : x ∈ W) (iWU : W ⟶ U) (iWV : W ⟶ V) {sU : F.obj (op U)} {sV : F.obj (op V)} (ih : F.map iWU.op sU = F.map iWV.op sV) : - F.germ ⟨x, hxU⟩ sU = F.germ ⟨x, hxV⟩ sV := by - erw [← F.germ_res iWU ⟨x, hxW⟩, ← F.germ_res iWV ⟨x, hxW⟩, comp_apply, comp_apply, ih] + F.germ _ x hxU sU = F.germ _ x hxV sV := by + rw [← F.germ_res iWU x hxW, ← F.germ_res iWV x hxW, comp_apply, comp_apply, ih] variable [PreservesFilteredColimits (forget C)] @@ -401,7 +429,7 @@ For presheaves valued in a concrete category whose forgetful functor preserves f every element of the stalk is the germ of a section. -/ theorem germ_exist (F : X.Presheaf C) (x : X) (t : (stalk.{v, u} F x : Type v)) : - ∃ (U : Opens X) (m : x ∈ U) (s : F.obj (op U)), F.germ ⟨x, m⟩ s = t := by + ∃ (U : Opens X) (m : x ∈ U) (s : F.obj (op U)), F.germ _ x m s = t := by obtain ⟨U, s, e⟩ := Types.jointly_surjective.{v, v} _ (isColimitOfPreserves (forget C) (colimit.isColimit _)) t revert s e @@ -411,7 +439,7 @@ theorem germ_exist (F : X.Presheaf C) (x : X) (t : (stalk.{v, u} F x : Type v)) exact ⟨V, m, s, e⟩ theorem germ_eq (F : X.Presheaf C) {U V : Opens X} (x : X) (mU : x ∈ U) (mV : x ∈ V) - (s : F.obj (op U)) (t : F.obj (op V)) (h : germ F ⟨x, mU⟩ s = germ F ⟨x, mV⟩ t) : + (s : F.obj (op U)) (t : F.obj (op V)) (h : F.germ U x mU s = F.germ V x mV t) : ∃ (W : Opens X) (_m : x ∈ W) (iU : W ⟶ U) (iV : W ⟶ V), F.map iU.op s = F.map iV.op t := by obtain ⟨W, iU, iV, e⟩ := (Types.FilteredColimit.isColimit_eq_iff.{v, v} _ @@ -423,13 +451,12 @@ theorem stalkFunctor_map_injective_of_app_injective {F G : Presheaf C X} (f : F Function.Injective ((stalkFunctor C x).map f) := fun s t hst => by rcases germ_exist F x s with ⟨U₁, hxU₁, s, rfl⟩ rcases germ_exist F x t with ⟨U₂, hxU₂, t, rfl⟩ - erw [stalkFunctor_map_germ_apply _ ⟨x, _⟩] at hst - erw [stalkFunctor_map_germ_apply _ ⟨x, _⟩] at hst + rw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply] at hst obtain ⟨W, hxW, iWU₁, iWU₂, heq⟩ := G.germ_eq x hxU₁ hxU₂ _ _ hst rw [← comp_apply, ← comp_apply, ← f.naturality, ← f.naturality, comp_apply, comp_apply] at heq replace heq := h W heq - convert congr_arg (F.germ ⟨x, hxW⟩) heq using 1 - exacts [(F.germ_res_apply iWU₁ ⟨x, hxW⟩ s).symm, (F.germ_res_apply iWU₂ ⟨x, hxW⟩ t).symm] + convert congr_arg (F.germ _ x hxW) heq using 1 + exacts [(F.germ_res_apply iWU₁ x hxW s).symm, (F.germ_res_apply iWU₂ x hxW t).symm] variable [HasLimits C] [PreservesLimits (forget C)] [(forget C).ReflectsIsomorphisms] @@ -437,10 +464,10 @@ variable [HasLimits C] [PreservesLimits (forget C)] [(forget C).ReflectsIsomorph preserves limits and filtered colimits. Then two sections who agree on every stalk must be equal. -/ theorem section_ext (F : Sheaf C X) (U : Opens X) (s t : F.1.obj (op U)) - (h : ∀ x : U, F.presheaf.germ x s = F.presheaf.germ x t) : s = t := by + (h : ∀ (x : X) (hx : x ∈ U), F.presheaf.germ U x hx s = F.presheaf.germ U x hx t) : s = t := by -- We use `germ_eq` and the axiom of choice, to pick for every point `x` a neighbourhood -- `V x`, such that the restrictions of `s` and `t` to `V x` coincide. - choose V m i₁ i₂ heq using fun x : U => F.presheaf.germ_eq x.1 x.2 x.2 s t (h x) + choose V m i₁ i₂ heq using fun x : U => F.presheaf.germ_eq x.1 x.2 x.2 s t (h x.1 x.2) -- Since `F` is a sheaf, we can prove the equality locally, if we can show that these -- neighborhoods form a cover of `U`. apply F.eq_of_locally_eq' V U i₁ @@ -456,16 +483,16 @@ imply surjectivity of the components of a sheaf morphism. However it does imply is an epi, but this fact is not yet formalized. -/ theorem app_injective_of_stalkFunctor_map_injective {F : Sheaf C X} {G : Presheaf C X} (f : F.1 ⟶ G) - (U : Opens X) (h : ∀ x : U, Function.Injective ((stalkFunctor C x.val).map f)) : + (U : Opens X) (h : ∀ x ∈ U, Function.Injective ((stalkFunctor C x).map f)) : Function.Injective (f.app (op U)) := fun s t hst => - section_ext F _ _ _ fun x => - h x <| by erw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply, hst] + section_ext F _ _ _ fun x hx => + h x hx <| by rw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply, hst] theorem app_injective_iff_stalkFunctor_map_injective {F : Sheaf C X} {G : Presheaf C X} (f : F.1 ⟶ G) : (∀ x : X, Function.Injective ((stalkFunctor C x).map f)) ↔ ∀ U : Opens X, Function.Injective (f.app (op U)) := - ⟨fun h U => app_injective_of_stalkFunctor_map_injective f U fun x => h x.1, + ⟨fun h U => app_injective_of_stalkFunctor_map_injective f U fun x _ => h x, stalkFunctor_map_injective_of_app_injective f⟩ instance stalkFunctor_preserves_mono (x : X) : @@ -489,7 +516,7 @@ theorem mono_of_stalk_mono {F G : Sheaf C X} (f : F ⟶ G) [∀ x, Mono <| (stal (Sheaf.Hom.mono_iff_presheaf_mono _ _ _).mpr <| (NatTrans.mono_iff_mono_app _).mpr fun U => (ConcreteCategory.mono_iff_injective_of_preservesPullback _).mpr <| - app_injective_of_stalkFunctor_map_injective f.1 U.unop fun ⟨_x, _hx⟩ => + app_injective_of_stalkFunctor_map_injective f.1 U.unop fun _x _hx => (ConcreteCategory.mono_iff_injective_of_preservesPullback _).mp <| inferInstance theorem mono_iff_stalk_mono {F G : Sheaf C X} (f : F ⟶ G) : @@ -501,10 +528,13 @@ We claim that it suffices to find preimages *locally*. That is, for each `x : U` a neighborhood `V ≤ U` and a section `s : F.obj (op V))` such that `f.app (op V) s` and `t` agree on `V`. -/ theorem app_surjective_of_injective_of_locally_surjective {F G : Sheaf C X} (f : F ⟶ G) - (U : Opens X) (hinj : ∀ x : U, Function.Injective ((stalkFunctor C x.1).map f.1)) - (hsurj : ∀ (t) (x : U), ∃ (V : Opens X) (_ : x.1 ∈ V) (iVU : V ⟶ U) (s : F.1.obj (op V)), + (U : Opens X) (hinj : ∀ x ∈ U, Function.Injective ((stalkFunctor C x).map f.1)) + (hsurj : ∀ (t x) (_ : x ∈ U), ∃ (V : Opens X) (_ : x ∈ V) (iVU : V ⟶ U) (s : F.1.obj (op V)), f.1.app (op V) s = G.1.map iVU.op t) : Function.Surjective (f.1.app (op U)) := by + conv at hsurj => + enter [t] + rw [Subtype.forall' (p := (· ∈ U))] intro t -- We use the axiom of choice to pick around each point `x` an open neighborhood `V` and a -- preimage under `f` on `V`. @@ -525,36 +555,36 @@ theorem app_surjective_of_injective_of_locally_surjective {F G : Sheaf C X} (f : -- What's left to show here is that the sections `sf` are compatible, i.e. they agree on -- the intersections `V x ⊓ V y`. We prove this by showing that all germs are equal. apply section_ext - intro z + intro z hz -- Here, we need to use injectivity of the stalk maps. - apply hinj ⟨z, (iVU x).le ((inf_le_left : V x ⊓ V y ≤ V x) z.2)⟩ + apply hinj z ((iVU x).le ((inf_le_left : V x ⊓ V y ≤ V x) hz)) dsimp only - erw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply] + rw [stalkFunctor_map_germ_apply, stalkFunctor_map_germ_apply] simp_rw [← comp_apply, f.1.naturality, comp_apply, heq, ← comp_apply, ← G.1.map_comp] rfl theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X) - (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) : + (h : ∀ x ∈ U, Function.Bijective ((stalkFunctor C x).map f.1)) : Function.Surjective (f.1.app (op U)) := by - refine app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => ?_ + refine app_surjective_of_injective_of_locally_surjective f U (And.left <| h · ·) fun t x hx => ?_ -- Now we need to prove our initial claim: That we can find preimages of `t` locally. -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x` - obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t) + obtain ⟨s₀, hs₀⟩ := (h x hx).2 (G.presheaf.germ U x hx t) -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁` - obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀ + obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x s₀ subst hs₁; rename' hs₀ => hs₁ - erw [stalkFunctor_map_germ_apply V₁ ⟨x.1, hxV₁⟩ f.1 s₁] at hs₁ + rw [stalkFunctor_map_germ_apply V₁ x hxV₁ f.1 s₁] at hs₁ -- Now, the germ of `f.app (op V₁) s₁` equals the germ of `t`, hence they must coincide on -- some open neighborhood `V₂`. - obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x.1 hxV₁ x.2 _ _ hs₁ + obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x hxV₁ hx _ _ hs₁ -- The restriction of `s₁` to that neighborhood is our desired local preimage. use V₂, hxV₂, iV₂U, F.1.map iV₂V₁.op s₁ rw [← comp_apply, f.1.naturality, comp_apply, heq] theorem app_bijective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X) - (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) : + (h : ∀ x ∈ U, Function.Bijective ((stalkFunctor C x).map f.1)) : Function.Bijective (f.1.app (op U)) := - ⟨app_injective_of_stalkFunctor_map_injective f.1 U fun x => (h x).1, + ⟨app_injective_of_stalkFunctor_map_injective f.1 U fun x hx => (h x hx).1, app_surjective_of_stalkFunctor_map_bijective f U h⟩ theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X) @@ -565,9 +595,9 @@ theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : O exact isIso_of_reflects_iso (f.1.app (op U)) (forget C) rw [isIso_iff_bijective] apply app_bijective_of_stalkFunctor_map_bijective - intro x + intro x hx apply (isIso_iff_bijective _).mp - exact Functor.map_isIso (forget C) ((stalkFunctor C x.1).map f.1) + exact Functor.map_isIso (forget C) ((stalkFunctor C (⟨x, hx⟩ : U).1).map f.1) -- Making this an instance would cause a loop in typeclass resolution with `Functor.map_isIso` /-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects @@ -599,11 +629,11 @@ end Concrete instance algebra_section_stalk (F : X.Presheaf CommRingCat) {U : Opens X} (x : U) : Algebra (F.obj <| op U) (F.stalk x) := - (F.germ x).toAlgebra + (F.germ U x.1 x.2).toAlgebra @[simp] theorem stalk_open_algebraMap {X : TopCat} (F : X.Presheaf CommRingCat) {U : Opens X} (x : U) : - algebraMap (F.obj <| op U) (F.stalk x) = F.germ x := + algebraMap (F.obj <| op U) (F.stalk x) = F.germ U x.1 x.2 := rfl end TopCat.Presheaf diff --git a/Mathlib/Topology/Specialization.lean b/Mathlib/Topology/Specialization.lean index 874083b9a9983..1c7ce45b4bb4b 100644 --- a/Mathlib/Topology/Specialization.lean +++ b/Mathlib/Topology/Specialization.lean @@ -5,7 +5,7 @@ Authors: Yaël Dillies -/ import Mathlib.Order.Category.Preord import Mathlib.Topology.Category.TopCat.Basic -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Topology.Separation import Mathlib.Topology.Order.UpperLowerSetTopology @@ -63,7 +63,7 @@ instance instPartialOrder [T0Space α] : PartialOrder (Specialization α) := spe orders. -/ def map (f : C(α, β)) : Specialization α →o Specialization β where toFun := toEquiv ∘ f ∘ ofEquiv - monotone' := f.continuous.specialization_monotone + monotone' := (map_continuous f).specialization_monotone @[simp] lemma map_id : map (ContinuousMap.id α) = OrderHom.id := rfl @[simp] lemma map_comp (g : C(β, γ)) (f : C(α, β)) : map (g.comp f) = (map g).comp (map f) := rfl diff --git a/Mathlib/Topology/Spectral/Hom.lean b/Mathlib/Topology/Spectral/Hom.lean index 078b9875e0dbe..30c704a2d0504 100644 --- a/Mathlib/Topology/Spectral/Hom.lean +++ b/Mathlib/Topology/Spectral/Hom.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.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic /-! # Spectral maps diff --git a/Mathlib/Topology/StoneCech.lean b/Mathlib/Topology/StoneCech.lean index 34a2c255120e0..3beed85e1b698 100644 --- a/Mathlib/Topology/StoneCech.lean +++ b/Mathlib/Topology/StoneCech.lean @@ -148,15 +148,18 @@ theorem induced_topology_pure : simp /-- `pure : α → Ultrafilter α` defines a dense inducing of `α` in `Ultrafilter α`. -/ -theorem denseInducing_pure : @DenseInducing _ _ ⊥ _ (pure : α → Ultrafilter α) := +theorem isDenseInducing_pure : @IsDenseInducing _ _ ⊥ _ (pure : α → Ultrafilter α) := letI : TopologicalSpace α := ⊥ ⟨⟨induced_topology_pure.symm⟩, denseRange_pure⟩ -- The following refined version will never be used /-- `pure : α → Ultrafilter α` defines a dense embedding of `α` in `Ultrafilter α`. -/ -theorem denseEmbedding_pure : @DenseEmbedding _ _ ⊥ _ (pure : α → Ultrafilter α) := +theorem isDenseEmbedding_pure : @IsDenseEmbedding _ _ ⊥ _ (pure : α → Ultrafilter α) := letI : TopologicalSpace α := ⊥ - { denseInducing_pure with inj := ultrafilter_pure_injective } + { isDenseInducing_pure with inj := ultrafilter_pure_injective } + +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_pure := isDenseEmbedding_pure end Embedding @@ -166,21 +169,21 @@ section Extension unique extension to a continuous function `Ultrafilter α → γ`. We already know it must be unique because `α → Ultrafilter α` is a dense embedding and `γ` is Hausdorff. For existence, we will invoke - `DenseInducing.continuous_extend`. -/ + `IsDenseInducing.continuous_extend`. -/ variable {γ : Type*} [TopologicalSpace γ] /-- The extension of a function `α → γ` to a function `Ultrafilter α → γ`. When `γ` is a compact Hausdorff space it will be continuous. -/ def Ultrafilter.extend (f : α → γ) : Ultrafilter α → γ := letI : TopologicalSpace α := ⊥ - denseInducing_pure.extend f + isDenseInducing_pure.extend f variable [T2Space γ] theorem ultrafilter_extend_extends (f : α → γ) : Ultrafilter.extend f ∘ pure = f := by letI : TopologicalSpace α := ⊥ haveI : DiscreteTopology α := ⟨rfl⟩ - exact funext (denseInducing_pure.extend_eq continuous_of_discreteTopology) + exact funext (isDenseInducing_pure.extend_eq continuous_of_discreteTopology) variable [CompactSpace γ] @@ -191,7 +194,7 @@ theorem continuous_ultrafilter_extend (f : α → γ) : Continuous (Ultrafilter. isCompact_univ.ultrafilter_le_nhds (b.map f) (by rw [le_principal_iff]; exact univ_mem) ⟨c, le_trans (map_mono (ultrafilter_comap_pure_nhds _)) h'⟩ let _ : TopologicalSpace α := ⊥ - exact denseInducing_pure.continuous_extend h + exact isDenseInducing_pure.continuous_extend h /-- The value of `Ultrafilter.extend f` on an ultrafilter `b` is the unique limit of the ultrafilter `b.map f` in `γ`. -/ @@ -210,7 +213,7 @@ theorem ultrafilter_extend_eq_iff {f : α → γ} {b : Ultrafilter α} {c : γ} exact le_rfl, fun h ↦ let _ : TopologicalSpace α := ⊥ - denseInducing_pure.extend_eq_of_tendsto + isDenseInducing_pure.extend_eq_of_tendsto (le_trans (map_mono (ultrafilter_comap_pure_nhds _)) h)⟩ end Extension diff --git a/Mathlib/Topology/Support.lean b/Mathlib/Topology/Support.lean index 8f8bcb0d14606..c0f19ee3e63a7 100644 --- a/Mathlib/Topology/Support.lean +++ b/Mathlib/Topology/Support.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Floris van Doorn, Patrick Massot -/ import Mathlib.Algebra.GroupWithZero.Indicator +import Mathlib.Algebra.Order.Group.Unbundled.Abs import Mathlib.Algebra.Module.Basic import Mathlib.Topology.Separation @@ -31,7 +32,7 @@ Furthermore, we say that `f` has compact support if the topological support of ` open Function Set Filter Topology -variable {X α α' β γ δ M E R : Type*} +variable {X α α' β γ δ M R : Type*} section One @@ -97,9 +98,9 @@ theorem mulTSupport_mul [TopologicalSpace X] [Monoid α] {f g : X → α} : section -variable [TopologicalSpace α] [TopologicalSpace α'] -variable [One β] [One γ] [One δ] -variable {g : β → γ} {f : α → β} {f₂ : α → γ} {m : β → γ → δ} {x : α} +variable [TopologicalSpace α] +variable [One β] +variable {f : α → β} {x : α} @[to_additive] theorem not_mem_mulTSupport_iff_eventuallyEq : x ∉ mulTSupport f ↔ f =ᶠ[𝓝 x] 1 := by @@ -118,7 +119,7 @@ end section CompactSupport variable [TopologicalSpace α] [TopologicalSpace α'] variable [One β] [One γ] [One δ] -variable {g : β → γ} {f : α → β} {f₂ : α → γ} {m : β → γ → δ} {x : α} +variable {g : β → γ} {f : α → β} {f₂ : α → γ} {m : β → γ → δ} /-- 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 @@ -293,7 +294,7 @@ section CompactSupport2 section Monoid variable [TopologicalSpace α] [MulOneClass β] -variable {f f' : α → β} {x : α} +variable {f f' : α → β} @[to_additive] theorem HasCompactMulSupport.mul (hf : HasCompactMulSupport f) (hf' : HasCompactMulSupport f') : @@ -319,7 +320,7 @@ end DivisionMonoid section SMulZeroClass variable [TopologicalSpace α] [Zero M] [SMulZeroClass R M] -variable {f : α → R} {f' : α → M} {x : α} +variable {f : α → R} {f' : α → M} theorem HasCompactSupport.smul_left (hf : HasCompactSupport f') : HasCompactSupport (f • f') := by rw [hasCompactSupport_iff_eventuallyEq] at hf ⊢ @@ -330,7 +331,7 @@ end SMulZeroClass section SMulWithZero variable [TopologicalSpace α] [Zero R] [Zero M] [SMulWithZero R M] -variable {f : α → R} {f' : α → M} {x : α} +variable {f : α → R} {f' : α → M} theorem HasCompactSupport.smul_right (hf : HasCompactSupport f) : HasCompactSupport (f • f') := by rw [hasCompactSupport_iff_eventuallyEq] at hf ⊢ @@ -344,7 +345,7 @@ end SMulWithZero section MulZeroClass variable [TopologicalSpace α] [MulZeroClass β] -variable {f f' : α → β} {x : α} +variable {f f' : α → β} theorem HasCompactSupport.mul_right (hf : HasCompactSupport f) : HasCompactSupport (f * f') := by rw [hasCompactSupport_iff_eventuallyEq] at hf ⊢ @@ -358,7 +359,7 @@ end MulZeroClass section OrderedAddGroup -variable {α β : Type*} [TopologicalSpace α] [AddGroup β] [Lattice β] +variable [TopologicalSpace α] [AddGroup β] [Lattice β] [CovariantClass β β (· + ·) (· ≤ ·)] protected theorem HasCompactSupport.abs {f : α → β} (hf : HasCompactSupport f) : diff --git a/Mathlib/Topology/TietzeExtension.lean b/Mathlib/Topology/TietzeExtension.lean index b1e175559e9fd..c707446315731 100644 --- a/Mathlib/Topology/TietzeExtension.lean +++ b/Mathlib/Topology/TietzeExtension.lean @@ -126,9 +126,9 @@ instance Prod.instTietzeExtension {Y : Type v} {Z : Type w} [TopologicalSpace Y] obtain ⟨g₂, hg₂⟩ := (ContinuousMap.snd.comp f).exists_restrict_eq hs exact ⟨g₁.prodMk g₂, by ext1 x; congrm(($(hg₁) x), $(hg₂) x)⟩ -instance Unique.instTietzeExtension {Y : Type v} [TopologicalSpace Y] [Unique Y] : - TietzeExtension.{u, v} Y where - exists_restrict_eq' _ _ f := ⟨.const _ default, by ext; subsingleton⟩ +instance Unique.instTietzeExtension {Y : Type v} [TopologicalSpace Y] + [Nonempty Y] [Subsingleton Y] : TietzeExtension.{u, v} Y where + exists_restrict_eq' _ _ f := ‹Nonempty Y›.elim fun y ↦ ⟨.const _ y, by ext; subsingleton⟩ /-- Any retract of a `TietzeExtension` space is one itself. -/ theorem TietzeExtension.of_retract {Y : Type v} {Z : Type w} [TopologicalSpace Y] diff --git a/Mathlib/Topology/UniformSpace/AbsoluteValue.lean b/Mathlib/Topology/UniformSpace/AbsoluteValue.lean index fb21530f3f80a..55efcadaf7133 100644 --- a/Mathlib/Topology/UniformSpace/AbsoluteValue.lean +++ b/Mathlib/Topology/UniformSpace/AbsoluteValue.lean @@ -5,7 +5,7 @@ Authors: Patrick Massot -/ import Mathlib.Algebra.Order.AbsoluteValue import Mathlib.Algebra.Order.Field.Basic -import Mathlib.Topology.UniformSpace.Basic +import Mathlib.Topology.UniformSpace.OfFun /-! # Uniform structure induced by an absolute value diff --git a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean index 903552b0c52dd..ce9024be56637 100644 --- a/Mathlib/Topology/UniformSpace/AbstractCompletion.lean +++ b/Mathlib/Topology/UniformSpace/AbstractCompletion.lean @@ -66,7 +66,7 @@ structure AbstractCompletion (α : Type u) [UniformSpace α] where /-- The completion is a T₀ space. -/ separation : T0Space space /-- The map into the completion is uniform-inducing. -/ - uniformInducing : UniformInducing coe + isUniformInducing : IsUniformInducing coe /-- The map into the completion has dense range. -/ dense : DenseRange coe @@ -81,18 +81,20 @@ local notation "hatα" => pkg.space local notation "ι" => pkg.coe +@[deprecated (since := "2024-10-08")] alias uniformInducing := isUniformInducing + /-- If `α` is complete, then it is an abstract completion of itself. -/ def ofComplete [T0Space α] [CompleteSpace α] : AbstractCompletion α := - mk α id inferInstance inferInstance inferInstance uniformInducing_id denseRange_id + mk α id inferInstance inferInstance inferInstance .id denseRange_id theorem closure_range : closure (range ι) = univ := pkg.dense.closure_range -theorem denseInducing : DenseInducing ι := - ⟨pkg.uniformInducing.inducing, pkg.dense⟩ +theorem isDenseInducing : IsDenseInducing ι := + ⟨pkg.isUniformInducing.inducing, pkg.dense⟩ theorem uniformContinuous_coe : UniformContinuous ι := - UniformInducing.uniformContinuous pkg.uniformInducing + IsUniformInducing.uniformContinuous pkg.isUniformInducing theorem continuous_coe : Continuous ι := pkg.uniformContinuous_coe.continuous @@ -114,23 +116,23 @@ section Extend /-- Extension of maps to completions -/ protected def extend (f : α → β) : hatα → β := - if UniformContinuous f then pkg.denseInducing.extend f else fun x => f (pkg.dense.some x) + if UniformContinuous f then pkg.isDenseInducing.extend f else fun x => f (pkg.dense.some x) variable {f : α → β} -theorem extend_def (hf : UniformContinuous f) : pkg.extend f = pkg.denseInducing.extend f := +theorem extend_def (hf : UniformContinuous f) : pkg.extend f = pkg.isDenseInducing.extend f := if_pos hf theorem extend_coe [T2Space β] (hf : UniformContinuous f) (a : α) : (pkg.extend f) (ι a) = f a := by rw [pkg.extend_def hf] - exact pkg.denseInducing.extend_eq hf.continuous a + exact pkg.isDenseInducing.extend_eq hf.continuous a variable [CompleteSpace β] theorem uniformContinuous_extend : UniformContinuous (pkg.extend f) := by by_cases hf : UniformContinuous f · rw [pkg.extend_def hf] - exact uniformContinuous_uniformly_extend pkg.uniformInducing pkg.dense hf + exact uniformContinuous_uniformly_extend pkg.isUniformInducing pkg.dense hf · change UniformContinuous (ite _ _ _) rw [if_neg hf] exact uniformContinuous_of_const fun a b => by congr 1 @@ -276,17 +278,17 @@ theorem compare_comp_eq_compare (γ : Type*) [TopologicalSpace γ] letI := pkg.uniformStruct.toTopologicalSpace letI := pkg'.uniformStruct.toTopologicalSpace (∀ a : pkg.space, - Filter.Tendsto f (Filter.comap pkg.coe (𝓝 a)) (𝓝 ((pkg.denseInducing.extend f) a))) → - pkg.denseInducing.extend f ∘ pkg'.compare pkg = pkg'.denseInducing.extend f := by + Filter.Tendsto f (Filter.comap pkg.coe (𝓝 a)) (𝓝 ((pkg.isDenseInducing.extend f) a))) → + pkg.isDenseInducing.extend f ∘ pkg'.compare pkg = pkg'.isDenseInducing.extend f := by let _ := pkg'.uniformStruct let _ := pkg.uniformStruct intro h - have (x : α) : (pkg.denseInducing.extend f ∘ pkg'.compare pkg) (pkg'.coe x) = f x := by - simp only [Function.comp_apply, compare_coe, DenseInducing.extend_eq _ cont_f, implies_true] - apply (DenseInducing.extend_unique (AbstractCompletion.denseInducing _) this + have (x : α) : (pkg.isDenseInducing.extend f ∘ pkg'.compare pkg) (pkg'.coe x) = f x := by + simp only [Function.comp_apply, compare_coe, IsDenseInducing.extend_eq _ cont_f, implies_true] + apply (IsDenseInducing.extend_unique (AbstractCompletion.isDenseInducing _) this (Continuous.comp _ (uniformContinuous_compare pkg' pkg).continuous )).symm - apply DenseInducing.continuous_extend - exact fun a ↦ ⟨(pkg.denseInducing.extend f) a, h a⟩ + apply IsDenseInducing.continuous_extend + exact fun a ↦ ⟨(pkg.isDenseInducing.extend f) a, h a⟩ end Compare @@ -305,8 +307,8 @@ protected def prod : AbstractCompletion (α × β) where uniformStruct := inferInstance complete := inferInstance separation := inferInstance - uniformInducing := UniformInducing.prod pkg.uniformInducing pkg'.uniformInducing - dense := DenseRange.prod_map pkg.dense pkg'.dense + isUniformInducing := IsUniformInducing.prod pkg.isUniformInducing pkg'.isUniformInducing + dense := pkg.dense.prodMap pkg'.dense end Prod diff --git a/Mathlib/Topology/UniformSpace/Ascoli.lean b/Mathlib/Topology/UniformSpace/Ascoli.lean index 75e7105788ec2..351606b63c56c 100644 --- a/Mathlib/Topology/UniformSpace/Ascoli.lean +++ b/Mathlib/Topology/UniformSpace/Ascoli.lean @@ -20,14 +20,14 @@ a family of compact subsets of `X`, and `α` is a uniform space. convergence coincide on equicontinuous subsets. This is the key fact that makes equicontinuity important in functional analysis. We state various versions of it: - as an equality of `UniformSpace`s: `Equicontinuous.comap_uniformFun_eq` - - in terms of `UniformInducing`: `Equicontinuous.uniformInducing_uniformFun_iff_pi` + - in terms of `IsUniformInducing`: `Equicontinuous.isUniformInducing_uniformFun_iff_pi` - in terms of `Inducing`: `Equicontinuous.inducing_uniformFun_iff_pi` - in terms of convergence along a filter: `Equicontinuous.tendsto_uniformFun_iff_pi` * As a consequence, if `𝔖` is a family of compact subsets of `X`, then the uniform structures of uniform convergence on `𝔖` and pointwise convergence on `⋃₀ 𝔖` coincide on equicontinuous subsets. Again, we prove multiple variations: - as an equality of `UniformSpace`s: `EquicontinuousOn.comap_uniformOnFun_eq` - - in terms of `UniformInducing`: `EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi'` + - in terms of `IsUniformInducing`: `EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi'` - in terms of `Inducing`: `EquicontinuousOn.inducing_uniformOnFun_iff_pi'` - in terms of convergence along a filter: `EquicontinuousOn.tendsto_uniformOnFun_iff_pi'` * The **Arzela-Ascoli theorem** follows from the previous fact and Tykhonov's theorem. @@ -70,8 +70,7 @@ equicontinuity, uniform convergence, ascoli open Set Filter Uniformity Topology Function UniformConvergence -variable {ι X Y α β : Type*} [TopologicalSpace X] [UniformSpace α] [UniformSpace β] -variable {F : ι → X → α} {G : ι → β → α} +variable {ι X α : Type*} [TopologicalSpace X] [UniformSpace α] {F : ι → X → α} /-- Let `X` be a compact topological space, `α` a uniform space, and `F : ι → (X → α)` an equicontinuous family. Then, the uniform structures of uniform convergence and pointwise @@ -80,7 +79,7 @@ convergence induce the same uniform structure on `ι`. In other words, pointwise convergence and uniform convergence coincide on an equicontinuous subset of `X → α`. -Consider using `Equicontinuous.uniformInducing_uniformFun_iff_pi` and +Consider using `Equicontinuous.isUniformInducing_uniformFun_iff_pi` and `Equicontinuous.inducing_uniformFun_iff_pi` instead, to avoid rewriting instances. -/ theorem Equicontinuous.comap_uniformFun_eq [CompactSpace X] (F_eqcont : Equicontinuous F) : (UniformFun.uniformSpace X α).comap F = @@ -131,15 +130,19 @@ convergence induce the same uniform structure on `ι`. In other words, pointwise convergence and uniform convergence coincide on an equicontinuous subset of `X → α`. -This is a version of `Equicontinuous.comap_uniformFun_eq` stated in terms of `UniformInducing` +This is a version of `Equicontinuous.comap_uniformFun_eq` stated in terms of `IsUniformInducing` for convenuence. -/ -lemma Equicontinuous.uniformInducing_uniformFun_iff_pi [UniformSpace ι] [CompactSpace X] +lemma Equicontinuous.isUniformInducing_uniformFun_iff_pi [UniformSpace ι] [CompactSpace X] (F_eqcont : Equicontinuous F) : - UniformInducing (UniformFun.ofFun ∘ F) ↔ UniformInducing F := by - rw [uniformInducing_iff_uniformSpace, uniformInducing_iff_uniformSpace, + IsUniformInducing (UniformFun.ofFun ∘ F) ↔ IsUniformInducing F := by + rw [isUniformInducing_iff_uniformSpace, isUniformInducing_iff_uniformSpace, ← F_eqcont.comap_uniformFun_eq] rfl +@[deprecated (since := "2024-10-05")] +alias Equicontinuous.uniformInducing_uniformFun_iff_pi := + Equicontinuous.isUniformInducing_uniformFun_iff_pi + /-- Let `X` be a compact topological space, `α` a uniform space, and `F : ι → (X → α)` an equicontinuous family. Then, the topologies of uniform convergence and pointwise convergence induce the same topology on `ι`. @@ -206,7 +209,7 @@ uniform structure on `ι`. In particular, pointwise convergence and compact convergence coincide on an equicontinuous subset of `X → α`. -Consider using `EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi'` and +Consider using `EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi'` and `EquicontinuousOn.inducing_uniformOnFun_iff_pi'` instead to avoid rewriting instances, as well as their unprimed versions in case `𝔖` covers `X`. -/ theorem EquicontinuousOn.comap_uniformOnFun_eq {𝔖 : Set (Set X)} (𝔖_compact : ∀ K ∈ 𝔖, IsCompact K) @@ -247,37 +250,45 @@ uniform structure on `ι`. In particular, pointwise convergence and compact convergence coincide on an equicontinuous subset of `X → α`. -This is a version of `EquicontinuousOn.comap_uniformOnFun_eq` stated in terms of `UniformInducing` +This is a version of `EquicontinuousOn.comap_uniformOnFun_eq` stated in terms of `IsUniformInducing` for convenuence. -/ -lemma EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi' [UniformSpace ι] +lemma EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi' [UniformSpace ι] {𝔖 : Set (Set X)} (𝔖_compact : ∀ K ∈ 𝔖, IsCompact K) (F_eqcont : ∀ K ∈ 𝔖, EquicontinuousOn F K) : - UniformInducing (UniformOnFun.ofFun 𝔖 ∘ F) ↔ - UniformInducing ((⋃₀ 𝔖).restrict ∘ F) := by - rw [uniformInducing_iff_uniformSpace, uniformInducing_iff_uniformSpace, + IsUniformInducing (UniformOnFun.ofFun 𝔖 ∘ F) ↔ + IsUniformInducing ((⋃₀ 𝔖).restrict ∘ F) := by + rw [isUniformInducing_iff_uniformSpace, isUniformInducing_iff_uniformSpace, ← EquicontinuousOn.comap_uniformOnFun_eq 𝔖_compact F_eqcont] rfl +@[deprecated (since := "2024-10-05")] +alias EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi' := + EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi' + /-- Let `X` be a topological space, `𝔖` a covering of `X` by compact subsets, `α` a uniform space, and `F : ι → (X → α)` a family which is equicontinuous on each `K ∈ 𝔖`. Then, the uniform structures of uniform convergence on `𝔖` and pointwise convergence induce the same uniform structure on `ι`. -This is a specialization of `EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi'` to +This is a specialization of `EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi'` to the case where `𝔖` covers `X`. -/ -lemma EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi [UniformSpace ι] +lemma EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi [UniformSpace ι] {𝔖 : Set (Set X)} (𝔖_covers : ⋃₀ 𝔖 = univ) (𝔖_compact : ∀ K ∈ 𝔖, IsCompact K) (F_eqcont : ∀ K ∈ 𝔖, EquicontinuousOn F K) : - UniformInducing (UniformOnFun.ofFun 𝔖 ∘ F) ↔ - UniformInducing F := by + IsUniformInducing (UniformOnFun.ofFun 𝔖 ∘ F) ↔ + IsUniformInducing F := by rw [eq_univ_iff_forall] at 𝔖_covers -- This obviously follows from the previous lemma, we formalize it by going through the -- isomorphism of uniform spaces between `(⋃₀ 𝔖) → α` and `X → α`. let φ : ((⋃₀ 𝔖) → α) ≃ᵤ (X → α) := UniformEquiv.piCongrLeft (β := fun _ ↦ α) (Equiv.subtypeUnivEquiv 𝔖_covers) - rw [EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi' 𝔖_compact F_eqcont, + rw [EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi' 𝔖_compact F_eqcont, show restrict (⋃₀ 𝔖) ∘ F = φ.symm ∘ F by rfl] - exact ⟨fun H ↦ φ.uniformInducing.comp H, fun H ↦ φ.symm.uniformInducing.comp H⟩ + exact ⟨fun H ↦ φ.isUniformInducing.comp H, fun H ↦ φ.symm.isUniformInducing.comp H⟩ + +@[deprecated (since := "2024-10-05")] +alias EquicontinuousOn.uniformInducing_uniformOnFun_iff_pi := + EquicontinuousOn.isUniformInducing_uniformOnFun_iff_pi /-- Let `X` be a topological space, `𝔖` a family of compact subsets of `X`, `α` a uniform space, and `F : ι → (X → α)` a family which is equicontinuous on each `K ∈ 𝔖`. Then, the topologies @@ -495,7 +506,8 @@ theorem ArzelaAscoli.isCompact_of_equicontinuous rw [isCompact_iff_compactSpace] at hS1 ⊢ exact (Equiv.toHomeomorphOfInducing _ h).symm.compactSpace rw [← inducing_subtype_val.of_comp_iff, ← EquicontinuousOn.inducing_uniformOnFun_iff_pi _ _ _] - · exact ContinuousMap.uniformEmbedding_toUniformOnFunIsCompact.inducing.comp inducing_subtype_val + · exact ContinuousMap.isUniformEmbedding_toUniformOnFunIsCompact.inducing.comp + inducing_subtype_val · exact eq_univ_iff_forall.mpr (fun x ↦ mem_sUnion_of_mem (mem_singleton x) isCompact_singleton) · exact fun _ ↦ id · exact fun K _ ↦ hS2.equicontinuousOn K diff --git a/Mathlib/Topology/UniformSpace/Basic.lean b/Mathlib/Topology/UniformSpace/Basic.lean index eca83bcfea729..caab9ab1db8cb 100644 --- a/Mathlib/Topology/UniformSpace/Basic.lean +++ b/Mathlib/Topology/UniformSpace/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 -/ import Mathlib.Order.Filter.SmallSets -import Mathlib.Tactic.Monotonicity +import Mathlib.Tactic.Monotonicity.Basic import Mathlib.Topology.Compactness.Compact import Mathlib.Topology.NhdsSet import Mathlib.Algebra.Group.Defs @@ -17,7 +17,7 @@ generalize to uniform spaces, e.g. * uniform continuity (in this file) * completeness (in `Cauchy.lean`) -* extension of uniform continuous functions to complete spaces (in `UniformEmbedding.lean`) +* extension of uniform continuous functions to complete spaces (in `IsUniformEmbedding.lean`) * totally bounded sets (in `Cauchy.lean`) * totally bounded complete sets are compact (in `Cauchy.lean`) @@ -136,6 +136,31 @@ theorem mem_idRel {a b : α} : (a, b) ∈ @idRel α ↔ a = b := theorem idRel_subset {s : Set (α × α)} : idRel ⊆ s ↔ ∀ a, (a, a) ∈ s := by simp [subset_def] +theorem eq_singleton_left_of_prod_subset_idRel {X : Type _} {S T : Set X} (hS : S.Nonempty) + (hT : T.Nonempty) (h_diag : S ×ˢ T ⊆ idRel) : ∃ x, S = {x} := by + rcases hS, hT with ⟨⟨s, hs⟩, ⟨t, ht⟩⟩ + refine ⟨s, eq_singleton_iff_nonempty_unique_mem.mpr ⟨⟨s, hs⟩, fun x hx ↦ ?_⟩⟩ + rw [prod_subset_iff] at h_diag + replace hs := h_diag s hs t ht + replace hx := h_diag x hx t ht + simp only [idRel, mem_setOf_eq] at hx hs + rwa [← hs] at hx + +theorem eq_singleton_right_prod_subset_idRel {X : Type _} {S T : Set X} (hS : S.Nonempty) + (hT : T.Nonempty) (h_diag : S ×ˢ T ⊆ idRel) : ∃ x, T = {x} := by + rw [Set.prod_subset_iff] at h_diag + replace h_diag := fun x hx y hy => (h_diag y hy x hx).symm + exact eq_singleton_left_of_prod_subset_idRel hT hS (prod_subset_iff.mpr h_diag) + +theorem eq_singleton_prod_subset_idRel {X : Type _} {S T : Set X} (hS : S.Nonempty) + (hT : T.Nonempty) (h_diag : S ×ˢ T ⊆ idRel) : ∃ x, S = {x} ∧ T = {x} := by + obtain ⟨⟨x, hx⟩, ⟨y, hy⟩⟩ := eq_singleton_left_of_prod_subset_idRel hS hT h_diag, + eq_singleton_right_prod_subset_idRel hS hT h_diag + refine ⟨x, ⟨hx, ?_⟩⟩ + rw [hy, Set.singleton_eq_singleton_iff] + exact (Set.prod_subset_iff.mp h_diag x (by simp only [hx, Set.mem_singleton]) y + (by simp only [hy, Set.mem_singleton])).symm + /-- The composition of relations -/ def compRel (r₁ r₂ : Set (α × α)) := { p : α × α | ∃ z : α, (p.1, z) ∈ r₁ ∧ (z, p.2) ∈ r₂ } @@ -367,33 +392,6 @@ theorem UniformSpace.replaceTopology_eq {α : Type*} [i : TopologicalSpace α] ( (h : i = u.toTopologicalSpace) : u.replaceTopology h = u := UniformSpace.ext rfl --- Porting note: rfc: use `UniformSpace.Core.mkOfBasis`? This will change defeq here and there -/-- Define a `UniformSpace` using a "distance" function. The function can be, e.g., the -distance in a (usual or extended) metric space or an absolute value on a ring. -/ -def UniformSpace.ofFun {α : Type u} {β : Type v} [OrderedAddCommMonoid β] - (d : α → α → β) (refl : ∀ x, d x x = 0) (symm : ∀ x y, d x y = d y x) - (triangle : ∀ x y z, d x z ≤ d x y + d y z) - (half : ∀ ε > (0 : β), ∃ δ > (0 : β), ∀ x < δ, ∀ y < δ, x + y < ε) : - UniformSpace α := - .ofCore - { uniformity := ⨅ r > 0, 𝓟 { x | d x.1 x.2 < r } - refl := le_iInf₂ fun r hr => principal_mono.2 <| idRel_subset.2 fun x => by simpa [refl] - symm := tendsto_iInf_iInf fun r => tendsto_iInf_iInf fun _ => tendsto_principal_principal.2 - fun x hx => by rwa [mem_setOf, symm] - comp := le_iInf₂ fun r hr => let ⟨δ, h0, hδr⟩ := half r hr; le_principal_iff.2 <| - mem_of_superset - (mem_lift' <| mem_iInf_of_mem δ <| mem_iInf_of_mem h0 <| mem_principal_self _) - fun (x, z) ⟨y, h₁, h₂⟩ => (triangle _ _ _).trans_lt (hδr _ h₁ _ h₂) } - -theorem UniformSpace.hasBasis_ofFun {α : Type u} {β : Type v} [LinearOrderedAddCommMonoid β] - (h₀ : ∃ x : β, 0 < x) (d : α → α → β) (refl : ∀ x, d x x = 0) (symm : ∀ x y, d x y = d y x) - (triangle : ∀ x y z, d x z ≤ d x y + d y z) - (half : ∀ ε > (0 : β), ∃ δ > (0 : β), ∀ x < δ, ∀ y < δ, x + y < ε) : - 𝓤[.ofFun d refl symm triangle half].HasBasis ((0 : β) < ·) (fun ε => { x | d x.1 x.2 < ε }) := - hasBasis_biInf_principal' - (fun ε₁ h₁ ε₂ h₂ => ⟨min ε₁ ε₂, lt_min h₁ h₂, fun _x hx => lt_of_lt_of_le hx (min_le_left _ _), - fun _x hx => lt_of_lt_of_le hx (min_le_right _ _)⟩) h₀ - section UniformSpace variable [UniformSpace α] @@ -894,7 +892,6 @@ lemma DenseRange.iUnion_uniformity_ball {ι : Type*} {xs : ι → α} ### Uniformity bases -/ - /-- Open elements of `𝓤 α` form a basis of `𝓤 α`. -/ theorem uniformity_hasBasis_open : HasBasis (𝓤 α) (fun V : Set (α × α) => V ∈ 𝓤 α ∧ IsOpen V) id := hasBasis_self.2 fun s hs => @@ -1119,6 +1116,11 @@ theorem uniformity_comap {_ : UniformSpace β} (f : α → β) : 𝓤[UniformSpace.comap f ‹_›] = comap (Prod.map f f) (𝓤 β) := rfl +lemma ball_preimage {f : α → β} {U : Set (β × β)} {x : α} : + UniformSpace.ball x (Prod.map f f ⁻¹' U) = f ⁻¹' UniformSpace.ball (f x) U := by + ext : 1 + simp only [UniformSpace.ball, mem_preimage, Prod.map_apply] + @[simp] theorem uniformSpace_comap_id {α : Type*} : UniformSpace.comap (id : α → α) = id := by ext : 2 @@ -1462,10 +1464,12 @@ theorem UniformContinuous.prod_mk_right {f : α × β → γ} (h : UniformContin UniformContinuous fun b => f (a, b) := h.comp (uniformContinuous_const.prod_mk uniformContinuous_id) -theorem UniformContinuous.prod_map [UniformSpace δ] {f : α → γ} {g : β → δ} +theorem UniformContinuous.prodMap [UniformSpace δ] {f : α → γ} {g : β → δ} (hf : UniformContinuous f) (hg : UniformContinuous g) : UniformContinuous (Prod.map f g) := (hf.comp uniformContinuous_fst).prod_mk (hg.comp uniformContinuous_snd) +@[deprecated (since := "2024-10-06")] alias UniformContinuous.prod_map := UniformContinuous.prodMap + theorem toTopologicalSpace_prod {α} {β} [u : UniformSpace α] [v : UniformSpace β] : @UniformSpace.toTopologicalSpace (α × β) instUniformSpaceProd = @instTopologicalSpaceProd α β u.toTopologicalSpace v.toTopologicalSpace := @@ -1481,7 +1485,7 @@ theorem uniformContinuous_inf_dom_left₂ {α β γ} {f : α → β → γ} {ua1 have ha := @UniformContinuous.inf_dom_left _ _ id ua1 ua2 ua1 (@uniformContinuous_id _ (id _)) have hb := @UniformContinuous.inf_dom_left _ _ id ub1 ub2 ub1 (@uniformContinuous_id _ (id _)) have h_unif_cont_id := - @UniformContinuous.prod_map _ _ _ _ (ua1 ⊓ ua2) (ub1 ⊓ ub2) ua1 ub1 _ _ ha hb + @UniformContinuous.prodMap _ _ _ _ (ua1 ⊓ ua2) (ub1 ⊓ ub2) ua1 ub1 _ _ ha hb exact @UniformContinuous.comp _ _ _ (id _) (id _) _ _ _ h h_unif_cont_id /-- A version of `UniformContinuous.inf_dom_right` for binary functions -/ @@ -1494,7 +1498,7 @@ theorem uniformContinuous_inf_dom_right₂ {α β γ} {f : α → β → γ} {ua have ha := @UniformContinuous.inf_dom_right _ _ id ua1 ua2 ua2 (@uniformContinuous_id _ (id _)) have hb := @UniformContinuous.inf_dom_right _ _ id ub1 ub2 ub2 (@uniformContinuous_id _ (id _)) have h_unif_cont_id := - @UniformContinuous.prod_map _ _ _ _ (ua1 ⊓ ua2) (ub1 ⊓ ub2) ua2 ub2 _ _ ha hb + @UniformContinuous.prodMap _ _ _ _ (ua1 ⊓ ua2) (ub1 ⊓ ub2) ua2 ub2 _ _ ha hb exact @UniformContinuous.comp _ _ _ (id _) (id _) _ _ _ h h_unif_cont_id /-- A version of `uniformContinuous_sInf_dom` for binary functions -/ @@ -1507,7 +1511,7 @@ theorem uniformContinuous_sInf_dom₂ {α β γ} {f : α → β → γ} {uas : S let _ : UniformSpace (α × β) := instUniformSpaceProd have ha := uniformContinuous_sInf_dom ha uniformContinuous_id have hb := uniformContinuous_sInf_dom hb uniformContinuous_id - have h_unif_cont_id := @UniformContinuous.prod_map _ _ _ _ (sInf uas) (sInf ubs) ua ub _ _ ha hb + have h_unif_cont_id := @UniformContinuous.prodMap _ _ _ _ (sInf uas) (sInf ubs) ua ub _ _ ha hb exact @UniformContinuous.comp _ _ _ (id _) (id _) _ _ _ hf h_unif_cont_id end Prod @@ -1543,7 +1547,7 @@ theorem UniformContinuous₂.comp {f : α → β → γ} {g : γ → δ} (hg : U theorem UniformContinuous₂.bicompl {f : α → β → γ} {ga : δ → α} {gb : δ' → β} (hf : UniformContinuous₂ f) (hga : UniformContinuous ga) (hgb : UniformContinuous gb) : UniformContinuous₂ (bicompl f ga gb) := - hf.uniformContinuous.comp (hga.prod_map hgb) + hf.uniformContinuous.comp (hga.prodMap hgb) end @@ -1735,7 +1739,7 @@ theorem continuousAt_iff'_left [TopologicalSpace β] {f : β → α} {b : β} : theorem continuousAt_iff_prod [TopologicalSpace β] {f : β → α} {b : β} : ContinuousAt f b ↔ Tendsto (fun x : β × β => (f x.1, f x.2)) (𝓝 (b, b)) (𝓤 α) := - ⟨fun H => le_trans (H.prod_map' H) (nhds_le_uniformity _), fun H => + ⟨fun H => le_trans (H.prodMap' H) (nhds_le_uniformity _), fun H => continuousAt_iff'_left.2 <| H.comp <| tendsto_id.prod_mk_nhds tendsto_const_nhds⟩ theorem continuousWithinAt_iff'_right [TopologicalSpace β] {f : β → α} {b : β} {s : Set β} : diff --git a/Mathlib/Topology/UniformSpace/Cauchy.lean b/Mathlib/Topology/UniformSpace/Cauchy.lean index 7907f4159bea3..b2be7ed715fd7 100644 --- a/Mathlib/Topology/UniformSpace/Cauchy.lean +++ b/Mathlib/Topology/UniformSpace/Cauchy.lean @@ -563,7 +563,7 @@ theorem TotallyBounded.image [UniformSpace β] {f : α → β} {s : Set α} (hs simp only [mem_image, iUnion_exists, biUnion_and', iUnion_iUnion_eq_right, image_subset_iff, preimage_iUnion, preimage_setOf_eq] simp? [subset_def] at hct says - simp only [mem_setOf_eq, subset_def, mem_iUnion, exists_prop', nonempty_prop] at hct + simp only [mem_setOf_eq, subset_def, mem_iUnion, exists_prop] at hct intro x hx simpa using hct x hx⟩ @@ -787,4 +787,29 @@ theorem secondCountable_of_separable [SeparableSpace α] : SecondCountableTopolo refine ⟨_, ⟨y, hys, k, rfl⟩, (hts k).subset hxy, fun z hz => ?_⟩ exact hUV (ball_subset_of_comp_subset (hk hxy) hUU' (hk hz)) +section DiscreteUniformity + +open Filter + +/-- A Cauchy filter in a discrete uniform space is contained in a principal filter-/ +theorem DiscreteUnif.cauchy_le_pure {X : Type _} {uX : UniformSpace X} + (hX : uX = ⊥) {α : Filter X} (hα : Cauchy α) : ∃ x : X, α = pure x := by + rcases hα with ⟨α_ne_bot, α_le⟩ + rw [hX, bot_uniformity, le_principal_iff, mem_prod_iff] at α_le + obtain ⟨S, ⟨hS, ⟨T, ⟨hT, H⟩⟩⟩⟩ := α_le + obtain ⟨x, rfl⟩ := eq_singleton_left_of_prod_subset_idRel (α_ne_bot.nonempty_of_mem hS) + (Filter.nonempty_of_mem hT) H + exact ⟨x, α_ne_bot.le_pure_iff.mp <| le_pure_iff.mpr hS⟩ + +/-- A constant to which a Cauchy filter in a discrete uniform space converges. -/ +noncomputable def DiscreteUnif.cauchyConst {X : Type _} {uX : UniformSpace X} + (hX : uX = ⊥) {α : Filter X} (hα : Cauchy α) : X := + (DiscreteUnif.cauchy_le_pure hX hα).choose + +theorem DiscreteUnif.eq_const_of_cauchy {X : Type _} {uX : UniformSpace X} (hX : uX = ⊥) + {α : Filter X} (hα : Cauchy α) : α = pure (DiscreteUnif.cauchyConst hX hα) := + (DiscreteUnif.cauchy_le_pure hX hα).choose_spec + +end DiscreteUniformity + end UniformSpace diff --git a/Mathlib/Topology/UniformSpace/Compact.lean b/Mathlib/Topology/UniformSpace/Compact.lean index 8f4de0a668e02..175d8d75ed946 100644 --- a/Mathlib/Topology/UniformSpace/Compact.lean +++ b/Mathlib/Topology/UniformSpace/Compact.lean @@ -151,7 +151,7 @@ theorem CompactSpace.uniformContinuous_of_continuous [CompactSpace α] {f : α (h : Continuous f) : UniformContinuous f := calc map (Prod.map f f) (𝓤 α) = map (Prod.map f f) (𝓝ˢ (diagonal α)) := by rw [nhdsSet_diagonal_eq_uniformity] - _ ≤ 𝓝ˢ (diagonal β) := (h.prod_map h).tendsto_nhdsSet mapsTo_prod_map_diagonal + _ ≤ 𝓝ˢ (diagonal β) := (h.prodMap h).tendsto_nhdsSet mapsTo_prod_map_diagonal _ ≤ 𝓤 β := nhdsSet_diagonal_le_uniformity /-- Heine-Cantor: a continuous function on a compact set of a uniform space is uniformly diff --git a/Mathlib/Topology/UniformSpace/CompactConvergence.lean b/Mathlib/Topology/UniformSpace/CompactConvergence.lean index 7f50b07c0cc1d..f13aaeff613af 100644 --- a/Mathlib/Topology/UniformSpace/CompactConvergence.lean +++ b/Mathlib/Topology/UniformSpace/CompactConvergence.lean @@ -171,11 +171,14 @@ instance compactConvergenceUniformSpace : UniformSpace C(α, β) := nhds_induced, tendsto_comap_iff, UniformOnFun.tendsto_iff_tendstoUniformlyOn] rfl -theorem uniformEmbedding_toUniformOnFunIsCompact : - UniformEmbedding (toUniformOnFunIsCompact : C(α, β) → α →ᵤ[{K | IsCompact K}] β) where +theorem isUniformEmbedding_toUniformOnFunIsCompact : + IsUniformEmbedding (toUniformOnFunIsCompact : C(α, β) → α →ᵤ[{K | IsCompact K}] β) where comap_uniformity := rfl inj := DFunLike.coe_injective +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_toUniformOnFunIsCompact := isUniformEmbedding_toUniformOnFunIsCompact + -- The following definitions and theorems -- used to be a part of the construction of the `UniformSpace C(α, β)` structure -- before it was migrated to `UniformOnFun` @@ -184,7 +187,7 @@ theorem _root_.Filter.HasBasis.compactConvergenceUniformity {ι : Type*} {pi : {s : ι → Set (β × β)} (h : (𝓤 β).HasBasis pi s) : HasBasis (𝓤 C(α, β)) (fun p : Set α × ι => IsCompact p.1 ∧ pi p.2) fun p => { fg : C(α, β) × C(α, β) | ∀ x ∈ p.1, (fg.1 x, fg.2 x) ∈ s p.2 } := by - rw [← uniformEmbedding_toUniformOnFunIsCompact.comap_uniformity] + rw [← isUniformEmbedding_toUniformOnFunIsCompact.comap_uniformity] exact .comap _ <| UniformOnFun.hasBasis_uniformity_of_basis _ _ {K | IsCompact K} ⟨∅, isCompact_empty⟩ (directedOn_of_sup_mem fun _ _ ↦ IsCompact.union) h @@ -260,27 +263,33 @@ variable {γ δ : Type*} [TopologicalSpace γ] [UniformSpace δ] theorem uniformContinuous_comp (g : C(β, δ)) (hg : UniformContinuous g) : UniformContinuous (ContinuousMap.comp g : C(α, β) → C(α, δ)) := - uniformEmbedding_toUniformOnFunIsCompact.uniformContinuous_iff.mpr <| + isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous_iff.mpr <| UniformOnFun.postcomp_uniformContinuous hg |>.comp - uniformEmbedding_toUniformOnFunIsCompact.uniformContinuous + isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous + +theorem isUniformInducing_comp (g : C(β, δ)) (hg : IsUniformInducing g) : + IsUniformInducing (ContinuousMap.comp g : C(α, β) → C(α, δ)) := + isUniformEmbedding_toUniformOnFunIsCompact.isUniformInducing.of_comp_iff.mp <| + UniformOnFun.postcomp_isUniformInducing hg |>.comp + isUniformEmbedding_toUniformOnFunIsCompact.isUniformInducing + +@[deprecated (since := "2024-10-05")] +alias uniformInducing_comp := isUniformInducing_comp -theorem uniformInducing_comp (g : C(β, δ)) (hg : UniformInducing g) : - UniformInducing (ContinuousMap.comp g : C(α, β) → C(α, δ)) := - uniformEmbedding_toUniformOnFunIsCompact.toUniformInducing.of_comp_iff.mp <| - UniformOnFun.postcomp_uniformInducing hg |>.comp - uniformEmbedding_toUniformOnFunIsCompact.toUniformInducing +theorem isUniformEmbedding_comp (g : C(β, δ)) (hg : IsUniformEmbedding g) : + IsUniformEmbedding (ContinuousMap.comp g : C(α, β) → C(α, δ)) := + isUniformEmbedding_toUniformOnFunIsCompact.of_comp_iff.mp <| + UniformOnFun.postcomp_isUniformEmbedding hg |>.comp + isUniformEmbedding_toUniformOnFunIsCompact -theorem uniformEmbedding_comp (g : C(β, δ)) (hg : UniformEmbedding g) : - UniformEmbedding (ContinuousMap.comp g : C(α, β) → C(α, δ)) := - uniformEmbedding_toUniformOnFunIsCompact.of_comp_iff.mp <| - UniformOnFun.postcomp_uniformEmbedding hg |>.comp - uniformEmbedding_toUniformOnFunIsCompact +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_comp := isUniformEmbedding_comp theorem uniformContinuous_comp_left (g : C(α, γ)) : UniformContinuous (fun f ↦ f.comp g : C(γ, β) → C(α, β)) := - uniformEmbedding_toUniformOnFunIsCompact.uniformContinuous_iff.mpr <| + isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous_iff.mpr <| UniformOnFun.precomp_uniformContinuous (fun _ hK ↦ hK.image g.continuous) |>.comp - uniformEmbedding_toUniformOnFunIsCompact.uniformContinuous + isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous /-- Any pair of a homeomorphism `X ≃ₜ Z` and an isomorphism `Y ≃ᵤ T` of uniform spaces gives rise to an isomorphism `C(X, Y) ≃ᵤ C(Z, T)`. -/ @@ -372,7 +381,8 @@ Sufficient conditions on `α` to satisfy this condition are (weak) local compact `ContinuousMap.instCompleteSpaceOfSequentialSpace`). -/ lemma completeSpace_of_restrictGenTopology (h : RestrictGenTopology {K : Set α | IsCompact K}) : CompleteSpace C(α, β) := by - rw [completeSpace_iff_isComplete_range uniformEmbedding_toUniformOnFunIsCompact.toUniformInducing, + rw [completeSpace_iff_isComplete_range + isUniformEmbedding_toUniformOnFunIsCompact.isUniformInducing, range_toUniformOnFunIsCompact, ← completeSpace_coe_iff_isComplete] exact (UniformOnFun.isClosed_setOf_continuous h).completeSpace_coe diff --git a/Mathlib/Topology/UniformSpace/CompareReals.lean b/Mathlib/Topology/UniformSpace/CompareReals.lean index 709fc27902447..c443d0a470a42 100644 --- a/Mathlib/Topology/UniformSpace/CompareReals.lean +++ b/Mathlib/Topology/UniformSpace/CompareReals.lean @@ -70,10 +70,10 @@ def rationalCauSeqPkg : @AbstractCompletion ℚ <| (@AbsoluteValue.abs ℚ _).un (uniformStruct := by infer_instance) (complete := by infer_instance) (separation := by infer_instance) - (uniformInducing := by + (isUniformInducing := by rw [Rat.uniformSpace_eq] - exact Rat.uniformEmbedding_coe_real.toUniformInducing) - (dense := Rat.denseEmbedding_coe_real.dense) + exact Rat.isUniformEmbedding_coe_real.isUniformInducing) + (dense := Rat.isDenseEmbedding_coe_real.dense) namespace CompareReals diff --git a/Mathlib/Topology/UniformSpace/CompleteSeparated.lean b/Mathlib/Topology/UniformSpace/CompleteSeparated.lean index 79943bfbcdbcf..7444f5a467be3 100644 --- a/Mathlib/Topology/UniformSpace/CompleteSeparated.lean +++ b/Mathlib/Topology/UniformSpace/CompleteSeparated.lean @@ -27,20 +27,23 @@ theorem IsComplete.isClosed [UniformSpace α] [T0Space α] {s : Set α} (h : IsC rcases h f this inf_le_right with ⟨y, ys, fy⟩ rwa [(tendsto_nhds_unique' ha inf_le_left fy : a = y)] -theorem UniformEmbedding.toClosedEmbedding [UniformSpace α] [UniformSpace β] [CompleteSpace α] - [T0Space β] {f : α → β} (hf : UniformEmbedding f) : +theorem IsUniformEmbedding.toClosedEmbedding [UniformSpace α] [UniformSpace β] [CompleteSpace α] + [T0Space β] {f : α → β} (hf : IsUniformEmbedding f) : ClosedEmbedding f := - ⟨hf.embedding, hf.toUniformInducing.isComplete_range.isClosed⟩ + ⟨hf.embedding, hf.isUniformInducing.isComplete_range.isClosed⟩ -namespace DenseInducing +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.toClosedEmbedding := IsUniformEmbedding.toClosedEmbedding + +namespace IsDenseInducing open Filter variable [TopologicalSpace α] {β : Type*} [TopologicalSpace β] variable {γ : Type*} [UniformSpace γ] [CompleteSpace γ] [T0Space γ] -theorem continuous_extend_of_cauchy {e : α → β} {f : α → γ} (de : DenseInducing e) +theorem continuous_extend_of_cauchy {e : α → β} {f : α → γ} (de : IsDenseInducing e) (h : ∀ b : β, Cauchy (map f (comap e <| 𝓝 b))) : Continuous (de.extend f) := de.continuous_extend fun b => CompleteSpace.complete (h b) -end DenseInducing +end IsDenseInducing diff --git a/Mathlib/Topology/UniformSpace/Completion.lean b/Mathlib/Topology/UniformSpace/Completion.lean index 25ec9b9b1bb0f..4d1365e733ea3 100644 --- a/Mathlib/Topology/UniformSpace/Completion.lean +++ b/Mathlib/Topology/UniformSpace/Completion.lean @@ -143,7 +143,7 @@ theorem mem_uniformity' {s : Set (CauchyFilter α × CauchyFilter α)} : def pureCauchy (a : α) : CauchyFilter α := ⟨pure a, cauchy_pure⟩ -theorem uniformInducing_pureCauchy : UniformInducing (pureCauchy : α → CauchyFilter α) := +theorem isUniformInducing_pureCauchy : IsUniformInducing (pureCauchy : α → CauchyFilter α) := ⟨have : (preimage fun x : α × α => (pureCauchy x.fst, pureCauchy x.snd)) ∘ gen = id := funext fun s => Set.ext fun ⟨a₁, a₂⟩ => by simp [preimage, gen, pureCauchy, prod_principal_principal] @@ -154,10 +154,16 @@ theorem uniformInducing_pureCauchy : UniformInducing (pureCauchy : α → Cauchy _ = 𝓤 α := by simp [this] ⟩ -theorem uniformEmbedding_pureCauchy : UniformEmbedding (pureCauchy : α → CauchyFilter α) := - { uniformInducing_pureCauchy with +@[deprecated (since := "2024-10-05")] +alias uniformInducing_pureCauchy := isUniformInducing_pureCauchy + +theorem isUniformEmbedding_pureCauchy : IsUniformEmbedding (pureCauchy : α → CauchyFilter α) := + { isUniformInducing_pureCauchy with inj := fun _a₁ _a₂ h => pure_injective <| Subtype.ext_iff_val.1 h } +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_pureCauchy := isUniformEmbedding_pureCauchy + theorem denseRange_pureCauchy : DenseRange (pureCauchy : α → CauchyFilter α) := fun f => by have h_ex : ∀ s ∈ 𝓤 (CauchyFilter α), ∃ y : α, (f, pureCauchy y) ∈ s := fun s hs => let ⟨t'', ht''₁, (ht''₂ : gen t'' ⊆ s)⟩ := (mem_lift'_sets monotone_gen).mp hs @@ -180,15 +186,18 @@ theorem denseRange_pureCauchy : DenseRange (pureCauchy : α → CauchyFilter α) ⟨mem_range_self y, hy⟩ exact ⟨_, this⟩ -theorem denseInducing_pureCauchy : DenseInducing (pureCauchy : α → CauchyFilter α) := - uniformInducing_pureCauchy.denseInducing denseRange_pureCauchy +theorem isDenseInducing_pureCauchy : IsDenseInducing (pureCauchy : α → CauchyFilter α) := + isUniformInducing_pureCauchy.isDenseInducing denseRange_pureCauchy + +theorem isDenseEmbedding_pureCauchy : IsDenseEmbedding (pureCauchy : α → CauchyFilter α) := + isUniformEmbedding_pureCauchy.isDenseEmbedding denseRange_pureCauchy -theorem denseEmbedding_pureCauchy : DenseEmbedding (pureCauchy : α → CauchyFilter α) := - uniformEmbedding_pureCauchy.denseEmbedding denseRange_pureCauchy +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_pureCauchy := isDenseEmbedding_pureCauchy theorem nonempty_cauchyFilter_iff : Nonempty (CauchyFilter α) ↔ Nonempty α := by constructor <;> rintro ⟨c⟩ - · have := eq_univ_iff_forall.1 denseEmbedding_pureCauchy.toDenseInducing.closure_range c + · have := eq_univ_iff_forall.1 isDenseEmbedding_pureCauchy.toIsDenseInducing.closure_range c obtain ⟨_, ⟨_, a, _⟩⟩ := mem_closure_iff.1 this _ isOpen_univ trivial exact ⟨a⟩ · exact ⟨pureCauchy c⟩ @@ -199,7 +208,7 @@ section -- set_option eqn_compiler.zeta true instance : CompleteSpace (CauchyFilter α) := - completeSpace_extension uniformInducing_pureCauchy denseRange_pureCauchy fun f hf => + completeSpace_extension isUniformInducing_pureCauchy denseRange_pureCauchy fun f hf => let f' : CauchyFilter α := ⟨f, hf⟩ have : map pureCauchy f ≤ (𝓤 <| CauchyFilter α).lift' (preimage (Prod.mk f')) := le_lift'.2 fun s hs => @@ -224,7 +233,7 @@ open Classical in /-- Extend a uniformly continuous function `α → β` to a function `CauchyFilter α → β`. Outputs junk when `f` is not uniformly continuous. -/ def extend (f : α → β) : CauchyFilter α → β := - if UniformContinuous f then denseInducing_pureCauchy.extend f + if UniformContinuous f then isDenseInducing_pureCauchy.extend f else fun x => f (nonempty_cauchyFilter_iff.1 ⟨x⟩).some section T0Space @@ -234,7 +243,7 @@ variable [T0Space β] theorem extend_pureCauchy {f : α → β} (hf : UniformContinuous f) (a : α) : extend f (pureCauchy a) = f a := by rw [extend, if_pos hf] - exact uniformly_extend_of_ind uniformInducing_pureCauchy denseRange_pureCauchy hf _ + exact uniformly_extend_of_ind isUniformInducing_pureCauchy denseRange_pureCauchy hf _ end T0Space @@ -243,7 +252,7 @@ variable [CompleteSpace β] theorem uniformContinuous_extend {f : α → β} : UniformContinuous (extend f) := by by_cases hf : UniformContinuous f · rw [extend, if_pos hf] - exact uniformContinuous_uniformly_extend uniformInducing_pureCauchy denseRange_pureCauchy hf + exact uniformContinuous_uniformly_extend isUniformInducing_pureCauchy denseRange_pureCauchy hf · rw [extend, if_neg hf] exact uniformContinuous_of_const fun a _b => by congr @@ -316,12 +325,15 @@ instance : Coe α (Completion α) := -- note [use has_coe_t] protected theorem coe_eq : ((↑) : α → Completion α) = SeparationQuotient.mk ∘ pureCauchy := rfl -theorem uniformInducing_coe : UniformInducing ((↑) : α → Completion α) := - SeparationQuotient.uniformInducing_mk.comp uniformInducing_pureCauchy +theorem isUniformInducing_coe : IsUniformInducing ((↑) : α → Completion α) := + SeparationQuotient.isUniformInducing_mk.comp isUniformInducing_pureCauchy + +@[deprecated (since := "2024-10-05")] +alias uniformInducing_coe := isUniformInducing_coe theorem comap_coe_eq_uniformity : ((𝓤 _).comap fun p : α × α => ((p.1 : Completion α), (p.2 : Completion α))) = 𝓤 α := - (uniformInducing_coe _).1 + (isUniformInducing_coe _).1 variable {α} @@ -338,7 +350,7 @@ def cPkg {α : Type*} [UniformSpace α] : AbstractCompletion α where uniformStruct := by infer_instance complete := by infer_instance separation := by infer_instance - uniformInducing := Completion.uniformInducing_coe α + isUniformInducing := Completion.isUniformInducing_coe α dense := Completion.denseRange_coe instance AbstractCompletion.inhabited : Inhabited (AbstractCompletion α) := @@ -356,17 +368,20 @@ theorem uniformContinuous_coe : UniformContinuous ((↑) : α → Completion α) theorem continuous_coe : Continuous ((↑) : α → Completion α) := cPkg.continuous_coe -theorem uniformEmbedding_coe [T0Space α] : UniformEmbedding ((↑) : α → Completion α) := +theorem isUniformEmbedding_coe [T0Space α] : IsUniformEmbedding ((↑) : α → Completion α) := { comap_uniformity := comap_coe_eq_uniformity α inj := separated_pureCauchy_injective } +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_coe := isUniformEmbedding_coe + theorem coe_injective [T0Space α] : Function.Injective ((↑) : α → Completion α) := - UniformEmbedding.inj (uniformEmbedding_coe _) + IsUniformEmbedding.inj (isUniformEmbedding_coe _) variable {α} -theorem denseInducing_coe : DenseInducing ((↑) : α → Completion α) := - { (uniformInducing_coe α).inducing with dense := denseRange_coe } +theorem isDenseInducing_coe : IsDenseInducing ((↑) : α → Completion α) := + { (isUniformInducing_coe α).inducing with dense := denseRange_coe } /-- The uniform bijection between a complete space and its uniform completion. -/ def UniformCompletion.completeEquivSelf [CompleteSpace α] [T0Space α] : Completion α ≃ᵤ α := @@ -375,19 +390,22 @@ def UniformCompletion.completeEquivSelf [CompleteSpace α] [T0Space α] : Comple open TopologicalSpace instance separableSpace_completion [SeparableSpace α] : SeparableSpace (Completion α) := - Completion.denseInducing_coe.separableSpace + Completion.isDenseInducing_coe.separableSpace + +theorem isDenseEmbedding_coe [T0Space α] : IsDenseEmbedding ((↑) : α → Completion α) := + { isDenseInducing_coe with inj := separated_pureCauchy_injective } -theorem denseEmbedding_coe [T0Space α] : DenseEmbedding ((↑) : α → Completion α) := - { denseInducing_coe with inj := separated_pureCauchy_injective } +@[deprecated (since := "2024-09-30")] +alias denseEmbedding_coe := isDenseEmbedding_coe theorem denseRange_coe₂ : DenseRange fun x : α × β => ((x.1 : Completion α), (x.2 : Completion β)) := - denseRange_coe.prod_map denseRange_coe + denseRange_coe.prodMap denseRange_coe theorem denseRange_coe₃ : DenseRange fun x : α × β × γ => ((x.1 : Completion α), ((x.2.1 : Completion β), (x.2.2 : Completion γ))) := - denseRange_coe.prod_map denseRange_coe₂ + denseRange_coe.prodMap denseRange_coe₂ @[elab_as_elim] theorem induction_on {p : Completion α → Prop} (a : Completion α) (hp : IsClosed { a | p a }) diff --git a/Mathlib/Topology/UniformSpace/Equicontinuity.lean b/Mathlib/Topology/UniformSpace/Equicontinuity.lean index 5fdd4c239966d..807c30865e06d 100644 --- a/Mathlib/Topology/UniformSpace/Equicontinuity.lean +++ b/Mathlib/Topology/UniformSpace/Equicontinuity.lean @@ -704,56 +704,74 @@ theorem Filter.HasBasis.uniformEquicontinuousOn_iff {κ₁ κ₂ : Type*} {p₁ /-- Given `u : α → β` a uniform inducing map, a family `𝓕 : ι → X → α` is equicontinuous at a point `x₀ : X` iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is equicontinuous at `x₀`. -/ -theorem UniformInducing.equicontinuousAt_iff {F : ι → X → α} {x₀ : X} {u : α → β} - (hu : UniformInducing u) : EquicontinuousAt F x₀ ↔ EquicontinuousAt ((u ∘ ·) ∘ F) x₀ := by - have := (UniformFun.postcomp_uniformInducing (α := ι) hu).inducing +theorem IsUniformInducing.equicontinuousAt_iff {F : ι → X → α} {x₀ : X} {u : α → β} + (hu : IsUniformInducing u) : EquicontinuousAt F x₀ ↔ EquicontinuousAt ((u ∘ ·) ∘ F) x₀ := by + have := (UniformFun.postcomp_isUniformInducing (α := ι) hu).inducing rw [equicontinuousAt_iff_continuousAt, equicontinuousAt_iff_continuousAt, this.continuousAt_iff] rfl +@[deprecated (since := "2024-10-05")] +alias UniformInducing.equicontinuousAt_iff := IsUniformInducing.equicontinuousAt_iff + /-- Given `u : α → β` a uniform inducing map, a family `𝓕 : ι → X → α` is equicontinuous at a point `x₀ : X` within a subset `S : Set X` iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is equicontinuous at `x₀` within `S`. -/ -theorem UniformInducing.equicontinuousWithinAt_iff {F : ι → X → α} {S : Set X} {x₀ : X} {u : α → β} - (hu : UniformInducing u) : EquicontinuousWithinAt F S x₀ ↔ +lemma IsUniformInducing.equicontinuousWithinAt_iff {F : ι → X → α} {S : Set X} {x₀ : X} {u : α → β} + (hu : IsUniformInducing u) : EquicontinuousWithinAt F S x₀ ↔ EquicontinuousWithinAt ((u ∘ ·) ∘ F) S x₀ := by - have := (UniformFun.postcomp_uniformInducing (α := ι) hu).inducing + have := (UniformFun.postcomp_isUniformInducing (α := ι) hu).inducing simp only [equicontinuousWithinAt_iff_continuousWithinAt, this.continuousWithinAt_iff] rfl +@[deprecated (since := "2024-10-05")] +alias UniformInducing.equicontinuousWithinAt_iff := IsUniformInducing.equicontinuousWithinAt_iff + /-- Given `u : α → β` a uniform inducing map, a family `𝓕 : ι → X → α` is equicontinuous iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is equicontinuous. -/ -theorem UniformInducing.equicontinuous_iff {F : ι → X → α} {u : α → β} (hu : UniformInducing u) : +lemma IsUniformInducing.equicontinuous_iff {F : ι → X → α} {u : α → β} (hu : IsUniformInducing u) : Equicontinuous F ↔ Equicontinuous ((u ∘ ·) ∘ F) := by congrm ∀ x, ?_ rw [hu.equicontinuousAt_iff] +@[deprecated (since := "2024-10-05")] +alias UniformInducing.equicontinuous_iff := IsUniformInducing.equicontinuous_iff + /-- Given `u : α → β` a uniform inducing map, a family `𝓕 : ι → X → α` is equicontinuous on a subset `S : Set X` iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is equicontinuous on `S`. -/ -theorem UniformInducing.equicontinuousOn_iff {F : ι → X → α} {S : Set X} {u : α → β} - (hu : UniformInducing u) : EquicontinuousOn F S ↔ EquicontinuousOn ((u ∘ ·) ∘ F) S := by +theorem IsUniformInducing.equicontinuousOn_iff {F : ι → X → α} {S : Set X} {u : α → β} + (hu : IsUniformInducing u) : EquicontinuousOn F S ↔ EquicontinuousOn ((u ∘ ·) ∘ F) S := by congrm ∀ x ∈ S, ?_ rw [hu.equicontinuousWithinAt_iff] +@[deprecated (since := "2024-10-05")] +alias UniformInducing.equicontinuousOn_iff := IsUniformInducing.equicontinuousOn_iff + /-- Given `u : α → γ` a uniform inducing map, a family `𝓕 : ι → β → α` is uniformly equicontinuous iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is uniformly equicontinuous. -/ -theorem UniformInducing.uniformEquicontinuous_iff {F : ι → β → α} {u : α → γ} - (hu : UniformInducing u) : UniformEquicontinuous F ↔ UniformEquicontinuous ((u ∘ ·) ∘ F) := by - have := UniformFun.postcomp_uniformInducing (α := ι) hu +theorem IsUniformInducing.uniformEquicontinuous_iff {F : ι → β → α} {u : α → γ} + (hu : IsUniformInducing u) : UniformEquicontinuous F ↔ UniformEquicontinuous ((u ∘ ·) ∘ F) := by + have := UniformFun.postcomp_isUniformInducing (α := ι) hu simp only [uniformEquicontinuous_iff_uniformContinuous, this.uniformContinuous_iff] rfl +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformEquicontinuous_iff := IsUniformInducing.uniformEquicontinuous_iff + /-- Given `u : α → γ` a uniform inducing map, a family `𝓕 : ι → β → α` is uniformly equicontinuous on a subset `S : Set β` iff the family `𝓕'`, obtained by composing each function of `𝓕` by `u`, is uniformly equicontinuous on `S`. -/ -theorem UniformInducing.uniformEquicontinuousOn_iff {F : ι → β → α} {S : Set β} {u : α → γ} - (hu : UniformInducing u) : +theorem IsUniformInducing.uniformEquicontinuousOn_iff {F : ι → β → α} {S : Set β} {u : α → γ} + (hu : IsUniformInducing u) : UniformEquicontinuousOn F S ↔ UniformEquicontinuousOn ((u ∘ ·) ∘ F) S := by - have := UniformFun.postcomp_uniformInducing (α := ι) hu + have := UniformFun.postcomp_isUniformInducing (α := ι) hu simp only [uniformEquicontinuousOn_iff_uniformContinuousOn, this.uniformContinuousOn_iff] rfl +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformEquicontinuousOn_iff := IsUniformInducing.uniformEquicontinuousOn_iff + /-- If a set of functions is equicontinuous at some `x₀` within a set `S`, the same is true for its closure in *any* topology for which evaluation at any `x ∈ S ∪ {x₀}` is continuous. Since this will be applied to `DFunLike` types, we state it for any topological space with a map diff --git a/Mathlib/Topology/UniformSpace/Equiv.lean b/Mathlib/Topology/UniformSpace/Equiv.lean index d4be20cb620ad..6fb396f7b0004 100644 --- a/Mathlib/Topology/UniformSpace/Equiv.lean +++ b/Mathlib/Topology/UniformSpace/Equiv.lean @@ -49,11 +49,11 @@ theorem toEquiv_injective : Function.Injective (toEquiv : α ≃ᵤ β → α | ⟨e, h₁, h₂⟩, ⟨e', h₁', h₂'⟩, h => by simpa only [mk.injEq] instance : EquivLike (α ≃ᵤ β) α β where - coe := fun h => h.toEquiv - 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 <| DFunLike.ext' H + coe h := h.toEquiv + inv h := h.toEquiv.symm + left_inv h := h.left_inv + right_inv h := h.right_inv + coe_injective' _ _ H _ := toEquiv_injective <| DFunLike.ext' H @[simp] theorem uniformEquiv_mk_coe (a : Equiv α β) (b c) : (UniformEquiv.mk a b c : α → β) = a := @@ -196,28 +196,35 @@ theorem image_preimage (h : α ≃ᵤ β) (s : Set β) : h '' (h ⁻¹' s) = s : theorem preimage_image (h : α ≃ᵤ β) (s : Set α) : h ⁻¹' (h '' s) = s := h.toEquiv.preimage_image s -protected theorem uniformInducing (h : α ≃ᵤ β) : UniformInducing h := - uniformInducing_of_compose h.uniformContinuous h.symm.uniformContinuous <| by - simp only [symm_comp_self, uniformInducing_id] +theorem isUniformInducing (h : α ≃ᵤ β) : IsUniformInducing h := + IsUniformInducing.of_comp h.uniformContinuous h.symm.uniformContinuous <| by + simp only [symm_comp_self, IsUniformInducing.id] + +@[deprecated (since := "2024-10-05")] +alias uniformInducing := isUniformInducing theorem comap_eq (h : α ≃ᵤ β) : UniformSpace.comap h ‹_› = ‹_› := - h.uniformInducing.comap_uniformSpace + h.isUniformInducing.comap_uniformSpace + +lemma isUniformEmbedding (h : α ≃ᵤ β) : IsUniformEmbedding h := ⟨h.isUniformInducing, h.injective⟩ -protected theorem uniformEmbedding (h : α ≃ᵤ β) : UniformEmbedding h := - ⟨h.uniformInducing, h.injective⟩ +@[deprecated (since := "2024-10-01")] alias uniformEmbedding := isUniformEmbedding theorem completeSpace_iff (h : α ≃ᵤ β) : CompleteSpace α ↔ CompleteSpace β := - completeSpace_congr h.uniformEmbedding + completeSpace_congr h.isUniformEmbedding /-- Uniform equiv given a uniform embedding. -/ -noncomputable def ofUniformEmbedding (f : α → β) (hf : UniformEmbedding f) : α ≃ᵤ Set.range f where - uniformContinuous_toFun := hf.toUniformInducing.uniformContinuous.subtype_mk _ +noncomputable def ofIsUniformEmbedding (f : α → β) (hf : IsUniformEmbedding f) : + α ≃ᵤ Set.range f where + uniformContinuous_toFun := hf.isUniformInducing.uniformContinuous.subtype_mk _ uniformContinuous_invFun := by - rw [hf.toUniformInducing.uniformContinuous_iff, Equiv.invFun_as_coe, + rw [hf.isUniformInducing.uniformContinuous_iff, Equiv.invFun_as_coe, Equiv.self_comp_ofInjective_symm] exact uniformContinuous_subtype_val toEquiv := Equiv.ofInjective f hf.inj +@[deprecated (since := "2024-10-03")] alias ofUniformEmbedding := ofIsUniformEmbedding + /-- If two sets are equal, then they are uniformly equivalent. -/ def setCongr {s t : Set α} (h : s = t) : s ≃ᵤ t where uniformContinuous_toFun := uniformContinuous_subtype_val.subtype_mk _ @@ -327,7 +334,7 @@ def ulift : ULift.{v, u} α ≃ᵤ α := { Equiv.ulift with uniformContinuous_toFun := uniformContinuous_comap uniformContinuous_invFun := by - have hf : UniformInducing (@Equiv.ulift.{v, u} α).toFun := ⟨rfl⟩ + have hf : IsUniformInducing (@Equiv.ulift.{v, u} α).toFun := ⟨rfl⟩ simp_rw [hf.uniformContinuous_iff] exact uniformContinuous_id } @@ -366,8 +373,8 @@ end UniformEquiv /-- A uniform inducing equiv between uniform spaces is a uniform isomorphism. -/ -- @[simps] -- Porting note: removed, `simps?` produced no `simp` lemmas -def Equiv.toUniformEquivOfUniformInducing [UniformSpace α] [UniformSpace β] (f : α ≃ β) - (hf : UniformInducing f) : α ≃ᵤ β := +def Equiv.toUniformEquivOfIsUniformInducing [UniformSpace α] [UniformSpace β] (f : α ≃ β) + (hf : IsUniformInducing f) : α ≃ᵤ β := { f with uniformContinuous_toFun := hf.uniformContinuous uniformContinuous_invFun := hf.uniformContinuous_iff.2 <| by simpa using uniformContinuous_id } diff --git a/Mathlib/Topology/UniformSpace/OfFun.lean b/Mathlib/Topology/UniformSpace/OfFun.lean new file mode 100644 index 0000000000000..6a1ff605f190e --- /dev/null +++ b/Mathlib/Topology/UniformSpace/OfFun.lean @@ -0,0 +1,52 @@ +/- +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.Topology.UniformSpace.Basic +import Mathlib.Algebra.Order.Monoid.Defs + +/-! +# Construct a `UniformSpace` from a `dist`-like function + +In this file we provide a constructor for `UniformSpace` +given a `dist`-like function + +## TODO + +RFC: use `UniformSpace.Core.mkOfBasis`? This will change defeq here and there +-/ + +open Filter Set +open scoped Uniformity + +variable {X M : Type*} + +namespace UniformSpace + +/-- Define a `UniformSpace` using a "distance" function. The function can be, e.g., the +distance in a (usual or extended) metric space or an absolute value on a ring. -/ +def ofFun [OrderedAddCommMonoid M] (d : X → X → M) (refl : ∀ x, d x x = 0) + (symm : ∀ x y, d x y = d y x) (triangle : ∀ x y z, d x z ≤ d x y + d y z) + (half : ∀ ε > (0 : M), ∃ δ > (0 : M), ∀ x < δ, ∀ y < δ, x + y < ε) : + UniformSpace X := + .ofCore + { uniformity := ⨅ r > 0, 𝓟 { x | d x.1 x.2 < r } + refl := le_iInf₂ fun r hr => principal_mono.2 <| idRel_subset.2 fun x => by simpa [refl] + symm := tendsto_iInf_iInf fun r => tendsto_iInf_iInf fun _ => tendsto_principal_principal.2 + fun x hx => by rwa [mem_setOf, symm] + comp := le_iInf₂ fun r hr => let ⟨δ, h0, hδr⟩ := half r hr; le_principal_iff.2 <| + mem_of_superset + (mem_lift' <| mem_iInf_of_mem δ <| mem_iInf_of_mem h0 <| mem_principal_self _) + fun (x, z) ⟨y, h₁, h₂⟩ => (triangle _ _ _).trans_lt (hδr _ h₁ _ h₂) } + +theorem hasBasis_ofFun [LinearOrderedAddCommMonoid M] + (h₀ : ∃ x : M, 0 < x) (d : X → X → M) (refl : ∀ x, d x x = 0) (symm : ∀ x y, d x y = d y x) + (triangle : ∀ x y z, d x z ≤ d x y + d y z) + (half : ∀ ε > (0 : M), ∃ δ > (0 : M), ∀ x < δ, ∀ y < δ, x + y < ε) : + 𝓤[.ofFun d refl symm triangle half].HasBasis ((0 : M) < ·) (fun ε => { x | d x.1 x.2 < ε }) := + hasBasis_biInf_principal' + (fun ε₁ h₁ ε₂ h₂ => ⟨min ε₁ ε₂, lt_min h₁ h₂, fun _x hx => lt_of_lt_of_le hx (min_le_left _ _), + fun _x hx => lt_of_lt_of_le hx (min_le_right _ _)⟩) h₀ + +end UniformSpace diff --git a/Mathlib/Topology/UniformSpace/Pi.lean b/Mathlib/Topology/UniformSpace/Pi.lean index 5c35d1206a3ad..783300913d8d4 100644 --- a/Mathlib/Topology/UniformSpace/Pi.lean +++ b/Mathlib/Topology/UniformSpace/Pi.lean @@ -122,8 +122,8 @@ protected theorem CompleteSpace.iInf {ι X : Type*} {u : ι → UniformSpace X} nontriviality X rcases ht with ⟨t, ht, hut⟩ -- The diagonal map `(X, ⨅ i, u i) → ∀ i, (X, u i)` is a uniform embedding. - have : @UniformInducing X (ι → X) (⨅ i, u i) (Pi.uniformSpace (U := u)) (const ι) := by - simp_rw [uniformInducing_iff, iInf_uniformity, Pi.uniformity, Filter.comap_iInf, + have : @IsUniformInducing X (ι → X) (⨅ i, u i) (Pi.uniformSpace (U := u)) (const ι) := by + simp_rw [isUniformInducing_iff, iInf_uniformity, Pi.uniformity, Filter.comap_iInf, Filter.comap_comap, comp_def, const, Prod.eta, comap_id'] -- Hence, it suffices to show that its range, the diagonal, is closed in `Π i, (X, u i)`. simp_rw [@completeSpace_iff_isComplete_range _ _ (_) (_) _ this, range_const_eq_diagonal, diff --git a/Mathlib/Topology/UniformSpace/UniformConvergence.lean b/Mathlib/Topology/UniformSpace/UniformConvergence.lean index 4d216ca50a3ca..3d5593d33b3b1 100644 --- a/Mathlib/Topology/UniformSpace/UniformConvergence.lean +++ b/Mathlib/Topology/UniformSpace/UniformConvergence.lean @@ -196,6 +196,12 @@ theorem TendstoUniformlyOn.congr {F' : ι → α → β} (hf : TendstoUniformlyO simp only [Set.EqOn] at hff' simp only [mem_prod_principal, hff', mem_setOf_eq] +lemma tendstoUniformly_congr {F F' : ι → α → β} {f : α → β} (hF : F =ᶠ[p] F') : + TendstoUniformly F f p ↔ TendstoUniformly F' f p := by + simp_rw [← tendstoUniformlyOn_univ] at * + have HF := EventuallyEq.exists_mem hF + exact ⟨fun h => h.congr (by aesop), fun h => h.congr (by simp_rw [eqOn_comm]; aesop)⟩ + theorem TendstoUniformlyOn.congr_right {g : α → β} (hf : TendstoUniformlyOn F f p s) (hfg : EqOn f g s) : TendstoUniformlyOn F g p s := fun u hu => by filter_upwards [hf u hu] with i hi a ha using hfg ha ▸ hi a ha diff --git a/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean b/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean index 4eae4a2c7b4eb..00cd2deafccea 100644 --- a/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean +++ b/Mathlib/Topology/UniformSpace/UniformConvergenceTopology.lean @@ -88,7 +88,7 @@ connection API to do most of the work. * `UniformOnFun.postcomp_uniformContinuous`: if `f : γ → β` is uniformly continuous, then `(fun g ↦ f ∘ g) : (α →ᵤ[𝔖] γ) → (α →ᵤ[𝔖] β)` is uniformly continuous. -* `UniformOnFun.postcomp_uniformInducing`: if `f : γ → β` is a uniform +* `UniformOnFun.postcomp_isUniformInducing`: if `f : γ → β` is a uniform inducing, then `(fun g ↦ f ∘ g) : (α →ᵤ[𝔖] γ) → (α →ᵤ[𝔖] β)` is a uniform inducing. * `UniformOnFun.precomp_uniformContinuous`: let `f : γ → α`, `𝔖 : Set (Set α)`, `𝔗 : Set (Set γ)`, and assume that `∀ T ∈ 𝔗, f '' T ∈ 𝔖`. Then, the function @@ -367,28 +367,35 @@ a uniform inducing function for the uniform structures of uniform convergence. More precisely, if `f : γ → β` is uniform inducing, then `(f ∘ ·) : (α →ᵤ γ) → (α →ᵤ β)` is uniform inducing. -/ -protected theorem postcomp_uniformInducing [UniformSpace γ] {f : γ → β} (hf : UniformInducing f) : - UniformInducing (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) := +lemma postcomp_isUniformInducing [UniformSpace γ] {f : γ → β} + (hf : IsUniformInducing f) : IsUniformInducing (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) := ⟨((UniformFun.hasBasis_uniformity _ _).comap _).eq_of_same_basis <| UniformFun.hasBasis_uniformity_of_basis _ _ (hf.basis_uniformity (𝓤 β).basis_sets)⟩ +@[deprecated (since := "2024-10-05")] +alias postcomp_uniformInducing := postcomp_isUniformInducing + /-- Post-composition by a uniform embedding is a uniform embedding for the uniform structures of uniform convergence. More precisely, if `f : γ → β` is a uniform embedding, then `(f ∘ ·) : (α →ᵤ γ) → (α →ᵤ β)` is a uniform embedding. -/ -protected theorem postcomp_uniformEmbedding [UniformSpace γ] {f : γ → β} (hf : UniformEmbedding f) : - UniformEmbedding (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) where - toUniformInducing := UniformFun.postcomp_uniformInducing hf.toUniformInducing +protected theorem postcomp_isUniformEmbedding [UniformSpace γ] {f : γ → β} + (hf : IsUniformEmbedding f) : + IsUniformEmbedding (ofFun ∘ (f ∘ ·) ∘ toFun : (α →ᵤ γ) → α →ᵤ β) where + toIsUniformInducing := UniformFun.postcomp_isUniformInducing hf.isUniformInducing inj _ _ H := funext fun _ ↦ hf.inj (congrFun H _) +@[deprecated (since := "2024-10-01")] +alias postcomp_uniformEmbedding := UniformFun.postcomp_isUniformEmbedding + -- Porting note: had to add a type annotation at `((f ∘ ·) : ((α → γ) → (α → β)))` /-- If `u` is a uniform structures on `β` and `f : γ → β`, then `𝒰(α, γ, comap f u) = comap (fun g ↦ f ∘ g) 𝒰(α, γ, u₁)`. -/ protected theorem comap_eq {f : γ → β} : 𝒰(α, γ, ‹UniformSpace β›.comap f) = 𝒰(α, β, _).comap (f ∘ ·) := by letI : UniformSpace γ := .comap f ‹_› - exact (UniformFun.postcomp_uniformInducing (f := f) ⟨rfl⟩).comap_uniformSpace.symm + exact (UniformFun.postcomp_isUniformInducing (f := f) ⟨rfl⟩).comap_uniformSpace.symm /-- Post-composition by a uniformly continuous function is uniformly continuous on `α →ᵤ β`. @@ -461,7 +468,7 @@ protected def uniformEquivProdArrow [UniformSpace γ] : (α →ᵤ β × γ) ≃ -- But `uβ × uγ` is defined as `comap fst uβ ⊓ comap snd uγ`, so we just have to apply -- `UniformFun.inf_eq` and `UniformFun.comap_eq`, which leaves us to check -- that some square commutes. - Equiv.toUniformEquivOfUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by + Equiv.toUniformEquivOfIsUniformInducing (Equiv.arrowProdEquivProdArrow _ _ _) <| by constructor change comap (Prod.map (Equiv.arrowProdEquivProdArrow _ _ _) (Equiv.arrowProdEquivProdArrow _ _ _)) @@ -486,10 +493,10 @@ protected def uniformEquivPiComm : UniformEquiv (α →ᵤ ∀ i, δ i) (∀ i, -- But `Π i, uδ i` is defined as `⨅ i, comap (eval i) (uδ i)`, so we just have to apply -- `UniformFun.iInf_eq` and `UniformFun.comap_eq`, which leaves us to check -- that some square commutes. - @Equiv.toUniformEquivOfUniformInducing + @Equiv.toUniformEquivOfIsUniformInducing _ _ 𝒰(α, ∀ i, δ i, Pi.uniformSpace δ) (@Pi.uniformSpace ι (fun i => α → δ i) fun i => 𝒰(α, δ i, _)) (Equiv.piComm _) <| by - refine @UniformInducing.mk ?_ ?_ ?_ ?_ ?_ ?_ + refine @IsUniformInducing.mk ?_ ?_ ?_ ?_ ?_ ?_ change comap (Prod.map Function.swap Function.swap) _ = _ rw [← uniformity_comap] congr @@ -861,8 +868,8 @@ uniform structures of `𝔖`-convergence. More precisely, if `f : γ → β` is a uniform inducing, then `(fun g ↦ f ∘ g) : (α →ᵤ[𝔖] γ) → (α →ᵤ[𝔖] β)` is a uniform inducing. -/ -protected theorem postcomp_uniformInducing [UniformSpace γ] {f : γ → β} (hf : UniformInducing f) : - UniformInducing (ofFun 𝔖 ∘ (f ∘ ·) ∘ toFun 𝔖) := by +lemma postcomp_isUniformInducing [UniformSpace γ] {f : γ → β} + (hf : IsUniformInducing f) : IsUniformInducing (ofFun 𝔖 ∘ (f ∘ ·) ∘ toFun 𝔖) := by -- This is a direct consequence of `UniformOnFun.comap_eq` constructor replace hf : (𝓤 β).comap (Prod.map f f) = _ := hf.comap_uniformity @@ -872,16 +879,22 @@ protected theorem postcomp_uniformInducing [UniformSpace γ] {f : γ → β} (hf rw [← UniformSpace.ext hf, UniformOnFun.comap_eq] rfl +@[deprecated (since := "2024-10-05")] +alias postcomp_uniformInducing := postcomp_isUniformInducing + /-- Post-composition by a uniform embedding is a uniform embedding for the uniform structures of `𝔖`-convergence. More precisely, if `f : γ → β` is a uniform embedding, then `(fun g ↦ f ∘ g) : (α →ᵤ[𝔖] γ) → (α →ᵤ[𝔖] β)` is a uniform embedding. -/ -protected theorem postcomp_uniformEmbedding [UniformSpace γ] {f : γ → β} (hf : UniformEmbedding f) : - UniformEmbedding (ofFun 𝔖 ∘ (f ∘ ·) ∘ toFun 𝔖) where - toUniformInducing := UniformOnFun.postcomp_uniformInducing hf.toUniformInducing +protected theorem postcomp_isUniformEmbedding [UniformSpace γ] {f : γ → β} + (hf : IsUniformEmbedding f) : IsUniformEmbedding (ofFun 𝔖 ∘ (f ∘ ·) ∘ toFun 𝔖) where + toIsUniformInducing := UniformOnFun.postcomp_isUniformInducing hf.isUniformInducing inj _ _ H := funext fun _ ↦ hf.inj (congrFun H _) +@[deprecated (since := "2024-10-01")] +alias postcomp_uniformEmbedding := UniformOnFun.postcomp_isUniformEmbedding + /-- Turn a uniform isomorphism `γ ≃ᵤ β` into a uniform isomorphism `(α →ᵤ[𝔖] γ) ≃ᵤ (α →ᵤ[𝔖] β)` by post-composing. -/ protected def congrRight [UniformSpace γ] (e : γ ≃ᵤ β) : (α →ᵤ[𝔖] γ) ≃ᵤ (α →ᵤ[𝔖] β) := @@ -1005,9 +1018,8 @@ protected def uniformEquivProdArrow [UniformSpace γ] : -- which leaves us to check that some square commutes. -- We could also deduce this from `UniformFun.uniformEquivProdArrow`, -- but it turns out to be more annoying. - ((UniformOnFun.ofFun 𝔖).symm.trans <| - (Equiv.arrowProdEquivProdArrow _ _ _).trans <| - (UniformOnFun.ofFun 𝔖).prodCongr (UniformOnFun.ofFun 𝔖)).toUniformEquivOfUniformInducing <| by + ((UniformOnFun.ofFun 𝔖).symm.trans <| (Equiv.arrowProdEquivProdArrow _ _ _).trans <| + (UniformOnFun.ofFun 𝔖).prodCongr (UniformOnFun.ofFun 𝔖)).toUniformEquivOfIsUniformInducing <| by constructor rw [uniformity_prod, comap_inf, comap_comap, comap_comap] have H := @UniformOnFun.inf_eq α (β × γ) 𝔖 @@ -1031,7 +1043,7 @@ protected def uniformEquivPiComm : (α →ᵤ[𝔖] ((i : ι) → δ i)) ≃ᵤ -- which leaves us to check that some square commutes. -- We could also deduce this from `UniformFun.uniformEquivPiComm`, but it turns out -- to be more annoying. - @Equiv.toUniformEquivOfUniformInducing (α →ᵤ[𝔖] ((i : ι) → δ i)) ((i : ι) → α →ᵤ[𝔖] δ i) + @Equiv.toUniformEquivOfIsUniformInducing (α →ᵤ[𝔖] ((i : ι) → δ i)) ((i : ι) → α →ᵤ[𝔖] δ i) _ _ (Equiv.piComm _) <| by constructor change comap (Prod.map Function.swap Function.swap) _ = _ @@ -1117,3 +1129,41 @@ instance {α β : Type*} [UniformSpace β] [CompleteSpace β] : CompleteSpace ( (UniformOnFun.uniformEquivUniformFun β {univ} (mem_singleton _)).completeSpace_iff.1 inferInstance end UniformFun + +section UniformComposition + +variable {α β γ ι : Type*} [UniformSpace β] [UniformSpace γ] {p : Filter ι} + +/-- Composing on the left by a uniformly continuous function preserves uniform convergence -/ +theorem UniformContinuousOn.comp_tendstoUniformly (s : Set β) (F : ι → α → β) (f : α → β) + (hF : ∀ i x, F i x ∈ s) (hf : ∀ x, f x ∈ s) + {g : β → γ} (hg : UniformContinuousOn g s) (h : TendstoUniformly F f p) : + TendstoUniformly (fun i x => g (F i x)) (fun x => g (f x)) p := by + rw [uniformContinuousOn_iff_restrict] at hg + lift F to ι → α → s using hF with F' hF' + lift f to α → s using hf with f' hf' + rw [tendstoUniformly_iff_tendsto] at h + have : Tendsto (fun q : ι × α ↦ (f' q.2, (F' q.1 q.2))) (p ×ˢ ⊤) (𝓤 s) := + h.of_tendsto_comp isUniformEmbedding_subtype_val.comap_uniformity.le + apply UniformContinuous.comp_tendstoUniformly hg ?_ + rwa [← tendstoUniformly_iff_tendsto] at this + +theorem UniformContinuousOn.comp_tendstoUniformly_eventually (s : Set β) (F : ι → α → β) (f : α → β) + (hF : ∀ᶠ i in p, ∀ x, F i x ∈ s) (hf : ∀ x, f x ∈ s) + {g : β → γ} (hg : UniformContinuousOn g s) (h : TendstoUniformly F f p) : + TendstoUniformly (fun i => fun x => g (F i x)) (fun x => g (f x)) p := by + classical + rw [eventually_iff_exists_mem] at hF + obtain ⟨s', hs', hs⟩ := hF + let F' : ι → α → β := fun (i : ι) x => if i ∈ s' then F i x else f x + have hF : F =ᶠ[p] F' := by + rw [eventuallyEq_iff_exists_mem] + refine ⟨s', hs', fun y hy => by aesop⟩ + have h' : TendstoUniformly F' f p := by + rwa [tendstoUniformly_congr hF] at h + apply (tendstoUniformly_congr _).mpr + (UniformContinuousOn.comp_tendstoUniformly s F' f (by aesop) hf hg h') + rw [eventuallyEq_iff_exists_mem] + refine ⟨s', hs', fun i hi => by aesop⟩ + +end UniformComposition diff --git a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean index ed90ccfc3618a..d70f7fb955c8f 100644 --- a/Mathlib/Topology/UniformSpace/UniformEmbedding.lean +++ b/Mathlib/Topology/UniformSpace/UniformEmbedding.lean @@ -20,6 +20,7 @@ section universe u v w variable {α : Type u} {β : Type v} {γ : Type w} [UniformSpace α] [UniformSpace β] [UniformSpace γ] + {f : α → β} /-! ### Uniform inducing maps @@ -27,102 +28,165 @@ variable {α : Type u} {β : Type v} {γ : Type w} [UniformSpace α] [UniformSpa /-- A map `f : α → β` between uniform spaces is called *uniform inducing* if the uniformity filter on `α` is the pullback of the uniformity filter on `β` under `Prod.map f f`. If `α` is a separated -space, then this implies that `f` is injective, hence it is a `UniformEmbedding`. -/ +space, then this implies that `f` is injective, hence it is a `IsUniformEmbedding`. -/ @[mk_iff] -structure UniformInducing (f : α → β) : Prop where +structure IsUniformInducing (f : α → β) : Prop where /-- The uniformity filter on the domain is the pullback of the uniformity filter on the codomain under `Prod.map f f`. -/ comap_uniformity : comap (fun x : α × α => (f x.1, f x.2)) (𝓤 β) = 𝓤 α -lemma uniformInducing_iff_uniformSpace {f : α → β} : - UniformInducing f ↔ ‹UniformSpace β›.comap f = ‹UniformSpace α› := by - rw [uniformInducing_iff, UniformSpace.ext_iff, Filter.ext_iff] +@[deprecated (since := "2024-10-08")] alias UniformInducing := IsUniformInducing + +lemma isUniformInducing_iff_uniformSpace {f : α → β} : + IsUniformInducing f ↔ ‹UniformSpace β›.comap f = ‹UniformSpace α› := by + rw [isUniformInducing_iff, UniformSpace.ext_iff, Filter.ext_iff] rfl -protected alias ⟨UniformInducing.comap_uniformSpace, _⟩ := uniformInducing_iff_uniformSpace +@[deprecated (since := "2024-10-05")] +alias uniformInducing_iff_uniformSpace := isUniformInducing_iff_uniformSpace + +protected alias ⟨IsUniformInducing.comap_uniformSpace, _⟩ := isUniformInducing_iff_uniformSpace + +@[deprecated (since := "2024-10-08")] alias UniformInducing.comap_uniformSpace := + IsUniformInducing.comap_uniformSpace + +lemma isUniformInducing_iff' {f : α → β} : + IsUniformInducing f ↔ UniformContinuous f ∧ comap (Prod.map f f) (𝓤 β) ≤ 𝓤 α := by + rw [isUniformInducing_iff, UniformContinuous, tendsto_iff_comap, le_antisymm_iff, and_comm]; rfl -lemma uniformInducing_iff' {f : α → β} : - UniformInducing f ↔ UniformContinuous f ∧ comap (Prod.map f f) (𝓤 β) ≤ 𝓤 α := by - rw [uniformInducing_iff, UniformContinuous, tendsto_iff_comap, le_antisymm_iff, and_comm]; rfl +@[deprecated (since := "2024-10-05")] +alias uniformInducing_iff' := isUniformInducing_iff' -protected lemma Filter.HasBasis.uniformInducing_iff {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} +protected lemma Filter.HasBasis.isUniformInducing_iff {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} (h : (𝓤 α).HasBasis p s) (h' : (𝓤 β).HasBasis p' s') {f : α → β} : - UniformInducing f ↔ + IsUniformInducing f ↔ (∀ i, p' i → ∃ j, p j ∧ ∀ x y, (x, y) ∈ s j → (f x, f y) ∈ s' i) ∧ (∀ j, p j → ∃ i, p' i ∧ ∀ x y, (f x, f y) ∈ s' i → (x, y) ∈ s j) := by - simp [uniformInducing_iff', h.uniformContinuous_iff h', (h'.comap _).le_basis_iff h, subset_def] + simp [isUniformInducing_iff', h.uniformContinuous_iff h', (h'.comap _).le_basis_iff h, subset_def] -theorem UniformInducing.mk' {f : α → β} - (h : ∀ s, s ∈ 𝓤 α ↔ ∃ t ∈ 𝓤 β, ∀ x y : α, (f x, f y) ∈ t → (x, y) ∈ s) : UniformInducing f := +@[deprecated (since := "2024-10-05")] +alias Filter.HasBasis.uniformInducing_iff := Filter.HasBasis.isUniformInducing_iff + +theorem IsUniformInducing.mk' {f : α → β} + (h : ∀ s, s ∈ 𝓤 α ↔ ∃ t ∈ 𝓤 β, ∀ x y : α, (f x, f y) ∈ t → (x, y) ∈ s) : IsUniformInducing f := ⟨by simp [eq_comm, Filter.ext_iff, subset_def, h]⟩ -theorem uniformInducing_id : UniformInducing (@id α) := +@[deprecated (since := "2024-10-05")] +alias UniformInducing.mk' := IsUniformInducing.mk' + +theorem IsUniformInducing.id : IsUniformInducing (@id α) := ⟨by rw [← Prod.map_def, Prod.map_id, comap_id]⟩ -theorem UniformInducing.comp {g : β → γ} (hg : UniformInducing g) {f : α → β} - (hf : UniformInducing f) : UniformInducing (g ∘ f) := +@[deprecated (since := "2024-10-05")] +alias uniformInducing_id := IsUniformInducing.id + +theorem IsUniformInducing.comp {g : β → γ} (hg : IsUniformInducing g) {f : α → β} + (hf : IsUniformInducing f) : IsUniformInducing (g ∘ f) := ⟨by rw [← hf.1, ← hg.1, comap_comap]; rfl⟩ -theorem UniformInducing.of_comp_iff {g : β → γ} (hg : UniformInducing g) {f : α → β} : - UniformInducing (g ∘ f) ↔ UniformInducing f := by +@[deprecated (since := "2024-10-05")] +alias UniformInducing.comp := IsUniformInducing.comp + +theorem IsUniformInducing.of_comp_iff {g : β → γ} (hg : IsUniformInducing g) {f : α → β} : + IsUniformInducing (g ∘ f) ↔ IsUniformInducing f := by refine ⟨fun h ↦ ?_, hg.comp⟩ - rw [uniformInducing_iff, ← hg.comap_uniformity, comap_comap, ← h.comap_uniformity, + rw [isUniformInducing_iff, ← hg.comap_uniformity, comap_comap, ← h.comap_uniformity, Function.comp_def, Function.comp_def] -theorem UniformInducing.basis_uniformity {f : α → β} (hf : UniformInducing f) {ι : Sort*} +@[deprecated (since := "2024-10-05")] +alias UniformInducing.of_comp_iff := IsUniformInducing.of_comp_iff + +theorem IsUniformInducing.basis_uniformity {f : α → β} (hf : IsUniformInducing f) {ι : Sort*} {p : ι → Prop} {s : ι → Set (β × β)} (H : (𝓤 β).HasBasis p s) : (𝓤 α).HasBasis p fun i => Prod.map f f ⁻¹' s i := hf.1 ▸ H.comap _ -theorem UniformInducing.cauchy_map_iff {f : α → β} (hf : UniformInducing f) {F : Filter α} : +@[deprecated (since := "2024-10-05")] +alias UniformInducing.basis_uniformity := IsUniformInducing.basis_uniformity + +theorem IsUniformInducing.cauchy_map_iff {f : α → β} (hf : IsUniformInducing f) {F : Filter α} : Cauchy (map f F) ↔ Cauchy F := by simp only [Cauchy, map_neBot_iff, prod_map_map_eq, map_le_iff_le_comap, ← hf.comap_uniformity] -theorem uniformInducing_of_compose {f : α → β} {g : β → γ} (hf : UniformContinuous f) - (hg : UniformContinuous g) (hgf : UniformInducing (g ∘ f)) : UniformInducing f := by +@[deprecated (since := "2024-10-05")] +alias UniformInducing.cauchy_map_iff := IsUniformInducing.cauchy_map_iff + +theorem IsUniformInducing.of_comp {f : α → β} {g : β → γ} (hf : UniformContinuous f) + (hg : UniformContinuous g) (hgf : IsUniformInducing (g ∘ f)) : IsUniformInducing f := by refine ⟨le_antisymm ?_ hf.le_comap⟩ rw [← hgf.1, ← Prod.map_def, ← Prod.map_def, ← Prod.map_comp_map f f g g, ← comap_comap] exact comap_mono hg.le_comap -theorem UniformInducing.uniformContinuous {f : α → β} (hf : UniformInducing f) : - UniformContinuous f := (uniformInducing_iff'.1 hf).1 +@[deprecated (since := "2024-10-05")] +alias uniformInducing_of_compose := IsUniformInducing.of_comp -theorem UniformInducing.uniformContinuous_iff {f : α → β} {g : β → γ} (hg : UniformInducing g) : +theorem IsUniformInducing.uniformContinuous {f : α → β} (hf : IsUniformInducing f) : + UniformContinuous f := (isUniformInducing_iff'.1 hf).1 + +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformContinuous := IsUniformInducing.uniformContinuous + +theorem IsUniformInducing.uniformContinuous_iff {f : α → β} {g : β → γ} (hg : IsUniformInducing g) : UniformContinuous f ↔ UniformContinuous (g ∘ f) := by dsimp only [UniformContinuous, Tendsto] simp only [← hg.comap_uniformity, ← map_le_iff_le_comap, Filter.map_map, Function.comp_def] -protected theorem UniformInducing.uniformInducing_comp_iff {f : α → β} {g : β → γ} - (hg : UniformInducing g) : UniformInducing (g ∘ f) ↔ UniformInducing f := by - simp only [uniformInducing_iff, ← hg.comap_uniformity, comap_comap, Function.comp_def] +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformContinuous_iff := IsUniformInducing.uniformContinuous_iff + +protected theorem IsUniformInducing.isUniformInducing_comp_iff {f : α → β} {g : β → γ} + (hg : IsUniformInducing g) : IsUniformInducing (g ∘ f) ↔ IsUniformInducing f := by + simp only [isUniformInducing_iff, ← hg.comap_uniformity, comap_comap, Function.comp_def] -theorem UniformInducing.uniformContinuousOn_iff {f : α → β} {g : β → γ} {S : Set α} - (hg : UniformInducing g) : +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformInducing_comp_iff := IsUniformInducing.isUniformInducing_comp_iff + +theorem IsUniformInducing.uniformContinuousOn_iff {f : α → β} {g : β → γ} {S : Set α} + (hg : IsUniformInducing g) : UniformContinuousOn f S ↔ UniformContinuousOn (g ∘ f) S := by dsimp only [UniformContinuousOn, Tendsto] rw [← hg.comap_uniformity, ← map_le_iff_le_comap, Filter.map_map, comp_def, comp_def] -theorem UniformInducing.inducing {f : α → β} (h : UniformInducing f) : Inducing f := by +@[deprecated (since := "2024-10-05")] +alias UniformInducing.uniformContinuousOn_iff := IsUniformInducing.uniformContinuousOn_iff + +theorem IsUniformInducing.inducing {f : α → β} (h : IsUniformInducing f) : Inducing f := by obtain rfl := h.comap_uniformSpace exact inducing_induced f -theorem UniformInducing.prod {α' : Type*} {β' : Type*} [UniformSpace α'] [UniformSpace β'] - {e₁ : α → α'} {e₂ : β → β'} (h₁ : UniformInducing e₁) (h₂ : UniformInducing e₂) : - UniformInducing fun p : α × β => (e₁ p.1, e₂ p.2) := +@[deprecated (since := "2024-10-05")] +alias UniformInducing.inducing := IsUniformInducing.inducing + +theorem IsUniformInducing.prod {α' : Type*} {β' : Type*} [UniformSpace α'] [UniformSpace β'] + {e₁ : α → α'} {e₂ : β → β'} (h₁ : IsUniformInducing e₁) (h₂ : IsUniformInducing e₂) : + IsUniformInducing fun p : α × β => (e₁ p.1, e₂ p.2) := ⟨by simp [Function.comp_def, uniformity_prod, ← h₁.1, ← h₂.1, comap_inf, comap_comap]⟩ -theorem UniformInducing.denseInducing {f : α → β} (h : UniformInducing f) (hd : DenseRange f) : - DenseInducing f := +@[deprecated (since := "2024-10-05")] +alias UniformInducing.prod := IsUniformInducing.prod + +lemma IsUniformInducing.isDenseInducing (h : IsUniformInducing f) (hd : DenseRange f) : + IsDenseInducing f := { dense := hd induced := h.inducing.induced } -theorem SeparationQuotient.uniformInducing_mk : UniformInducing (mk : α → SeparationQuotient α) := +@[deprecated (since := "2024-10-05")] +alias UniformInducing.isDenseInducing := IsUniformInducing.isDenseInducing + +lemma SeparationQuotient.isUniformInducing_mk : + IsUniformInducing (mk : α → SeparationQuotient α) := ⟨comap_mk_uniformity⟩ -protected theorem UniformInducing.injective [T0Space α] {f : α → β} (h : UniformInducing f) : +@[deprecated (since := "2024-10-05")] +alias SeparationQuotient.uniformInducing_mk := SeparationQuotient.isUniformInducing_mk + +protected theorem IsUniformInducing.injective [T0Space α] {f : α → β} (h : IsUniformInducing f) : Injective f := h.inducing.injective +@[deprecated (since := "2024-10-05")] +alias UniformInducing.injective := IsUniformInducing.injective + /-! ### Uniform embeddings -/ @@ -130,70 +194,118 @@ protected theorem UniformInducing.injective [T0Space α] {f : α → β} (h : Un /-- A map `f : α → β` between uniform spaces is a *uniform embedding* if it is uniform inducing and injective. If `α` is a separated space, then the latter assumption follows from the former. -/ @[mk_iff] -structure UniformEmbedding (f : α → β) extends UniformInducing f : Prop where +structure IsUniformEmbedding (f : α → β) extends IsUniformInducing f : Prop where /-- A uniform embedding is injective. -/ inj : Function.Injective f -theorem uniformEmbedding_iff' {f : α → β} : - UniformEmbedding f ↔ Injective f ∧ UniformContinuous f ∧ comap (Prod.map f f) (𝓤 β) ≤ 𝓤 α := by - rw [uniformEmbedding_iff, and_comm, uniformInducing_iff'] +lemma IsUniformEmbedding.isUniformInducing (hf : IsUniformEmbedding f) : IsUniformInducing f := + hf.toIsUniformInducing -theorem Filter.HasBasis.uniformEmbedding_iff' {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} +@[deprecated (since := "2024-10-03")] alias UniformEmbedding := IsUniformEmbedding + +theorem isUniformEmbedding_iff' {f : α → β} : + IsUniformEmbedding f ↔ + Injective f ∧ UniformContinuous f ∧ comap (Prod.map f f) (𝓤 β) ≤ 𝓤 α := by + rw [isUniformEmbedding_iff, and_comm, isUniformInducing_iff'] + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_iff' := isUniformEmbedding_iff' + +theorem Filter.HasBasis.isUniformEmbedding_iff' {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} (h : (𝓤 α).HasBasis p s) (h' : (𝓤 β).HasBasis p' s') {f : α → β} : - UniformEmbedding f ↔ Injective f ∧ + IsUniformEmbedding f ↔ Injective f ∧ (∀ i, p' i → ∃ j, p j ∧ ∀ x y, (x, y) ∈ s j → (f x, f y) ∈ s' i) ∧ (∀ j, p j → ∃ i, p' i ∧ ∀ x y, (f x, f y) ∈ s' i → (x, y) ∈ s j) := by - rw [uniformEmbedding_iff, and_comm, h.uniformInducing_iff h'] + rw [isUniformEmbedding_iff, and_comm, h.isUniformInducing_iff h'] -theorem Filter.HasBasis.uniformEmbedding_iff {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} +@[deprecated (since := "2024-10-01")] +alias Filter.HasBasis.uniformEmbedding_iff' := Filter.HasBasis.isUniformEmbedding_iff' + +theorem Filter.HasBasis.isUniformEmbedding_iff {ι ι'} {p : ι → Prop} {p' : ι' → Prop} {s s'} (h : (𝓤 α).HasBasis p s) (h' : (𝓤 β).HasBasis p' s') {f : α → β} : - UniformEmbedding f ↔ Injective f ∧ UniformContinuous f ∧ + IsUniformEmbedding f ↔ Injective f ∧ UniformContinuous f ∧ (∀ j, p j → ∃ i, p' i ∧ ∀ x y, (f x, f y) ∈ s' i → (x, y) ∈ s j) := by - simp only [h.uniformEmbedding_iff' h', h.uniformContinuous_iff h'] + simp only [h.isUniformEmbedding_iff' h', h.uniformContinuous_iff h'] + +@[deprecated (since := "2024-10-01")] +alias Filter.HasBasis.uniformEmbedding_iff := Filter.HasBasis.isUniformEmbedding_iff -theorem uniformEmbedding_subtype_val {p : α → Prop} : - UniformEmbedding (Subtype.val : Subtype p → α) := +theorem isUniformEmbedding_subtype_val {p : α → Prop} : + IsUniformEmbedding (Subtype.val : Subtype p → α) := { comap_uniformity := rfl inj := Subtype.val_injective } -theorem uniformEmbedding_set_inclusion {s t : Set α} (hst : s ⊆ t) : - UniformEmbedding (inclusion hst) where +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_subtype_val := isUniformEmbedding_subtype_val + +theorem isUniformEmbedding_set_inclusion {s t : Set α} (hst : s ⊆ t) : + IsUniformEmbedding (inclusion hst) where comap_uniformity := by rw [uniformity_subtype, uniformity_subtype, comap_comap]; rfl inj := inclusion_injective hst -theorem UniformEmbedding.comp {g : β → γ} (hg : UniformEmbedding g) {f : α → β} - (hf : UniformEmbedding f) : UniformEmbedding (g ∘ f) := - { hg.toUniformInducing.comp hf.toUniformInducing with inj := hg.inj.comp hf.inj } +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_set_inclusion := isUniformEmbedding_set_inclusion -theorem UniformEmbedding.of_comp_iff {g : β → γ} (hg : UniformEmbedding g) {f : α → β} : - UniformEmbedding (g ∘ f) ↔ UniformEmbedding f := by - simp_rw [uniformEmbedding_iff, hg.toUniformInducing.of_comp_iff, hg.inj.of_comp_iff f] +theorem IsUniformEmbedding.comp {g : β → γ} (hg : IsUniformEmbedding g) {f : α → β} + (hf : IsUniformEmbedding f) : IsUniformEmbedding (g ∘ f) := + { hg.isUniformInducing.comp hf.isUniformInducing with inj := hg.inj.comp hf.inj } -theorem Equiv.uniformEmbedding {α β : Type*} [UniformSpace α] [UniformSpace β] (f : α ≃ β) - (h₁ : UniformContinuous f) (h₂ : UniformContinuous f.symm) : UniformEmbedding f := - uniformEmbedding_iff'.2 ⟨f.injective, h₁, by rwa [← Equiv.prodCongr_apply, ← map_equiv_symm]⟩ +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.comp := IsUniformEmbedding.comp -theorem uniformEmbedding_inl : UniformEmbedding (Sum.inl : α → α ⊕ β) := - uniformEmbedding_iff'.2 ⟨Sum.inl_injective, uniformContinuous_inl, fun s hs => +theorem IsUniformEmbedding.of_comp_iff {g : β → γ} (hg : IsUniformEmbedding g) {f : α → β} : + IsUniformEmbedding (g ∘ f) ↔ IsUniformEmbedding f := by + simp_rw [isUniformEmbedding_iff, hg.isUniformInducing.of_comp_iff, hg.inj.of_comp_iff f] + +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.of_comp_iff := IsUniformEmbedding.of_comp_iff + +theorem Equiv.isUniformEmbedding {α β : Type*} [UniformSpace α] [UniformSpace β] (f : α ≃ β) + (h₁ : UniformContinuous f) (h₂ : UniformContinuous f.symm) : IsUniformEmbedding f := + isUniformEmbedding_iff'.2 ⟨f.injective, h₁, by rwa [← Equiv.prodCongr_apply, ← map_equiv_symm]⟩ + +@[deprecated (since := "2024-10-01")] +alias Equiv.uniformEmbedding := Equiv.isUniformEmbedding + +theorem isUniformEmbedding_inl : IsUniformEmbedding (Sum.inl : α → α ⊕ β) := + isUniformEmbedding_iff'.2 ⟨Sum.inl_injective, uniformContinuous_inl, fun s hs => ⟨Prod.map Sum.inl Sum.inl '' s ∪ range (Prod.map Sum.inr Sum.inr), union_mem_sup (image_mem_map hs) range_mem_map, fun x h => by simpa [Prod.map_apply'] using h⟩⟩ -theorem uniformEmbedding_inr : UniformEmbedding (Sum.inr : β → α ⊕ β) := - uniformEmbedding_iff'.2 ⟨Sum.inr_injective, uniformContinuous_inr, fun s hs => +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_inl := isUniformEmbedding_inl + +theorem isUniformEmbedding_inr : IsUniformEmbedding (Sum.inr : β → α ⊕ β) := + isUniformEmbedding_iff'.2 ⟨Sum.inr_injective, uniformContinuous_inr, fun s hs => ⟨range (Prod.map Sum.inl Sum.inl) ∪ Prod.map Sum.inr Sum.inr '' s, union_mem_sup range_mem_map (image_mem_map hs), fun x h => by simpa [Prod.map_apply'] using h⟩⟩ -/-- If the domain of a `UniformInducing` map `f` is a T₀ space, then `f` is injective, -hence it is a `UniformEmbedding`. -/ -protected theorem UniformInducing.uniformEmbedding [T0Space α] {f : α → β} - (hf : UniformInducing f) : UniformEmbedding f := +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_inr := isUniformEmbedding_inr + +/-- If the domain of a `IsUniformInducing` map `f` is a T₀ space, then `f` is injective, +hence it is a `IsUniformEmbedding`. -/ +protected theorem IsUniformInducing.isUniformEmbedding [T0Space α] {f : α → β} + (hf : IsUniformInducing f) : IsUniformEmbedding f := ⟨hf, hf.inducing.injective⟩ -theorem uniformEmbedding_iff_uniformInducing [T0Space α] {f : α → β} : - UniformEmbedding f ↔ UniformInducing f := - ⟨UniformEmbedding.toUniformInducing, UniformInducing.uniformEmbedding⟩ +@[deprecated (since := "2024-10-05")] +alias UniformInducing.isUniformEmbedding := IsUniformInducing.isUniformEmbedding + +@[deprecated (since := "2024-10-01")] +alias IsUniformInducing.uniformEmbedding := IsUniformInducing.isUniformEmbedding + +theorem isUniformEmbedding_iff_isUniformInducing [T0Space α] {f : α → β} : + IsUniformEmbedding f ↔ IsUniformInducing f := + ⟨IsUniformEmbedding.isUniformInducing, IsUniformInducing.isUniformEmbedding⟩ + +@[deprecated (since := "2024-10-05")] +alias isUniformEmbedding_iff_uniformInducing := isUniformEmbedding_iff_isUniformInducing + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_iff_isUniformInducing := isUniformEmbedding_iff_isUniformInducing /-- If a map `f : α → β` sends any two distinct points to point that are **not** related by a fixed `s ∈ 𝓤 β`, then `f` is uniform inducing with respect to the discrete uniformity on `α`: @@ -210,29 +322,41 @@ theorem comap_uniformity_of_spaced_out {α} {f : α → β} {s : Set (β × β)} /-- If a map `f : α → β` sends any two distinct points to point that are **not** related by a fixed `s ∈ 𝓤 β`, then `f` is a uniform embedding with respect to the discrete uniformity on `α`. -/ -theorem uniformEmbedding_of_spaced_out {α} {f : α → β} {s : Set (β × β)} (hs : s ∈ 𝓤 β) - (hf : Pairwise fun x y => (f x, f y) ∉ s) : @UniformEmbedding α β ⊥ ‹_› f := by +theorem isUniformEmbedding_of_spaced_out {α} {f : α → β} {s : Set (β × β)} (hs : s ∈ 𝓤 β) + (hf : Pairwise fun x y => (f x, f y) ∉ s) : @IsUniformEmbedding α β ⊥ ‹_› f := by let _ : UniformSpace α := ⊥; have := discreteTopology_bot α - exact UniformInducing.uniformEmbedding ⟨comap_uniformity_of_spaced_out hs hf⟩ + exact IsUniformInducing.isUniformEmbedding ⟨comap_uniformity_of_spaced_out hs hf⟩ + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_of_spaced_out := isUniformEmbedding_of_spaced_out -protected theorem UniformEmbedding.embedding {f : α → β} (h : UniformEmbedding f) : Embedding f := - { toInducing := h.toUniformInducing.inducing +protected lemma IsUniformEmbedding.embedding {f : α → β} (h : IsUniformEmbedding f) : Embedding f := + { toInducing := h.isUniformInducing.inducing inj := h.inj } -theorem UniformEmbedding.denseEmbedding {f : α → β} (h : UniformEmbedding f) (hd : DenseRange f) : - DenseEmbedding f := +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.embedding := IsUniformEmbedding.embedding + +theorem IsUniformEmbedding.isDenseEmbedding {f : α → β} (h : IsUniformEmbedding f) + (hd : DenseRange f) : IsDenseEmbedding f := { h.embedding with dense := hd } +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.isDenseEmbedding := IsUniformEmbedding.isDenseEmbedding + +@[deprecated (since := "2024-09-30")] +alias IsUniformEmbedding.denseEmbedding := IsUniformEmbedding.isDenseEmbedding + theorem closedEmbedding_of_spaced_out {α} [TopologicalSpace α] [DiscreteTopology α] [T0Space β] {f : α → β} {s : Set (β × β)} (hs : s ∈ 𝓤 β) (hf : Pairwise fun x y => (f x, f y) ∉ s) : ClosedEmbedding f := by rcases @DiscreteTopology.eq_bot α _ _ with rfl; let _ : UniformSpace α := ⊥ exact - { (uniformEmbedding_of_spaced_out hs hf).embedding with + { (isUniformEmbedding_of_spaced_out hs hf).embedding with isClosed_range := isClosed_range_of_spaced_out hs hf } -theorem closure_image_mem_nhds_of_uniformInducing {s : Set (α × α)} {e : α → β} (b : β) - (he₁ : UniformInducing e) (he₂ : DenseInducing e) (hs : s ∈ 𝓤 α) : +theorem closure_image_mem_nhds_of_isUniformInducing {s : Set (α × α)} {e : α → β} (b : β) + (he₁ : IsUniformInducing e) (he₂ : IsDenseInducing e) (hs : s ∈ 𝓤 α) : ∃ a, closure (e '' { a' | (a, a') ∈ s }) ∈ 𝓝 b := by obtain ⟨U, ⟨hU, hUo, hsymm⟩, hs⟩ : ∃ U, (U ∈ 𝓤 β ∧ IsOpen U ∧ SymmetricRel U) ∧ Prod.map e e ⁻¹' U ⊆ s := by @@ -245,68 +369,101 @@ theorem closure_image_mem_nhds_of_uniformInducing {s : Set (α × α)} {e : α rcases he₂.dense.mem_nhds (inter_mem hV (ho.mem_nhds hy)) with ⟨x, hxV, hxU⟩ exact ⟨e x, hxV, mem_image_of_mem e hxU⟩ -theorem uniformEmbedding_subtypeEmb (p : α → Prop) {e : α → β} (ue : UniformEmbedding e) - (de : DenseEmbedding e) : UniformEmbedding (DenseEmbedding.subtypeEmb p e) := +@[deprecated (since := "2024-10-05")] +alias closure_image_mem_nhds_of_uniformInducing := closure_image_mem_nhds_of_isUniformInducing + +theorem isUniformEmbedding_subtypeEmb (p : α → Prop) {e : α → β} (ue : IsUniformEmbedding e) + (de : IsDenseEmbedding e) : IsUniformEmbedding (IsDenseEmbedding.subtypeEmb p e) := { comap_uniformity := by - simp [comap_comap, Function.comp_def, DenseEmbedding.subtypeEmb, uniformity_subtype, + simp [comap_comap, Function.comp_def, IsDenseEmbedding.subtypeEmb, uniformity_subtype, ue.comap_uniformity.symm] inj := (de.subtype p).inj } -theorem UniformEmbedding.prod {α' : Type*} {β' : Type*} [UniformSpace α'] [UniformSpace β'] - {e₁ : α → α'} {e₂ : β → β'} (h₁ : UniformEmbedding e₁) (h₂ : UniformEmbedding e₂) : - UniformEmbedding fun p : α × β => (e₁ p.1, e₂ p.2) := - { h₁.toUniformInducing.prod h₂.toUniformInducing with inj := h₁.inj.prodMap h₂.inj } +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_subtypeEmb := isUniformEmbedding_subtypeEmb + +theorem IsUniformEmbedding.prod {α' : Type*} {β' : Type*} [UniformSpace α'] [UniformSpace β'] + {e₁ : α → α'} {e₂ : β → β'} (h₁ : IsUniformEmbedding e₁) (h₂ : IsUniformEmbedding e₂) : + IsUniformEmbedding fun p : α × β => (e₁ p.1, e₂ p.2) := + { h₁.isUniformInducing.prod h₂.isUniformInducing with inj := h₁.inj.prodMap h₂.inj } + +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.prod := IsUniformEmbedding.prod /-- A set is complete iff its image under a uniform inducing map is complete. -/ -theorem isComplete_image_iff {m : α → β} {s : Set α} (hm : UniformInducing m) : +theorem isComplete_image_iff {m : α → β} {s : Set α} (hm : IsUniformInducing m) : IsComplete (m '' s) ↔ IsComplete s := by have fact1 : SurjOn (map m) (Iic <| 𝓟 s) (Iic <| 𝓟 <| m '' s) := surjOn_image .. |>.filter_map_Iic have fact2 : MapsTo (map m) (Iic <| 𝓟 s) (Iic <| 𝓟 <| m '' s) := mapsTo_image .. |>.filter_map_Iic simp_rw [IsComplete, imp.swap (a := Cauchy _), ← mem_Iic (b := 𝓟 _), fact1.forall fact2, hm.cauchy_map_iff, exists_mem_image, map_le_iff_le_comap, hm.inducing.nhds_eq_comap] -/-- If `f : X → Y` is an `UniformInducing` map, the image `f '' s` of a set `s` is complete +/-- If `f : X → Y` is an `IsUniformInducing` map, the image `f '' s` of a set `s` is complete if and only if `s` is complete. -/ -theorem UniformInducing.isComplete_iff {f : α → β} {s : Set α} (hf : UniformInducing f) : +theorem IsUniformInducing.isComplete_iff {f : α → β} {s : Set α} (hf : IsUniformInducing f) : IsComplete (f '' s) ↔ IsComplete s := isComplete_image_iff hf -/-- If `f : X → Y` is an `UniformEmbedding`, the image `f '' s` of a set `s` is complete +@[deprecated (since := "2024-10-05")] +alias UniformInducing.isComplete_iff := IsUniformInducing.isComplete_iff + +/-- If `f : X → Y` is an `IsUniformEmbedding`, the image `f '' s` of a set `s` is complete if and only if `s` is complete. -/ -theorem UniformEmbedding.isComplete_iff {f : α → β} {s : Set α} (hf : UniformEmbedding f) : - IsComplete (f '' s) ↔ IsComplete s := hf.toUniformInducing.isComplete_iff +theorem IsUniformEmbedding.isComplete_iff {f : α → β} {s : Set α} (hf : IsUniformEmbedding f) : + IsComplete (f '' s) ↔ IsComplete s := hf.isUniformInducing.isComplete_iff + +@[deprecated (since := "2024-10-01")] +alias UniformEmbedding.isComplete_iff := IsUniformEmbedding.isComplete_iff /-- Sets of a subtype are complete iff their image under the coercion is complete. -/ theorem Subtype.isComplete_iff {p : α → Prop} {s : Set { x // p x }} : IsComplete s ↔ IsComplete ((↑) '' s : Set α) := - uniformEmbedding_subtype_val.isComplete_iff.symm + isUniformEmbedding_subtype_val.isComplete_iff.symm alias ⟨isComplete_of_complete_image, _⟩ := isComplete_image_iff -theorem completeSpace_iff_isComplete_range {f : α → β} (hf : UniformInducing f) : +theorem completeSpace_iff_isComplete_range {f : α → β} (hf : IsUniformInducing f) : CompleteSpace α ↔ IsComplete (range f) := by rw [completeSpace_iff_isComplete_univ, ← isComplete_image_iff hf, image_univ] -theorem UniformInducing.isComplete_range [CompleteSpace α] {f : α → β} (hf : UniformInducing f) : +alias ⟨_, IsUniformInducing.completeSpace⟩ := completeSpace_iff_isComplete_range + +@[deprecated (since := "2024-10-08")] alias UniformInducing.completeSpace := + IsUniformInducing.completeSpace + +lemma IsUniformInducing.isComplete_range [CompleteSpace α] (hf : IsUniformInducing f) : IsComplete (range f) := (completeSpace_iff_isComplete_range hf).1 ‹_› +@[deprecated (since := "2024-10-05")] +alias UniformInducing.isComplete_range := IsUniformInducing.isComplete_range + +/-- If `f` is a surjective uniform inducing map, +then its domain is a complete space iff its codomain is a complete space. +See also `_root_.completeSpace_congr` for a version that assumes `f` to be an equivalence. -/ +theorem IsUniformInducing.completeSpace_congr {f : α → β} (hf : IsUniformInducing f) + (hsurj : f.Surjective) : CompleteSpace α ↔ CompleteSpace β := by + rw [completeSpace_iff_isComplete_range hf, hsurj.range_eq, completeSpace_iff_isComplete_univ] + +@[deprecated (since := "2024-10-05")] +alias UniformInducing.completeSpace_congr := IsUniformInducing.completeSpace_congr + theorem SeparationQuotient.completeSpace_iff : - CompleteSpace (SeparationQuotient α) ↔ CompleteSpace α := by - rw [completeSpace_iff_isComplete_univ, ← range_mk, - ← completeSpace_iff_isComplete_range uniformInducing_mk] + CompleteSpace (SeparationQuotient α) ↔ CompleteSpace α := + .symm <| isUniformInducing_mk.completeSpace_congr surjective_mk instance SeparationQuotient.instCompleteSpace [CompleteSpace α] : CompleteSpace (SeparationQuotient α) := completeSpace_iff.2 ‹_› -theorem completeSpace_congr {e : α ≃ β} (he : UniformEmbedding e) : - CompleteSpace α ↔ CompleteSpace β := by - rw [completeSpace_iff_isComplete_range he.toUniformInducing, e.range_eq_univ, - completeSpace_iff_isComplete_univ] +/-- See also `IsUniformInducing.completeSpace_congr` +for a version that works for non-injective maps. -/ +theorem completeSpace_congr {e : α ≃ β} (he : IsUniformEmbedding e) : + CompleteSpace α ↔ CompleteSpace β := + he.completeSpace_congr e.surjective -theorem completeSpace_coe_iff_isComplete {s : Set α} : CompleteSpace s ↔ IsComplete s := - (completeSpace_iff_isComplete_range uniformEmbedding_subtype_val.toUniformInducing).trans <| by - rw [Subtype.range_coe] +theorem completeSpace_coe_iff_isComplete {s : Set α} : CompleteSpace s ↔ IsComplete s := by + rw [completeSpace_iff_isComplete_range isUniformEmbedding_subtype_val.isUniformInducing, + Subtype.range_coe] alias ⟨_, IsComplete.completeSpace_coe⟩ := completeSpace_coe_iff_isComplete @@ -314,12 +471,14 @@ theorem IsClosed.completeSpace_coe [CompleteSpace α] {s : Set α} (hs : IsClose CompleteSpace s := hs.isComplete.completeSpace_coe +theorem completeSpace_ulift_iff : CompleteSpace (ULift α) ↔ CompleteSpace α := + IsUniformInducing.completeSpace_congr ⟨rfl⟩ ULift.down_surjective + /-- The lift of a complete space to another universe is still complete. -/ -instance ULift.completeSpace [h : CompleteSpace α] : CompleteSpace (ULift α) := - haveI : UniformEmbedding (@Equiv.ulift α) := ⟨⟨rfl⟩, ULift.down_injective⟩ - (completeSpace_congr this).2 h +instance ULift.instCompleteSpace [CompleteSpace α] : CompleteSpace (ULift α) := + completeSpace_ulift_iff.2 ‹_› -theorem completeSpace_extension {m : β → α} (hm : UniformInducing m) (dense : DenseRange m) +theorem completeSpace_extension {m : β → α} (hm : IsUniformInducing m) (dense : DenseRange m) (h : ∀ f : Filter β, Cauchy f → ∃ x : α, map m f ≤ 𝓝 x) : CompleteSpace α := ⟨fun {f : Filter α} (hf : Cauchy f) => let p : Set (α × α) → Set α → Set α := fun s t => { y : α | ∃ x : α, x ∈ t ∧ (x, y) ∈ s } @@ -365,7 +524,7 @@ theorem completeSpace_extension {m : β → α} (hm : UniformInducing m) (dense _ ≤ 𝓝 x := le_nhds_of_cauchy_adhp ‹Cauchy g› this ⟩⟩ -lemma totallyBounded_image_iff {f : α → β} {s : Set α} (hf : UniformInducing f) : +lemma totallyBounded_image_iff {f : α → β} {s : Set α} (hf : IsUniformInducing f) : TotallyBounded (f '' s) ↔ TotallyBounded s := by refine ⟨fun hs ↦ ?_, fun h ↦ h.image hf.uniformContinuous⟩ simp_rw [(hf.basis_uniformity (basis_sets _)).totallyBounded_iff] @@ -374,21 +533,24 @@ lemma totallyBounded_image_iff {f : α → β} {s : Set α} (hf : UniformInducin use u, hfin rwa [biUnion_image, image_subset_iff, preimage_iUnion₂] at h -theorem totallyBounded_preimage {f : α → β} {s : Set β} (hf : UniformInducing f) +theorem totallyBounded_preimage {f : α → β} {s : Set β} (hf : IsUniformInducing f) (hs : TotallyBounded s) : TotallyBounded (f ⁻¹' s) := (totallyBounded_image_iff hf).1 <| hs.subset <| image_preimage_subset .. instance CompleteSpace.sum [CompleteSpace α] [CompleteSpace β] : CompleteSpace (α ⊕ β) := by rw [completeSpace_iff_isComplete_univ, ← range_inl_union_range_inr] - exact uniformEmbedding_inl.toUniformInducing.isComplete_range.union - uniformEmbedding_inr.toUniformInducing.isComplete_range + exact isUniformEmbedding_inl.isUniformInducing.isComplete_range.union + isUniformEmbedding_inr.isUniformInducing.isComplete_range end -theorem uniformEmbedding_comap {α : Type*} {β : Type*} {f : α → β} [u : UniformSpace β] - (hf : Function.Injective f) : @UniformEmbedding α β (UniformSpace.comap f u) u f := - @UniformEmbedding.mk _ _ (UniformSpace.comap f u) _ _ - (@UniformInducing.mk _ _ (UniformSpace.comap f u) _ _ rfl) hf +theorem isUniformEmbedding_comap {α : Type*} {β : Type*} {f : α → β} [u : UniformSpace β] + (hf : Function.Injective f) : @IsUniformEmbedding α β (UniformSpace.comap f u) u f := + @IsUniformEmbedding.mk _ _ (UniformSpace.comap f u) _ _ + (@IsUniformInducing.mk _ _ (UniformSpace.comap f u) _ _ rfl) hf + +@[deprecated (since := "2024-10-01")] +alias uniformEmbedding_comap := isUniformEmbedding_comap /-- Pull back a uniform space structure by an embedding, adjusting the new uniform structure to make sure that its topology is defeq to the original one. -/ @@ -396,23 +558,26 @@ def Embedding.comapUniformSpace {α β} [TopologicalSpace α] [u : UniformSpace (h : Embedding f) : UniformSpace α := (u.comap f).replaceTopology h.induced -theorem Embedding.to_uniformEmbedding {α β} [TopologicalSpace α] [u : UniformSpace β] (f : α → β) - (h : Embedding f) : @UniformEmbedding α β (h.comapUniformSpace f) u f := +theorem Embedding.to_isUniformEmbedding {α β} [TopologicalSpace α] [u : UniformSpace β] (f : α → β) + (h : Embedding f) : @IsUniformEmbedding α β (h.comapUniformSpace f) u f := let _ := h.comapUniformSpace f { comap_uniformity := rfl inj := h.inj } +@[deprecated (since := "2024-10-01")] +alias Embedding.to_uniformEmbedding := Embedding.to_isUniformEmbedding + section UniformExtension variable {α : Type*} {β : Type*} {γ : Type*} [UniformSpace α] [UniformSpace β] [UniformSpace γ] - {e : β → α} (h_e : UniformInducing e) (h_dense : DenseRange e) {f : β → γ} + {e : β → α} (h_e : IsUniformInducing e) (h_dense : DenseRange e) {f : β → γ} (h_f : UniformContinuous f) -local notation "ψ" => DenseInducing.extend (UniformInducing.denseInducing h_e h_dense) f +local notation "ψ" => IsDenseInducing.extend (IsUniformInducing.isDenseInducing h_e h_dense) f include h_e h_dense h_f in theorem uniformly_extend_exists [CompleteSpace γ] (a : α) : ∃ c, Tendsto f (comap e (𝓝 a)) (𝓝 c) := - let de := h_e.denseInducing h_dense + let de := h_e.isDenseInducing h_dense have : Cauchy (𝓝 a) := cauchy_nhds have : Cauchy (comap e (𝓝 a)) := this.comap' (le_of_eq h_e.comap_uniformity) (de.comap_nhds_neBot _) @@ -420,24 +585,25 @@ theorem uniformly_extend_exists [CompleteSpace γ] (a : α) : ∃ c, Tendsto f ( CompleteSpace.complete this theorem uniform_extend_subtype [CompleteSpace γ] {p : α → Prop} {e : α → β} {f : α → γ} {b : β} - {s : Set α} (hf : UniformContinuous fun x : Subtype p => f x.val) (he : UniformEmbedding e) + {s : Set α} (hf : UniformContinuous fun x : Subtype p => f x.val) (he : IsUniformEmbedding e) (hd : ∀ x : β, x ∈ closure (range e)) (hb : closure (e '' s) ∈ 𝓝 b) (hs : IsClosed s) (hp : ∀ x ∈ s, p x) : ∃ c, Tendsto f (comap e (𝓝 b)) (𝓝 c) := by - have de : DenseEmbedding e := he.denseEmbedding hd - have de' : DenseEmbedding (DenseEmbedding.subtypeEmb p e) := de.subtype p - have ue' : UniformEmbedding (DenseEmbedding.subtypeEmb p e) := uniformEmbedding_subtypeEmb _ he de + have de : IsDenseEmbedding e := he.isDenseEmbedding hd + have de' : IsDenseEmbedding (IsDenseEmbedding.subtypeEmb p e) := de.subtype p + have ue' : IsUniformEmbedding (IsDenseEmbedding.subtypeEmb p e) := + isUniformEmbedding_subtypeEmb _ he de have : b ∈ closure (e '' { x | p x }) := (closure_mono <| monotone_image <| hp) (mem_of_mem_nhds hb) - let ⟨c, hc⟩ := uniformly_extend_exists ue'.toUniformInducing de'.dense hf ⟨b, this⟩ + let ⟨c, hc⟩ := uniformly_extend_exists ue'.isUniformInducing de'.dense hf ⟨b, this⟩ replace hc : Tendsto (f ∘ Subtype.val (p := p)) (((𝓝 b).comap e).comap Subtype.val) (𝓝 c) := by - simpa only [nhds_subtype_eq_comap, comap_comap, DenseEmbedding.subtypeEmb_coe] using hc + simpa only [nhds_subtype_eq_comap, comap_comap, IsDenseEmbedding.subtypeEmb_coe] using hc refine ⟨c, (tendsto_comap'_iff ?_).1 hc⟩ rw [Subtype.range_coe_subtype] exact ⟨_, hb, by rwa [← de.toInducing.closure_eq_preimage_closure_image, hs.closure_eq]⟩ include h_e h_f in theorem uniformly_extend_spec [CompleteSpace γ] (a : α) : Tendsto f (comap e (𝓝 a)) (𝓝 (ψ a)) := by - simpa only [DenseInducing.extend] using + simpa only [IsDenseInducing.extend] using tendsto_nhds_limUnder (uniformly_extend_exists h_e ‹_› h_f _) include h_f in @@ -446,7 +612,7 @@ theorem uniformContinuous_uniformly_extend [CompleteSpace γ] : UniformContinuou have h_pnt : ∀ {a m}, m ∈ 𝓝 a → ∃ c ∈ f '' (e ⁻¹' m), (c, ψ a) ∈ s ∧ (ψ a, c) ∈ s := fun {a m} hm => have nb : NeBot (map f (comap e (𝓝 a))) := - ((h_e.denseInducing h_dense).comap_nhds_neBot _).map _ + ((h_e.isDenseInducing h_dense).comap_nhds_neBot _).map _ have : f '' (e ⁻¹' m) ∩ ({ c | (c, ψ a) ∈ s } ∩ { c | (ψ a, c) ∈ s }) ∈ map f (comap e (𝓝 a)) := inter_mem (image_mem_map <| preimage_mem_comap <| hm) @@ -471,9 +637,9 @@ variable [T0Space γ] include h_f in theorem uniformly_extend_of_ind (b : β) : ψ (e b) = f b := - DenseInducing.extend_eq_at _ h_f.continuous.continuousAt + IsDenseInducing.extend_eq_at _ h_f.continuous.continuousAt theorem uniformly_extend_unique {g : α → γ} (hg : ∀ b, g (e b) = f b) (hc : Continuous g) : ψ = g := - DenseInducing.extend_unique _ hg hc + IsDenseInducing.extend_unique _ hg hc end UniformExtension diff --git a/Mathlib/Topology/UnitInterval.lean b/Mathlib/Topology/UnitInterval.lean index 69b4eada244b4..55c6405dda1b6 100644 --- a/Mathlib/Topology/UnitInterval.lean +++ b/Mathlib/Topology/UnitInterval.lean @@ -40,10 +40,10 @@ theorem one_mem : (1 : ℝ) ∈ I := ⟨zero_le_one, le_rfl⟩ theorem mul_mem {x y : ℝ} (hx : x ∈ I) (hy : y ∈ I) : x * y ∈ I := - ⟨mul_nonneg hx.1 hy.1, mul_le_one hx.2 hy.1 hy.2⟩ + ⟨mul_nonneg hx.1 hy.1, mul_le_one₀ hx.2 hy.1 hy.2⟩ theorem div_mem {x y : ℝ} (hx : 0 ≤ x) (hy : 0 ≤ y) (hxy : x ≤ y) : x / y ∈ I := - ⟨div_nonneg hx hy, div_le_one_of_le hxy hy⟩ + ⟨div_nonneg hx hy, div_le_one_of_le₀ hxy hy⟩ theorem fract_mem (x : ℝ) : fract x ∈ I := ⟨fract_nonneg _, (fract_lt_one _).le⟩ diff --git a/Mathlib/Topology/UrysohnsBounded.lean b/Mathlib/Topology/UrysohnsBounded.lean index fa436cb53dfbd..16835df30f181 100644 --- a/Mathlib/Topology/UrysohnsBounded.lean +++ b/Mathlib/Topology/UrysohnsBounded.lean @@ -4,14 +4,14 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Yury Kudryashov -/ import Mathlib.Topology.UrysohnsLemma -import Mathlib.Topology.ContinuousFunction.Bounded +import Mathlib.Topology.ContinuousMap.Bounded /-! # Urysohn's lemma for bounded continuous functions In this file we reformulate Urysohn's lemma `exists_continuous_zero_one_of_isClosed` in terms of bounded continuous functions `X →ᵇ ℝ`. These lemmas live in a separate file because -`Topology.ContinuousFunction.Bounded` imports too many other files. +`Topology.ContinuousMap.Bounded` imports too many other files. ## Tags diff --git a/Mathlib/Topology/UrysohnsLemma.lean b/Mathlib/Topology/UrysohnsLemma.lean index 4c07760f23a50..705eb5ca08358 100644 --- a/Mathlib/Topology/UrysohnsLemma.lean +++ b/Mathlib/Topology/UrysohnsLemma.lean @@ -5,7 +5,7 @@ Authors: Yury Kudryashov -/ import Mathlib.Analysis.Normed.Affine.AddTorsor import Mathlib.LinearAlgebra.AffineSpace.Ordered -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic import Mathlib.Topology.GDelta import Mathlib.Analysis.NormedSpace.FunctionSeries import Mathlib.Analysis.SpecificLimits.Basic diff --git a/Mathlib/Util/AtomM.lean b/Mathlib/Util/AtomM.lean index 2c411702a829b..0b829028c0b11 100644 --- a/Mathlib/Util/AtomM.lean +++ b/Mathlib/Util/AtomM.lean @@ -22,7 +22,7 @@ namespace Mathlib.Tactic open Lean Meta /-- The context (read-only state) of the `AtomM` monad. -/ -structure AtomM.Context := +structure AtomM.Context where /-- The reducibility setting for definitional equality of atoms -/ red : TransparencyMode /-- A simplification to apply to atomic expressions when they are encountered, @@ -31,7 +31,7 @@ structure AtomM.Context := deriving Inhabited /-- The mutable state of the `AtomM` monad. -/ -structure AtomM.State := +structure AtomM.State where /-- The list of atoms-up-to-defeq encountered thus far, used for atom sorting. -/ atoms : Array Expr := #[] diff --git a/Mathlib/Util/CountHeartbeats.lean b/Mathlib/Util/CountHeartbeats.lean index 3b30d85e1aa29..bbc00430ba743 100644 --- a/Mathlib/Util/CountHeartbeats.lean +++ b/Mathlib/Util/CountHeartbeats.lean @@ -43,8 +43,8 @@ def runTacForHeartbeats (tac : TSyntax `Lean.Parser.Tactic.tacticSeq) (revert : Given a `List Nat`, return the minimum, maximum, and standard deviation. -/ def variation (counts : List Nat) : List Nat := - let min := counts.minimum?.getD 0 - let max := counts.maximum?.getD 0 + let min := counts.min?.getD 0 + let max := counts.max?.getD 0 let toFloat (n : Nat) := n.toUInt64.toFloat let toNat (f : Float) := f.toUInt64.toNat let counts' := counts.map toFloat diff --git a/Mathlib/Util/SleepHeartbeats.lean b/Mathlib/Util/SleepHeartbeats.lean index 7716e32f74a86..f6cb76c320e8d 100644 --- a/Mathlib/Util/SleepHeartbeats.lean +++ b/Mathlib/Util/SleepHeartbeats.lean @@ -34,7 +34,6 @@ elab "sleep_heartbeats " n:num : tactic => do option -/ | some m => sleepAtLeastHeartbeats (m * 1000) -set_option linter.unusedTactic false in example : 1 = 1 := by sleep_heartbeats 1000 rfl diff --git a/Mathlib/Util/Superscript.lean b/Mathlib/Util/Superscript.lean index a696144b7f9fe..85d3b2fecae7f 100644 --- a/Mathlib/Util/Superscript.lean +++ b/Mathlib/Util/Superscript.lean @@ -95,7 +95,8 @@ partial def satisfyTokensFn (p : Char → Bool) (errorMsg : String) (many := tru variable {α : Type u} [Inhabited α] (as : Array α) (leftOfPartition : α → Bool) in /-- Given a predicate `leftOfPartition` which is true for indexes `< i` and false for `≥ i`, returns `i`, by binary search. -/ -@[specialize] partial def partitionPoint (lo := 0) (hi := as.size) : Nat := +@[specialize] +def partitionPoint (lo := 0) (hi := as.size) : Nat := if lo < hi then let m := (lo + hi)/2 let a := as.get! m @@ -104,6 +105,7 @@ returns `i`, by binary search. -/ else partitionPoint lo m else lo + termination_by hi - lo /-- The core function for super/subscript parsing. It consists of three stages: diff --git a/README.md b/README.md index 53d266e917989..dfe49c658f2b5 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ For more pointers, see [Learning Lean](https://leanprover-community.github.io/le ## Documentation Besides the installation guides above and [Lean's general -documentation](https://leanprover.github.io/documentation/), the documentation +documentation](https://docs.lean-lang.org/lean4/doc/), the documentation of mathlib consists of: - [The mathlib4 docs](https://leanprover-community.github.io/mathlib4_docs/index.html): documentation [generated diff --git a/bors.toml b/bors.toml index 6f0bc95fdaa7a..a94f6e08beeac 100644 --- a/bors.toml +++ b/bors.toml @@ -1,7 +1,7 @@ status = ["Build", "Lint style"] use_squash_merge = true timeout_sec = 28800 -block_labels = ["not-ready-to-merge", "WIP", "blocked-by-other-PR", "merge-conflict", "awaiting-CI"] +block_labels = ["WIP", "blocked-by-other-PR", "merge-conflict", "awaiting-CI"] delete_merged_branches = true update_base_for_deletes = true cut_body_after = "---" diff --git a/docs/overview.yaml b/docs/overview.yaml index be28612dbf810..d020bc5328e44 100644 --- a/docs/overview.yaml +++ b/docs/overview.yaml @@ -209,7 +209,7 @@ Topology: cluster point: 'ClusterPt' Hausdorff space: 'T2Space' sequential space: 'SequentialSpace' - extension by continuity: 'DenseInducing.extend' + extension by continuity: 'IsDenseInducing.extend' compactness in terms of filters: 'IsCompact' compactness in terms of open covers (Borel-Lebesgue): 'isCompact_iff_finite_subcover' connectedness: 'ConnectedSpace' @@ -352,7 +352,7 @@ Analysis: Liouville theorem: 'Differentiable.apply_eq_apply_of_bounded' maximum modulus principle: 'Complex.eventually_eq_of_isLocalMax_norm' principle of isolated zeros: 'AnalyticAt.eventually_eq_zero_or_eventually_ne_zero' - principle of analytic continuation: 'AnalyticOn.eqOn_of_preconnected_of_frequently_eq' + principle of analytic continuation: 'AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq' analyticity of holomorphic functions: 'DifferentiableOn.analyticAt' Schwarz lemma: 'Complex.abs_le_abs_of_mapsTo_ball_self' removable singularity: 'Complex.differentiableOn_update_limUnder_insert_of_isLittleO' diff --git a/docs/references.bib b/docs/references.bib index 71178e6a2c7f3..67919e2ced15f 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -1396,6 +1396,18 @@ @Book{ friedmanscarr2005 zbl = {1080.46001} } +@Book{ fritsch-piccinini1990, + place = {Cambridge}, + series = {Cambridge Studies in Advanced Mathematics}, + title = {Cellular Structures in Topology}, + publisher = {Cambridge University Press}, + author = {Fritsch, Rudolf and Piccinini, Renzo}, + year = {1990}, + collection = {Cambridge Studies in Advanced Mathematics}, + url = {https://doi.org/10.1017/CBO9780511983948}, + doi = {10.1017/CBO9780511983948} +} + @Book{ fuchs1963, author = {Fuchs, L.}, title = {Partially ordered algebraic systems}, @@ -2076,6 +2088,14 @@ @Article{ Joyce1982 publisher = {Elsevier {BV}} } +@Book{ juskevic2022, + author = {Ju{\v{s}}kevi{\v{c}}, Adolf P and Winter, Eduard}, + title = {Leonhard Euler und Christian Goldbach: Briefwechsel + 1729--1764}, + year = {2022}, + publisher = {Walter de Gruyter GmbH \& Co KG} +} + @Article{ KahnMaltsiniotis2008, author = {Kahn, Bruno and Maltsiniotis, Georges}, title = {Structures de d\'{e}rivabilit\'{e}}, @@ -2827,6 +2847,17 @@ @Misc{ ponton2020chebyshev primaryclass = {math.NT} } +@Article{ Prielipp1970, + author = {Robert W. Prielipp}, + title = {PERFECT NUMBERS, ABUNDANT NUMBERS, AND DEFICIENT NUMBERS}, + journal = {The Mathematics Teacher}, + volume = {63}, + year = {1970}, + pages = {692--696}, + issn = {00255769}, + url = {http://www.jstor.org/stable/27958492} +} + @InCollection{ ribenboim1971, author = {Ribenboim, Paulo}, title = {\'{E}pimorphismes de modules qui sont n\'{e}cessairement diff --git a/docs/undergrad.yaml b/docs/undergrad.yaml index 21619980559e5..4a3b5c75b8fd9 100644 --- a/docs/undergrad.yaml +++ b/docs/undergrad.yaml @@ -356,7 +356,9 @@ Single Variable Real Analysis: Weierstrass trigonometric approximation theorem: 'span_fourier_closure_eq_top' Convexity: convex functions of a real variable: 'ConvexOn' - continuity and differentiability of convex functions: 'https://en.wikipedia.org/wiki/Convex_function#Functions_of_one_variable' + continuity and differentiability of convex functions: + continuity: 'ConvexOn.continuousOn' + differentiability: 'https://en.wikipedia.org/wiki/Convex_function#Functions_of_one_variable' characterizations of convexity: 'convexOn_of_deriv2_nonneg' convexity inequalities: 'analysis/mean_inequalities.html' @@ -387,7 +389,7 @@ Single Variable Complex Analysis: Cauchy formulas: 'Complex.two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable' analyticity of a holomorphic function: 'DifferentiableOn.analyticAt' principle of isolated zeros: 'AnalyticAt.eventually_eq_zero_or_eventually_ne_zero' - principle of analytic continuation: 'AnalyticOn.eqOn_of_preconnected_of_frequently_eq' + principle of analytic continuation: 'AnalyticOnNhd.eqOn_of_preconnected_of_frequently_eq' maximum principle: 'Complex.eventually_eq_of_isLocalMax_norm' isolated singularities: '' Laurent series: '' diff --git a/lake-manifest.json b/lake-manifest.json index db5f8604eab98..4a49ec817f12a 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -5,7 +5,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "35d1cd731ad832c9f1d860c4d8ec1c7c3ab96823", + "rev": "daf1ed91789811cf6bbb7bf2f4dad6b3bad8fbf4", "name": "batteries", "manifestFile": "lake-manifest.json", "inputRev": "main", @@ -15,7 +15,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "2c8ae451ce9ffc83554322b14437159c1a9703f9", + "rev": "2b2f6d7fbe9d917fc010e9054c1ce11774c9088b", "name": "Qq", "manifestFile": "lake-manifest.json", "inputRev": "master", @@ -25,7 +25,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "a895713f7701e295a015b1087f3113fd3d615272", + "rev": "b20a88676fd00affb90cbc9f1ff004ae588103b3", "name": "aesop", "manifestFile": "lake-manifest.json", "inputRev": "master", @@ -44,7 +44,7 @@ {"url": "https://github.com/leanprover/lean4-cli", "type": "git", "subDir": null, - "scope": "", + "scope": "leanprover", "rev": "2cf1030dc2ae6b3632c84a09350b675ef3e347d0", "name": "Cli", "manifestFile": "lake-manifest.json", @@ -55,7 +55,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "fb7841a6f4fb389ec0e47dd4677844d49906af3c", + "rev": "7376ac07aa2b0492372c056b7a2c3163b3026d1e", "name": "importGraph", "manifestFile": "lake-manifest.json", "inputRev": "main", @@ -65,7 +65,7 @@ "type": "git", "subDir": null, "scope": "leanprover-community", - "rev": "2ba60fa2c384a94735454db11a2d523612eaabff", + "rev": "4b61d4abc1659f15ffda5ec24fdebc229d51d066", "name": "LeanSearchClient", "manifestFile": "lake-manifest.json", "inputRev": "main", diff --git a/lakefile.lean b/lakefile.lean index 086cd93292deb..212047a97ac35 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -25,6 +25,7 @@ require "leanprover-community" / "LeanSearchClient" @ git "main" (as well as `Archive`, `Counterexamples` and `test`). -/ abbrev mathlibOnlyLinters : Array LeanOption := #[ + ⟨`linter.docPrime, true⟩, ⟨`linter.hashCommand, true⟩, ⟨`linter.oldObtain, true,⟩, ⟨`linter.refine, true⟩, @@ -34,7 +35,8 @@ abbrev mathlibOnlyLinters : Array LeanOption := #[ ⟨`linter.style.longLine, true⟩, ⟨`linter.style.longFile, .ofNat 1500⟩, ⟨`linter.style.missingEnd, true⟩, - ⟨`linter.style.setOption, true⟩ + ⟨`linter.style.setOption, true⟩, + ⟨`aesop.warn.applyIff, false⟩ -- This became a problem after https://github.com/leanprover-community/aesop/commit/29cf094e84ae9852f0011b47b6ddc684ffe4be5f ] /-- These options are passed as `leanOptions` to building mathlib, as well as the @@ -83,6 +85,16 @@ lean_lib docs where ## Executables provided by Mathlib -/ +/-- +`lake exe autolabel 150100` adds a topic label to PR `150100` if there is a unique choice. +This requires GitHub CLI `gh` to be installed! + +Calling `lake exe autolabel` without a PR number will print the result without applying +any labels online. +-/ +lean_exe autolabel where + srcDir := "scripts" + /-- `lake exe cache get` retrieves precompiled `.olean` files from a central server. -/ lean_exe cache where root := `Cache.Main diff --git a/lean-toolchain b/lean-toolchain index 98556ba065e2a..eff86fd63de9e 100644 --- a/lean-toolchain +++ b/lean-toolchain @@ -1 +1 @@ -leanprover/lean4:v4.12.0-rc1 +leanprover/lean4:v4.13.0-rc3 diff --git a/scripts/autolabel.lean b/scripts/autolabel.lean new file mode 100644 index 0000000000000..76e42ae90b1fc --- /dev/null +++ b/scripts/autolabel.lean @@ -0,0 +1,310 @@ +/- +Copyright (c) 2024 Damiano Testa. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Jon Eugster, Damiano Testa +-/ +import Lean.Elab.Command + +/-! +# Automatic labelling of PRs + +This file contains the script to automatically assign a GitHub label to a PR. + +## Label definition + +The mapping from GitHub labels to Mathlib folders is done in this file and +needs to be updated here if necessary: + +* `AutoLabel.mathlibLabels` contains an assignment of GitHub labels to folders inside + the mathlib repository. If no folder is specified, a label like `t-set-theory` will be + interpreted as matching the folder `"Mathlib" / "SetTheory"`. +* `AutoLabel.mathlibUnlabelled` contains subfolders of `Mathlib/` which are deliberately + left without topic label. + +## lake exe autolabel + +`lake exe autolabel` uses `git diff --name-only origin/master...HEAD` to determine which +files have been modified and then finds all labels which should be added based on these changes. +These are printed for testing purposes. + +`lake exe autolabel [NUMBER]` will further try to add the applicable labels +to the PR specified. This requires the **GitHub CLI** `gh` to be installed! +Example: `lake exe autolabel 10402` for PR #10402. + +For the time being, the script only adds a label if it finds a **single unique label** +which would apply. If multiple labels are found, nothing happens. + +## Workflow + +There is a mathlib workflow `.github/workflows/add_label_from_diff.yaml` which executes +this script automatically. + +Currently it is set to run only one time when a PR is created. + +## Tests + +Additionally, the script does a few consistency checks: + +- it ensures all paths in specified in `AutoLabel.mathlibLabels` exist +- It makes sure all subfolders of `Mathlib/` belong to at least one label. + There is `AutoLabel.mathlibUnlabelled` to add exceptions for this test. + +-/ + +open Lean System + +namespace AutoLabel + +/-- +A `Label` consists of the +* The `label` field is the actual GitHub label name. +* The `dirs` field is the array of all "root paths" such that a modification in a file contained + in one of these paths should be labelled with `label`. +* The `exclusions` field is the array of all "root paths" that are excluded, among the + ones that start with the ones in `dirs`. + Any modifications to a file in an excluded path is ignored for the purposes of labelling. +-/ +structure Label where + /-- The label name as it appears on GitHub -/ + label : String + /-- Array of paths which fall under this label. e.g. `"Mathlib" / "Algebra"`. + + For a label of the form `t-set-theory` this defaults to `#["Mathlib" / "SetTheory"]`. -/ + dirs : Array FilePath := if label.startsWith "t-" then + #["Mathlib" / ("".intercalate (label.splitOn "-" |>.drop 1 |>.map .capitalize))] + else #[] + /-- Array of paths which should be excluded. + Any modifications to a file in an excluded path are ignored for the purposes of labelling. -/ + exclusions : Array FilePath := #[] + deriving BEq, Hashable + +/-- +Mathlib labels and their corresponding folders. Add new labels and folders here! +-/ +def mathlibLabels : Array Label := #[ + { label := "t-algebra", + dirs := #[ + "Mathlib" / "Algebra", + "Mathlib" / "FieldTheory", + "Mathlib" / "RingTheory", + "Mathlib" / "GroupTheory", + "Mathlib" / "RepresentationTheory", + "Mathlib" / "LinearAlgebra"] }, + { label := "t-algebraic-geometry", + dirs := #[ + "Mathlib" / "AlgebraicGeometry", + "Mathlib" / "Geometry" / "RingedSpace"] }, + { label := "t-analysis" }, + { label := "t-category-theory" }, + { label := "t-combinatorics" }, + { label := "t-computability" }, + { label := "t-condensed" }, + { label := "t-data" }, + { label := "t-differential-geometry", + dirs := #["Mathlib" / "Geometry" / "Manifold"] }, + { label := "t-dynamics" }, + { label := "t-euclidean-geometry", + dirs := #["Mathlib" / "Geometry" / "Euclidean"] }, + { label := "t-linter", + dirs := #["Mathlib" / "Tactic" / "Linter"] }, + { label := "t-logic", + dirs := #[ + "Mathlib" / "Logic", + "Mathlib" / "ModelTheory"] }, + { label := "t-measure-probability", + dirs := #[ + "Mathlib" / "MeasureTheory", + "Mathlib" / "Probability", + "Mathlib" / "InformationTheory"] }, + { label := "t-meta", + dirs := #[ + "Mathlib" / "Control", + "Mathlib" / "Lean", + "Mathlib" / "Mathport", + "Mathlib" / "Tactic", + "Mathlib" / "Util"], + exclusions := #["Mathlib" / "Tactic" / "Linter"] }, + { label := "t-number-theory" }, + { label := "t-order" }, + { label := "t-set-theory" }, + { label := "t-topology", + dirs := #[ + "Mathlib" / "Topology", + "Mathlib" / "AlgebraicTopology"] }, + { label := "CI", + dirs := #[".github"] }, + { label := "IMO", + dirs := #["Archive" / "Imo"] } ] + +/-- Exceptions inside `Mathlib/` which are not covered by any label. -/ +def mathlibUnlabelled : Array FilePath := #[ + "Mathlib" / "Deprecated", + "Mathlib" / "Init", + "Mathlib" / "Testing", + "Mathlib" / "Std" ] + +/-- Checks if the folder `path` lies inside the folder `dir`. -/ +def _root_.System.FilePath.isPrefixOf (dir path : FilePath) : Bool := + -- use `dir / ""` to prevent partial matching of folder names + (dir / "").normalize.toString.isPrefixOf (path / "").normalize.toString + +/-- +Return all names of labels in `mathlibLabels` which match +at least one of the `files`. + +* `files`: array of relative paths starting from the mathlib root directory. +-/ +def getMatchingLabels (files : Array FilePath) : Array String := + let applicable := mathlibLabels.filter fun label ↦ + -- first exclude all files the label excludes, + -- then see if any file remains included by the label + let notExcludedFiles := files.filter fun file ↦ + label.exclusions.all (!·.isPrefixOf file) + label.dirs.any (fun dir ↦ notExcludedFiles.any (dir.isPrefixOf ·)) + -- return sorted list of label names + applicable.map (·.label) |>.qsort (· < ·) + +/-! +Testing the functionality of the declarations defined in this script +-/ +section Tests + +-- Test `FilePath.isPrefixOf` +#guard ("Mathlib" / "Algebra" : FilePath).isPrefixOf ("Mathlib" / "Algebra" / "Basic.lean") + +-- Test `FilePath.isPrefixOf` does not trigger on partial prefixes +#guard ! ("Mathlib" / "Algebra" : FilePath).isPrefixOf ("Mathlib" / "AlgebraicGeometry") + +#guard getMatchingLabels #[] == #[] +-- Test default value for `label.dirs` works +#guard getMatchingLabels #["Mathlib" / "SetTheory" / "ZFC"] == #["t-set-theory"] +-- Test exclusion +#guard getMatchingLabels #["Mathlib" / "Tactic"/ "Abel.lean"] == #["t-meta"] +#guard getMatchingLabels #["Mathlib" / "Tactic"/ "Linter" / "Lint.lean"] == #["t-linter"] +#guard getMatchingLabels #[ + "Mathlib" / "Tactic"/ "Linter" / "Lint.lean", + "Mathlib" / "Tactic" / "Abel.lean" ] == #["t-linter", "t-meta"] + +/-- Testing function to ensure the labels defined in `mathlibLabels` cover all +subfolders of `Mathlib/`. -/ +partial def findUncoveredPaths (path : FilePath) (exceptions : Array FilePath := #[]) : + IO <| Array FilePath := do + let mut notMatched : Array FilePath := #[] + -- all directories inside `path` + let subDirs ← (← path.readDir).map (·.path) |>.filterM (do FilePath.isDir ·) + for dir in subDirs do + -- if the sub directory is not matched by a label, + -- we go recursively into it + if (getMatchingLabels #[dir]).size == 0 then + notMatched := notMatched ++ (← findUncoveredPaths dir exceptions) + -- a directory should be flagged if none of its sub-directories is matched by a label + -- note: we assume here the base directory, i.e. "Mathlib" is never matched by a label, + -- therefore we skip this test. + if notMatched.size == subDirs.size then + if exceptions.contains path then + return #[] + else + return #[path] + else + return notMatched + +end Tests + +/-- +Create a message which GitHub CI parses as annotation and displays at the specified file. + +Note: `file` is duplicated below so that it is also visible in the plain text output. + +* `type`: "error" or "warning" +* `file`: file where the annotation should be displayed +* `title`: title of the annotation +* `message`: annotation message +-/ +def githubAnnotation (type file title message : String) : String := + s!"::{type} file={file},title={title}::{file}: {message}" + +end AutoLabel + +open IO AutoLabel in + +/-- `args` is expected to have length 0 or 1, where the first argument is the PR number. + +If a PR number is provided, the script requires GitHub CLI `gh` to be installed in order +to add the label to the PR. + +## Exit codes: + +- `0`: success +- `1`: invalid arguments provided +- `2`: invalid labels defined +- `3`: ~labels do not cover all of `Mathlib/`~ (unused; only emitting warning) +-/ +unsafe def main (args : List String): IO UInt32 := do + if args.length > 1 then + println s!"::error:: autolabel: invalid number of arguments ({args.length}), \ + expected at most 1. Please run without arguments or provide the target PR's \ + number as a single argument!" + return 1 + let prNumber? := args[0]? + + -- test: validate that all paths in `mathlibLabels` actually exist + let mut valid := true + for label in mathlibLabels do + for dir in label.dirs do + unless ← FilePath.pathExists dir do + -- print github annotation error + println <| AutoLabel.githubAnnotation "error" "scripts/autolabel.lean" + s!"Misformatted `{ ``AutoLabel.mathlibLabels }`" + s!"directory '{dir}' does not exist but is included by label '{label.label}'. \ + Please update `{ ``AutoLabel.mathlibLabels }`!" + valid := false + for dir in label.exclusions do + unless ← FilePath.pathExists dir do + -- print github annotation error + println <| AutoLabel.githubAnnotation "error" "scripts/autolabel.lean" + s!"Misformatted `{ ``AutoLabel.mathlibLabels }`" + s!"directory '{dir}' does not exist but is excluded by label '{label.label}'. \ + Please update `{ ``AutoLabel.mathlibLabels }`!" + valid := false + unless valid do + return 2 + + -- test: validate that the labels cover all of the `Mathlib/` folder + let notMatchedPaths ← findUncoveredPaths "Mathlib" (exceptions := mathlibUnlabelled) + if notMatchedPaths.size > 0 then + -- print github annotation warning + -- note: only emitting a warning because the workflow is only triggered on the first commit + -- of a PR and could therefore lead to unexpected behaviour if a folder was created later. + println <| AutoLabel.githubAnnotation "warning" "scripts/autolabel.lean" + s!"Incomplete `{ ``AutoLabel.mathlibLabels }`" + s!"the following paths inside `Mathlib/` are not covered \ + by any label: {notMatchedPaths} Please modify `AutoLabel.mathlibLabels` accordingly!" + -- return 3 + + -- get the modified files + let gitDiff ← IO.Process.run { + cmd := "git", + args := #["diff", "--name-only", "origin/master...HEAD"] } + let modifiedFiles : Array FilePath := (gitDiff.splitOn "\n").toArray.map (⟨·⟩) + + -- find labels covering the modified files + let labels := getMatchingLabels modifiedFiles + + println s!"::notice::Applicable labels: {labels}" + + match labels with + | #[] => + println s!"::warning::no label to add" + | #[label] => + match prNumber? with + | some n => + let _ ← IO.Process.run { + cmd := "gh", + args := #["pr", "edit", n, "--add-label", label] } + println s!"::notice::added label: {label}" + | none => + println s!"::warning::no PR-number provided, not adding labels. \ + (call `lake exe autolabel 150602` to add the labels to PR `150602`)" + | _ => + println s!"::notice::not adding multiple labels: {labels}" + return 0 diff --git a/scripts/bench/temci-config.run.yml b/scripts/bench/temci-config.run.yml index dd8af5f9c062a..9fdeceaa83cda 100644 --- a/scripts/bench/temci-config.run.yml +++ b/scripts/bench/temci-config.run.yml @@ -6,7 +6,8 @@ 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' + # use build cache for proofwidgets, but not for anything else + bash -c 'set -eo pipefail; lake clean 1>&2 && LEAN_PATH=$(lean --print-libdir) lake build proofwidgets 1>&2 && rm .lake/packages/batteries/.lake/build/bin/runLinter 1>&2 && lake build --no-cache -v --lean ./scripts/bench/fake-root/bin/lean | ./scripts/bench/accumulate_profile.py | grep -v took' parse_output: true runs: 1 - attributes: diff --git a/scripts/create-adaptation-pr.sh b/scripts/create-adaptation-pr.sh index 2e7d69f7916d8..c64a006cbf1a3 100755 --- a/scripts/create-adaptation-pr.sh +++ b/scripts/create-adaptation-pr.sh @@ -21,9 +21,10 @@ AUTO="no" usage() { echo "Usage: $0 " echo " or" - echo " $0 --bumpversion= --nightlydate= [--auto=]" + echo " $0 --bumpversion= --nightlydate= --nightlysha= [--auto=]" echo "BUMPVERSION: The upcoming release that we are targeting, e.g., 'v4.10.0'" echo "NIGHTLYDATE: The date of the nightly toolchain currently used on 'nightly-testing'" + echo "NIGHTLYSHA: The SHA of the nightly toolchain that we want to adapt to" echo "AUTO: Optional flag to specify automatic mode, default is 'no'" exit 1 } @@ -43,6 +44,10 @@ elif [ $# -ge 2 ]; then NIGHTLYDATE="${arg#*=}" shift ;; + --nightlysha=*) + NIGHTLYSHA="${arg#*=}" + shift + ;; --auto=*) AUTO="${arg#*=}" shift @@ -148,15 +153,14 @@ echo echo "### [auto] create a new branch 'bump/nightly-$NIGHTLYDATE' and merge the latest changes from 'origin/nightly-testing'" git checkout -b "bump/nightly-$NIGHTLYDATE" -git merge origin/nightly-testing || true # ignore error if there are conflicts +git merge $NIGHTLYSHA || true # ignore error if there are conflicts # Check if there are merge conflicts if git diff --name-only --diff-filter=U | grep -q .; then echo echo "### [auto] Conflict resolution" - echo "### Automatically choosing 'lean-toolchain' and 'lake-manifest.json' from the newer branch" - echo "### In this case, the newer branch is 'origin/nightly-testing'" - git checkout origin/nightly-testing -- lean-toolchain lake-manifest.json + echo "### Automatically choosing 'lean-toolchain' and 'lake-manifest.json' from 'nightly-testing'" + git checkout $NIGHTLYSHA -- lean-toolchain lake-manifest.json git add lean-toolchain lake-manifest.json fi @@ -172,6 +176,8 @@ if git diff --name-only --diff-filter=U | grep -q .; then echo echo "### [user] Conflict resolution" echo "We are merging the latest changes from 'origin/nightly-testing' into 'bump/nightly-$NIGHTLYDATE'" + echo "Specifically, we are merging the following version of 'origin/nightly-testing':" + echo "$NIGHTLYSHA" echo "There seem to be conflicts: please resolve them" echo "" echo " 1) Open `pwd` in a new terminal and run 'git status'" @@ -286,7 +292,7 @@ if git diff --name-only --diff-filter=U | grep -q . || ! git diff-index --quiet if [ "$AUTO" = "yes" ]; then echo "Auto mode enabled. Bailing out due to unresolved conflicts or uncommitted changes." echo "PR has been created, and message posted to Zulip." - echo "Error occured while merging the new branch into 'nightly-testing'." + echo "Error occurred while merging the new branch into 'nightly-testing'." exit 2 fi fi diff --git a/scripts/import-graph-report.py b/scripts/import-graph-report.py index cf072b916c5e8..86775bf4c2fc1 100755 --- a/scripts/import-graph-report.py +++ b/scripts/import-graph-report.py @@ -10,6 +10,8 @@ import json import sys +high_import_threshold = 2 + def compare_counts(base_file, head_file, changed_files_txt): # Load the counts with open(head_file, 'r') as f: @@ -29,6 +31,7 @@ def compare_counts(base_file, head_file, changed_files_txt): # Compare the counts changes = [] + high_pct = [] for file in changed_files: base_count = base_counts.get(file, 0) head_count = head_counts.get(file, 0) @@ -36,6 +39,8 @@ def compare_counts(base_file, head_file, changed_files_txt): continue diff = head_count - base_count percent = (diff / base_count) * 100 + if high_import_threshold < percent: + high_pct.append(f'| +{percent:.2f}% | `{file}` |') if diff < 0: # Dependencies went down changes.append((file, base_count, head_count, diff, percent)) elif diff > new_files: # Dependencies went up by more than the number of new files @@ -59,11 +64,19 @@ def compare_counts(base_file, head_file, changed_files_txt): message += '\n'.join(messages) else: message += 'No significant changes to the import graph' - return message + + high_pct_report = '' + if high_pct: + high_pct_report += f'Import changes exceeding {high_import_threshold}%\n\n' + high_pct_report += '| % | File |\n' + high_pct_report += '| - | - |\n' + high_pct_report += '\n'.join(high_pct) + return (message, high_pct_report) if __name__ == '__main__': base_file = sys.argv[1] head_file = sys.argv[2] changed_files_txt = sys.argv[3] - message = compare_counts(base_file, head_file, changed_files_txt) + (message, high_pct) = compare_counts(base_file, head_file, changed_files_txt) print(message) + print(high_pct) diff --git a/scripts/init_creation.sh b/scripts/init_creation.sh index 5fc09772f9670..7abca30241c43 100644 --- a/scripts/init_creation.sh +++ b/scripts/init_creation.sh @@ -2,8 +2,8 @@ : <<'BASH_MODULE_DOC' -These are the commands to generate a "root" `Mathlib/Init.lean` file, imported by all the -`Mathlib` files that do not import any `Mathlib` file. +These are the commands to add an import of `Mathlib/Init.lean` to all `Mathlib` files +that do not import any `Mathlib` file. BASH_MODULE_DOC @@ -35,11 +35,3 @@ printf 'Adding `import Mathlib.Init` to all file that import no Mathlib file.\n' # The `sed` command appends the line `import Mathlib.Init` after the first # `-/[linebreaks]*` of each file printed by `mathlibNonImportingFiles`. sed -i -z 's=-/\n*=&import Mathlib.Init\n=' $(mathlibNonImportingFiles) - -printf 'Creating `Mathlib/Init.lean`.\n' - -# Creates the `Mathlib/Init.lean` files. -echo '-- This is the root file in Mathlib: it is imported by virtually *all* Mathlib files' > Mathlib/Init.lean - -printf $'Don\'t forget to add `Mathlib.Init` to the `ignoreImport` field of `scripts/noshake.json` -This ensures that `import Mathlib.Init` does not trigger a `shake` exception.\n' diff --git a/scripts/lean-pr-testing-comments.sh b/scripts/lean-pr-testing-comments.sh index 189a6ea6ac536..ba5c9586b2e05 100755 --- a/scripts/lean-pr-testing-comments.sh +++ b/scripts/lean-pr-testing-comments.sh @@ -1,8 +1,13 @@ -## Create comments and labels on a Lean 4 PR after CI has finished on a `lean-pr-testing-NNNN` branch. +## Create comments and labels on a Lean 4 or Batteries PR after CI has finished on a `*-pr-testing-NNNN` branch. ## ## See https://leanprover-community.github.io/contribute/tags_and_branches.html set -e +# Ensure first argument is either 'lean' or 'batteries'. +if [ -z "$1" ]; then + echo "The first argument must be either 'lean' or 'batteries'" + exit 1 +fi # TODO: The whole script ought to be rewritten in javascript, to avoid having to use curl for API calls. # @@ -19,14 +24,29 @@ set -e # LINT_OUTCOME: ${{ steps.lint.outcome }} # TEST_OUTCOME: ${{ steps.test.outcome }} +# Adjust the branch pattern and URLs based on the repository. +if [ "$1" == "lean" ]; then + branch_prefix="lean-pr-testing" + repo_url="https://api.github.com/repos/leanprover/lean4" + base_branch="nightly-testing" # This really should be the relevant `nightly-testing-YYYY-MM-DD` tag. +elif [ "$1" == "batteries" ]; then + branch_prefix="batteries-pr-testing" + repo_url="https://api.github.com/repos/leanprover-community/batteries" + base_branch="master" +else + echo "Unknown repository: $1. Must be either 'lean' or 'batteries'." + exit 1 +fi + # Extract branch name and check if it matches the pattern. branch_name=$(echo "$GITHUB_CONTEXT" | jq -r .ref | cut -d'/' -f3) -if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then +if [[ "$branch_name" =~ ^$branch_prefix-([0-9]+)$ ]]; then pr_number="${BASH_REMATCH[1]}" current_time=$(date "+%Y-%m-%d %H:%M:%S") - echo "This is a 'lean-pr-testing-$pr_number' branch, so we need to adjust labels and write a comment." + echo "This is a '$branch_prefix-$pr_number' branch, so we need to adjust labels and write a comment." + # Perform actions based on outcomes (same logic as before) if [ "$TEST_OUTCOME" == "success" ]; then echo "Removing label awaiting-mathlib" curl -L -s \ @@ -34,21 +54,21 @@ if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then -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/awaiting-mathlib + $repo_url/issues/$pr_number/labels/awaiting-mathlib echo "Removing label breaks-mathlib" curl -L -s \ -X DELETE \ -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/breaks-mathlib + $repo_url/issues/$pr_number/labels/breaks-mathlib echo "Adding label builds-mathlib" 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 \ + $repo_url/issues/$pr_number/labels \ -d '{"labels":["builds-mathlib"]}' elif [ "$LINT_OUTCOME" == "failure" ] || [ "$TEST_OUTCOME" == "failure" ] || [ "$COUNTEREXAMPLES_OUTCOME" == "failure" ] || [ "$ARCHIVE_OUTCOME" == "failure" ] || [ "$NOISY_OUTCOME" == "failure" ] || [ "$BUILD_OUTCOME" == "failure" ]; then echo "Removing label builds-mathlib" @@ -57,32 +77,32 @@ if [[ "$branch_name" =~ ^lean-pr-testing-([0-9]+)$ ]]; then -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/builds-mathlib + $repo_url/issues/$pr_number/labels/builds-mathlib echo "Adding label breaks-mathlib" 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 \ + $repo_url/issues/$pr_number/labels \ -d '{"labels":["breaks-mathlib"]}' 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 'first(.[] | select(.body | test("^- . Mathlib") or startswith("Mathlib CI status")) | select(.user.login == "leanprover-community-mathlib4-bot"))') + "$repo_url/issues/$pr_number/comments" \ + | jq 'first(.[] | select(.body | test("^- . Mathlib") or startswith("Mathlib CI status")) | select(.user.login == "leanprover-community-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)" + branch="[$branch_prefix-$pr_number](https://github.com/leanprover-community/mathlib4/compare/$base_branch...$branch_prefix-$pr_number)" # Depending on the success/failure, set the appropriate message if [ "$LINT_OUTCOME" == "cancelled" ] || [ "$TEST_OUTCOME" == "cancelled" ] || [ "$COUNTEREXAMPLES_OUTCOME" == "cancelled" ] || [ "$ARCHIVE_OUTCOME" == "cancelled" ] || [ "$NOISY_OUTCOME" == "cancelled" ] || [ "$BUILD_OUTCOME" == "cancelled" ]; then message="- 🟡 Mathlib branch $branch build against this PR was cancelled. ($current_time) [View Log]($WORKFLOW_URL)" elif [ "$TEST_OUTCOME" == "success" ]; then message="- ✅ Mathlib branch $branch has successfully built against this PR. ($current_time) [View Log]($WORKFLOW_URL)" - elif [ "$BUILD_OUTCOME" == "failure" ] ; then + elif [ "$BUILD_OUTCOME" == "failure" ]; then message="- 💥 Mathlib branch $branch build failed against this PR. ($current_time) [View Log]($WORKFLOW_URL)" elif [ "$LINT_OUTCOME" == "failure" ]; then message="- ❌ Mathlib branch $branch built against this PR, but linting failed. ($current_time) [View Log]($WORKFLOW_URL)" @@ -103,23 +123,22 @@ 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" + echo "Posting as new comment at $repo_url/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 intro "$intro" --arg val "$message" '{"body": ($intro + "\n" + $val)}')" \ - "https://api.github.com/repos/leanprover/lean4/issues/$pr_number/comments" + "$repo_url/issues/$pr_number/comments" else # Append new result to the existing comment - echo "Appending to existing comment at leanprover/lean4/issues/$pr_number/comments" + echo "Appending to existing comment at $repo_url/issues/$pr_number/comments" curl -L -s \ -X PATCH \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ -d "$(jq --null-input --arg existing "$existing_comment_body" --arg message "$message" '{"body":($existing + "\n" + $message)}')" \ - "https://api.github.com/repos/leanprover/lean4/issues/comments/$existing_comment_id" + "$repo_url/issues/comments/$existing_comment_id" fi fi diff --git a/scripts/no_lints_prime_decls.txt b/scripts/no_lints_prime_decls.txt new file mode 100644 index 0000000000000..b2fa718c5be98 --- /dev/null +++ b/scripts/no_lints_prime_decls.txt @@ -0,0 +1,4879 @@ +AbelRuffini.not_solvable_by_rad' +abs_add' +abs_le_of_sq_le_sq' +abs_lt_of_sq_lt_sq' +abs_norm' +abs_norm_sub_norm_le' +Absorbent.zero_mem' +ack_strict_mono_left' +Action.inhabited' +Action.tensorUnit_ρ' +Action.tensor_ρ' +AddAction.orbitZMultiplesEquiv_symm_apply' +AddChar.div_apply' +AddChar.inv_apply' +AddChar.neg_apply' +AddChar.sub_apply' +AddChar.zmodChar_apply' +AddCircle.addOrderOf_div_of_gcd_eq_one' +AddCircle.continuous_mk' +AddCircle.measurable_mk' +AddCircle.norm_eq' +AddCommGroup.intCast_modEq_intCast' +AddCommGroup.ModEq.add_left_cancel' +AddCommGroup.ModEq.add_right_cancel' +AddCommGroup.modEq_sub_iff_add_modEq' +AddCommGroup.ModEq.sub_left_cancel' +AddCommGroup.ModEq.sub_right_cancel' +AddCommGroup.sub_modEq_iff_modEq_add' +AddConstMapClass.map_add_int' +AddConstMapClass.map_add_nat' +AddConstMapClass.map_add_ofNat' +AddConstMapClass.map_int_add' +AddConstMapClass.map_nat' +AddConstMapClass.map_nat_add' +AddConstMapClass.map_ofNat' +AddConstMapClass.map_ofNat_add' +AddConstMapClass.map_sub_int' +AddConstMapClass.map_sub_nat' +AddConstMapClass.map_sub_ofNat' +add_div' +AddGroup.int_smulCommClass' +Additive.isometricVAdd' +Additive.isometricVAdd'' +add_le_mul' +AddMonoidAlgebra.lift_apply' +AddMonoidAlgebra.lift_of' +AddMonoidAlgebra.lift_unique' +AddMonoidAlgebra.mem_grade_iff' +AddMonoidHom.coe_smul' +AddMonoidHom.coe_toMultiplicative' +AddMonoidHom.coe_toMultiplicative'' +AddMonoid.nat_smulCommClass' +add_sq' +AddSubgroup.torsionBy.mod_self_nsmul' +AddValuation.map_add' +AddValuation.map_lt_sum' +ADEInequality.admissible_A' +ADEInequality.admissible_D' +ADEInequality.admissible_of_one_lt_sumInv_aux' +AdjoinRoot.algebraMap_eq' +AdjoinRoot.coe_injective' +AdjoinRoot.isIntegral_root' +AdjoinRoot.Minpoly.toAdjoin_apply' +AEMeasurable.comp_aemeasurable' +aemeasurable_const' +AEMeasurable.const_smul' +AEMeasurable.div' +aemeasurable_id' +aemeasurable_id'' +AEMeasurable.inf' +AEMeasurable.mono' +AEMeasurable.mul' +aemeasurable_of_tendsto_metrizable_ae' +AEMeasurable.sup' +AffineEquiv.coe_mk' +AffineEquiv.linear_mk' +AffineIsometryEquiv.coe_mk' +AffineIsometryEquiv.coe_vaddConst' +AffineIsometryEquiv.dist_pointReflection_self' +AffineIsometryEquiv.linearIsometryEquiv_mk' +AffineMap.coe_mk' +AffineMap.lineMap_apply_module' +AffineMap.lineMap_apply_ring' +AffineSubspace.mem_perpBisector_iff_dist_eq' +AkraBazziRecurrence.asympBound_def' +AkraBazziRecurrence.dist_r_b' +Algebra.adjoin_induction'' +Algebra.algebraMap_eq_smul_one' +Algebra.fg_trans' +Algebra.FormallyUnramified.ext' +Algebra.FormallyUnramified.lift_unique' +Algebra.Generators.Cotangent.module' +Algebra.Generators.Cotangent.val_smul' +Algebra.Generators.Cotangent.val_smul'' +Algebra.Generators.Cotangent.val_smul''' +AlgebraicClosure.toStepOfLE' +AlgebraicGeometry.basicOpen_eq_of_affine' +AlgebraicGeometry.IsAffineOpen.fromSpec_preimage_basicOpen' +AlgebraicGeometry.IsAffineOpen.isLocalization_stalk' +AlgebraicGeometry.IsOpenImmersion.hasLimit_cospan_forget_of_left' +AlgebraicGeometry.IsOpenImmersion.hasLimit_cospan_forget_of_right' +AlgebraicGeometry.LocallyRingedSpace.Hom.ext' +AlgebraicGeometry.LocallyRingedSpace.id_val' +AlgebraicGeometry.LocallyRingedSpace.stalkMap_germ' +AlgebraicGeometry.morphismRestrict_app' +AlgebraicGeometry.PresheafedSpace.GlueData.opensImagePreimageMap_app' +AlgebraicGeometry.PresheafedSpace.IsOpenImmersion.c_iso' +AlgebraicGeometry.PresheafedSpace.stalkMap_germ' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.add_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.mul_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.neg_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.one_mem' +AlgebraicGeometry.ProjectiveSpectrum.StructureSheaf.SectionSubring.zero_mem' +AlgebraicGeometry.ProjIsoSpecTopComponent.FromSpec.mem_carrier_iff' +AlgebraicGeometry.Proj.stalkIso'_germ' +AlgebraicGeometry.Scheme.Hom.appIso_hom' +AlgebraicGeometry.Scheme.Hom.appLE_map' +AlgebraicGeometry.Scheme.Hom.map_appLE' +AlgebraicGeometry.Scheme.map_basicOpen' +AlgebraicGeometry.Scheme.mem_basicOpen_top' +AlgebraicGeometry.Scheme.Opens.germ_stalkIso_hom' +AlgebraicGeometry.Scheme.stalkMap_germ' +AlgebraicGeometry.SheafedSpace.comp_c_app' +AlgebraicGeometry.SheafedSpace.IsOpenImmersion.hasLimit_cospan_forget_of_left' +AlgebraicGeometry.SheafedSpace.IsOpenImmersion.hasLimit_cospan_forget_of_right' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_presheaf' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_presheaf_map' +AlgebraicGeometry.Spec.locallyRingedSpaceObj_sheaf' +AlgebraicGeometry.stalkToFiberRingHom_germ' +AlgebraicGeometry.StructureSheaf.comap_id' +AlgebraicGeometry.StructureSheaf.const_apply' +AlgebraicGeometry.StructureSheaf.const_mul_cancel' +AlgebraicGeometry.StructureSheaf.IsFraction.eq_mk' +AlgebraicGeometry.StructureSheaf.localizationToStalk_mk' +AlgebraicGeometry.StructureSheaf.res_const' +AlgebraicGeometry.StructureSheaf.stalkToFiberRingHom_germ' +AlgebraicGeometry.StructureSheaf.toBasicOpen_mk' +AlgebraicGeometry.ΓSpec.adjunction_counit_app' +AlgebraicGeometry.ΓSpec.locallyRingedSpaceAdjunction_counit_app' +AlgebraicGeometry.ΓSpec.locallyRingedSpaceAdjunction_homEquiv_apply' +AlgebraicGeometry.ΓSpec.toOpen_unit_app_val_c_app' +algebraicIndependent_equiv' +AlgebraicIndependent.map' +AlgebraicIndependent.to_subtype_range' +AlgebraicTopology.DoldKan.hσ'_eq' +AlgebraicTopology.DoldKan.Γ₀.Obj.map_on_summand' +AlgebraicTopology.DoldKan.Γ₀.Obj.map_on_summand₀' +AlgebraicTopology.DoldKan.Γ₀.Obj.Termwise.mapMono_δ₀' +Algebra.IsAlgebraic.bijective_of_isScalarTower' +Algebra.TensorProduct.algebraMap_apply' +Algebra.TensorProduct.basis_repr_symm_apply' +Algebra.TensorProduct.ext' +Algebra.TensorProduct.intCast_def' +Algebra.TensorProduct.natCast_def' +Algebra.toMatrix_lmul' +AlgEquiv.apply_smulCommClass' +AlgEquiv.coe_restrictScalars' +AlgEquiv.coe_ringEquiv' +AlgEquiv.mk_coe' +AlgHom.coe_mk' +AlgHom.coe_restrictScalars' +AlgHom.toAddMonoidHom' +AlgHom.toMonoidHom' +AlternatingMap.domCoprod.summand_mk'' +analyticOnNhd_congr' +AnalyticOnNhd.congr' +AnalyticOnNhd.eval_continuousLinearMap' +AnalyticOnNhd.eval_linearMap' +AntilipschitzWith.le_mul_nnnorm' +AntilipschitzWith.le_mul_norm' +AntilipschitzWith.to_rightInvOn' +antisymm' +Antitone.const_mul' +Antitone.mul_const' +AntitoneOn.const_mul' +AntitoneOn.mul_const' +Applicative.pure_seq_eq_map' +ApplicativeTransformation.preserves_map' +apply_abs_le_mul_of_one_le' +ArithmeticFunction.mul_smul' +ArithmeticFunction.one_smul' +ArithmeticFunction.ppow_succ' +ArithmeticFunction.sum_eq_iff_sum_smul_moebius_eq_on' +Associated.dvd' +Associated.of_pow_associated_of_prime' +Associates.count_mul_of_coprime' +Associates.dvd_of_mem_factors' +Associates.map_subtype_coe_factors' +Associates.mk_ne_zero' +Associates.unique' +Asymptotics.IsBigO.congr' +Asymptotics.isBigO_const_mul_left_iff' +Asymptotics.IsBigO.const_mul_right' +Asymptotics.isBigO_const_mul_right_iff' +Asymptotics.isBigO_fst_prod' +Asymptotics.IsBigO.of_bound' +Asymptotics.isBigO_of_le' +Asymptotics.isBigO_self_const_mul' +Asymptotics.isBigO_snd_prod' +Asymptotics.IsBigOWith.congr' +Asymptotics.IsBigOWith.const_mul_right' +Asymptotics.isBigOWith_of_le' +Asymptotics.IsBigOWith.pow' +Asymptotics.isBigOWith_self_const_mul' +Asymptotics.IsBigOWith.sup' +Asymptotics.isBigOWith_zero' +Asymptotics.isEquivalent_of_tendsto_one' +Asymptotics.IsLittleO.congr' +Asymptotics.isLittleO_const_mul_left_iff' +Asymptotics.IsLittleO.const_mul_right' +Asymptotics.isLittleO_const_mul_right_iff' +Asymptotics.IsLittleO.def' +Asymptotics.isLittleO_iff_nat_mul_le' +Asymptotics.isLittleO_iff_tendsto' +Asymptotics.isLittleO_irrefl' +Asymptotics.IsLittleO.right_isBigO_add' +Asymptotics.IsLittleO.right_isTheta_add' +Asymptotics.isTheta_of_norm_eventuallyEq' +Asymptotics.SuperpolynomialDecay.congr' +ball_eq' +Ballot.ballot_problem' +Basis.det_map' +Basis.det_reindex' +Basis.mk_eq_rank' +Basis.mk_eq_rank'' +Basis.reindexRange_repr' +Basis.repr_eq_iff' +Basis.tensorProduct_apply' +Behrend.bound_aux' +Behrend.lower_bound_le_one' +Behrend.map_succ' +bernoulli'_def' +bernoulli'_spec' +bernoulli_spec' +bernsteinPolynomial.flip' +Besicovitch.SatelliteConfig.hlast' +Besicovitch.SatelliteConfig.inter' +bihimp_eq' +biInf_congr' +biInf_finsetSigma' +biInf_sigma' +Bimod.AssociatorBimod.hom_left_act_hom' +Bimod.AssociatorBimod.hom_right_act_hom' +Bimod.comp_hom' +Bimod.id_hom' +Bimod.LeftUnitorBimod.hom_left_act_hom' +Bimod.LeftUnitorBimod.hom_right_act_hom' +Bimod.RightUnitorBimod.hom_left_act_hom' +Bimod.RightUnitorBimod.hom_right_act_hom' +Bimod.TensorBimod.actRight_one' +Bimod.TensorBimod.left_assoc' +Bimod.TensorBimod.middle_assoc' +Bimod.TensorBimod.one_act_left' +Bimod.TensorBimod.right_assoc' +Bimon_.comp_hom' +Bimon_.id_hom' +birkhoffAverage_congr_ring' +birkhoffAverage_one' +birkhoffAverage_zero' +birkhoffSum_one' +birkhoffSum_succ' +birkhoffSum_zero' +biSup_congr' +biSup_finsetSigma' +biSup_sigma' +BooleanRing.add_eq_zero' +Bool.eq_false_of_not_eq_true' +Bool.eq_true_of_not_eq_false' +Bornology.ext_iff' +Bornology.IsBounded.exists_pos_norm_le' +Bornology.IsBounded.exists_pos_norm_lt' +bound' +BoundedContinuousFunction.const_apply' +BoundedContinuousFunction.dist_le_two_norm' +BoundedContinuousFunction.dist_nonneg' +BoundedContinuousFunction.extend_apply' +BoundedContinuousFunction.instModule' +BoundedContinuousFunction.instSMul' +BoundedLatticeHom.coe_comp_inf_hom' +BoundedLatticeHom.coe_comp_lattice_hom' +BoundedLatticeHom.coe_comp_sup_hom' +BoxIntegral.Box.coe_mk' +BoxIntegral.Box.volume_apply' +BoxIntegral.IntegrationParams.toFilterDistortioniUnion_neBot' +BoxIntegral.Prepartition.iUnion_def' +BoxIntegral.Prepartition.mem_restrict' +BoxIntegral.Prepartition.mem_split_iff' +BoxIntegral.TaggedPrepartition.IsSubordinate.mono' +Bundle.TotalSpace.mk' +calc_eval_z' +card_dvd_exponent_pow_rank' +Cardinal.add_eq_max' +Cardinal.add_le_add' +Cardinal.add_mk_eq_max' +Cardinal.aleph0_le_aleph' +Cardinal.aleph_eq_aleph' +Cardinal.alephIdx_aleph' +Cardinal.cantor' +Cardinal.lift_lt_univ' +Cardinal.lift_mk_shrink' +Cardinal.lift_mk_shrink'' +Cardinal.lt_univ' +Cardinal.mk_eq_two_iff' +Cardinal.mk_finsupp_lift_of_infinite' +Cardinal.mk_finsupp_of_infinite' +Cardinal.mul_comm' +Cardinal.mul_eq_max' +Cardinal.prod_const' +Cardinal.sum_add_distrib' +Cardinal.sum_const' +Cardinal.two_le_iff' +card_le_of_injective' +card_le_of_surjective' +catalan_succ' +CategoryTheory.Abelian.coimageImageComparison_eq_coimageImageComparison' +CategoryTheory.Abelian.epi_of_epi_of_epi_of_mono' +CategoryTheory.Abelian.epi_of_mono_of_epi_of_mono' +CategoryTheory.Abelian.Ext.add_hom' +CategoryTheory.Abelian.Ext.neg_hom' +CategoryTheory.Abelian.FunctorCategory.coimageImageComparison_app' +CategoryTheory.Abelian.mono_of_epi_of_epi_mono' +CategoryTheory.Abelian.mono_of_epi_of_mono_of_mono' +CategoryTheory.Abelian.OfCoimageImageComparisonIsIso.imageMonoFactorisation_e' +CategoryTheory.Abelian.Pseudoelement.pseudoApply_mk' +CategoryTheory.Abelian.Pseudoelement.zero_eq_zero' +CategoryTheory.Abelian.Pseudoelement.zero_morphism_ext' +CategoryTheory.ActionCategory.cases' +CategoryTheory.additive_coyonedaObj' +CategoryTheory.additive_yonedaObj' +CategoryTheory.Adhesive.van_kampen' +CategoryTheory.Adjunction.he'' +CategoryTheory.Arrow.iso_w' +CategoryTheory.BicategoricalCoherence.assoc' +CategoryTheory.BicategoricalCoherence.left' +CategoryTheory.BicategoricalCoherence.right' +CategoryTheory.BicategoricalCoherence.tensorRight' +CategoryTheory.Bifunctor.diagonal' +CategoryTheory.Biproduct.column_nonzero_of_iso' +CategoryTheory.BraidedCategory.yang_baxter' +CategoryTheory.BraidedFunctor.ext' +CategoryTheory.CategoryOfElements.CreatesLimitsAux.π_liftedConeElement' +CategoryTheory.CechNerveTerminalFrom.hasWidePullback' +CategoryTheory.CommSq.HasLift.mk' +CategoryTheory.Comonad.Coalgebra.Hom.ext' +CategoryTheory.ComonadHom.ext' +CategoryTheory.comp_apply' +CategoryTheory.ComposableArrows.Exact.exact' +CategoryTheory.ComposableArrows.IsComplex.zero' +CategoryTheory.ComposableArrows.map'_inv_eq_inv_map' +CategoryTheory.ComposableArrows.naturality' +CategoryTheory.ComposableArrows.Precomp.map_zero_one' +CategoryTheory.composePath_comp' +CategoryTheory.conj_eqToHom_iff_heq' +CategoryTheory.CosimplicialObject.δ_comp_δ' +CategoryTheory.CosimplicialObject.δ_comp_δ'' +CategoryTheory.CosimplicialObject.δ_comp_δ_self' +CategoryTheory.CosimplicialObject.δ_comp_σ_of_gt' +CategoryTheory.CosimplicialObject.δ_comp_σ_self' +CategoryTheory.CosimplicialObject.δ_comp_σ_succ' +CategoryTheory.DifferentialObject.eqToHom_f' +CategoryTheory.e_assoc' +CategoryTheory.Endofunctor.Algebra.Initial.left_inv' +CategoryTheory.eq_of_comp_left_eq' +CategoryTheory.eq_of_comp_right_eq' +CategoryTheory.Equivalence.cancel_counitInv_right_assoc' +CategoryTheory.Equivalence.cancel_unit_right_assoc' +CategoryTheory.ExactPairing.coevaluation_evaluation'' +CategoryTheory.ExactPairing.evaluation_coevaluation'' +CategoryTheory.exists_zigzag' +CategoryTheory.forgetEnrichment_id' +CategoryTheory.Functor.commShiftIso_add' +CategoryTheory.Functor.coreflective' +CategoryTheory.Functor.HasRightDerivedFunctor.mk' +CategoryTheory.Functor.inl_biprodComparison' +CategoryTheory.Functor.inr_biprodComparison' +CategoryTheory.Functor.isContinuous_comp' +CategoryTheory.Functor.IsHomological.mk' +CategoryTheory.Functor.IsLocalization.mk' +CategoryTheory.Functor.Iteration.Hom.ext' +CategoryTheory.Functor.map_comp_heq' +CategoryTheory.Functor.postcomp_map_heq' +CategoryTheory.Functor.reflective' +CategoryTheory.Functor.relativelyRepresentable.map_fst' +CategoryTheory.Functor.relativelyRepresentable.w' +CategoryTheory.Functor.shiftIso_add' +CategoryTheory.Functor.shiftMap_comp' +CategoryTheory.FunctorToTypes.jointly_surjective' +CategoryTheory.FunctorToTypes.prod_ext' +CategoryTheory.Functor.uncurry_obj_curry_obj_flip_flip' +CategoryTheory.Functor.ι_biproductComparison' +CategoryTheory.Grothendieck.comp_fiber' +CategoryTheory.Grothendieck.id_fiber' +CategoryTheory.GrothendieckTopology.OneHypercoverFamily.IsSheafIff.fac' +CategoryTheory.GrothendieckTopology.OneHypercover.mem_sieve₁' +CategoryTheory.GrothendieckTopology.WEqualsLocallyBijective.mk' +CategoryTheory.Grpd.str' +CategoryTheory.HasPullbacksOfInclusions.hasPullbackInr' +CategoryTheory.HasPullbacksOfInclusions.preservesPullbackInl' +CategoryTheory.HasSheafify.mk' +CategoryTheory.Injective.injective_iff_preservesEpimorphisms_preadditive_yoneda_obj' +CategoryTheory.IsCoreflexivePair.mk' +CategoryTheory.IsHomLift.fac' +CategoryTheory.IsHomLift.of_fac' +CategoryTheory.Iso.inv_ext' +CategoryTheory.IsPullback.inl_snd' +CategoryTheory.IsPullback.inr_fst' +CategoryTheory.IsPullback.of_hasBinaryProduct' +CategoryTheory.IsPullback.of_is_bilimit' +CategoryTheory.IsPushout.inl_snd' +CategoryTheory.IsPushout.inr_fst' +CategoryTheory.IsPushout.of_hasBinaryCoproduct' +CategoryTheory.IsPushout.of_is_bilimit' +CategoryTheory.IsReflexivePair.mk' +CategoryTheory.isSheaf_yoneda' +CategoryTheory.LaxBraidedFunctor.ext' +CategoryTheory.Limits.biprod.hom_ext' +CategoryTheory.Limits.biprod.map_eq_map' +CategoryTheory.Limits.biprod.symmetry' +CategoryTheory.Limits.biproduct.hom_ext' +CategoryTheory.Limits.biproduct.map_eq_map' +CategoryTheory.Limits.Cofork.IsColimit.π_desc' +CategoryTheory.Limits.colimit.pre_map' +CategoryTheory.Limits.colimMap_epi' +CategoryTheory.Limits.Concrete.widePullback_ext' +CategoryTheory.Limits.Concrete.widePushout_exists_rep' +CategoryTheory.Limits.coprod.symmetry' +CategoryTheory.Limits.equalizerSubobject_arrow' +CategoryTheory.Limits.Fork.IsLimit.lift_ι' +CategoryTheory.Limits.ImageMap.mk.injEq' +CategoryTheory.Limits.imageSubobject_arrow' +CategoryTheory.Limits.kernelSubobject_arrow' +CategoryTheory.Limits.limit.map_pre' +CategoryTheory.Limits.limLax_obj' +CategoryTheory.Limits.limMap_mono' +CategoryTheory.Limits.MonoCoprod.mk' +CategoryTheory.Limits.MonoCoprod.mono_binaryCofanSum_inl' +CategoryTheory.Limits.MonoCoprod.mono_binaryCofanSum_inr' +CategoryTheory.Limits.MonoCoprod.mono_of_injective' +CategoryTheory.Limits.Multicoequalizer.multicofork_ι_app_right' +CategoryTheory.Limits.Multicofork.ofSigmaCofork_ι_app_right' +CategoryTheory.Limits.parallelPair_initial_mk' +CategoryTheory.Limits.Pi.map'_comp_map' +CategoryTheory.Limits.Pi.map_comp_map' +CategoryTheory.Limits.prod.symmetry' +CategoryTheory.Limits.Sigma.map'_comp_map' +CategoryTheory.Limits.Sigma.map_comp_map' +CategoryTheory.Limits.Sigma.ι_comp_map' +CategoryTheory.Limits.Types.Colimit.w_apply' +CategoryTheory.Limits.Types.Colimit.ι_desc_apply' +CategoryTheory.Limits.Types.Colimit.ι_map_apply' +CategoryTheory.Limits.Types.limit_ext' +CategoryTheory.Limits.Types.limit_ext_iff' +CategoryTheory.Limits.Types.Limit.lift_π_apply' +CategoryTheory.Limits.Types.Limit.map_π_apply' +CategoryTheory.Limits.Types.Limit.w_apply' +CategoryTheory.Limits.Types.Pushout.equivalence_rel' +CategoryTheory.Limits.WalkingParallelPairHom.id.sizeOf_spec' +CategoryTheory.Limits.zero_of_source_iso_zero' +CategoryTheory.Limits.zero_of_target_iso_zero' +CategoryTheory.Localization.Preadditive.comp_add' +CategoryTheory.Localization.Preadditive.zero_add' +CategoryTheory.Localization.SmallShiftedHom.equiv_shift' +CategoryTheory.LocalizerMorphism.guitartExact_of_isRightDerivabilityStructure' +CategoryTheory.LocalizerMorphism.IsLocalizedEquivalence.mk' +CategoryTheory.Mat_.additiveObjIsoBiproduct_naturality' +CategoryTheory.Monad.Algebra.Hom.ext' +CategoryTheory.MonadHom.ext' +CategoryTheory.MonoidalCategory.hom_inv_id_tensor' +CategoryTheory.MonoidalCategory.hom_inv_whiskerRight' +CategoryTheory.MonoidalCategory.inv_hom_id_tensor' +CategoryTheory.MonoidalCategory.inv_hom_whiskerRight' +CategoryTheory.MonoidalCategory.leftUnitor_tensor' +CategoryTheory.MonoidalCategory.leftUnitor_tensor'' +CategoryTheory.MonoidalCategory.leftUnitor_tensor_inv' +CategoryTheory.MonoidalCategory.tensorHom_def' +CategoryTheory.MonoidalCategory.tensor_hom_inv_id' +CategoryTheory.MonoidalCategory.tensor_inv_hom_id' +CategoryTheory.MonoidalCategory.tensorIso_def' +CategoryTheory.MonoidalCategory.whiskerLeft_hom_inv' +CategoryTheory.MonoidalCategory.whiskerLeft_inv_hom' +CategoryTheory.MonoidalCoherence.assoc' +CategoryTheory.MonoidalCoherence.left' +CategoryTheory.MonoidalCoherence.right' +CategoryTheory.MonoidalCoherence.tensor_right' +CategoryTheory.MonoidalNatTrans.ext' +CategoryTheory.MonoOver.mk'_coe' +CategoryTheory.NatIso.naturality_1' +CategoryTheory.NatIso.naturality_2' +CategoryTheory.NatTrans.ext' +CategoryTheory.NatTrans.id_app' +CategoryTheory.NatTrans.vcomp_app' +CategoryTheory.NonPreadditiveAbelian.neg_sub' +CategoryTheory.OplaxNatTrans.Modification.comp_app' +CategoryTheory.OplaxNatTrans.Modification.id_app' +CategoryTheory.Preadditive.epi_iff_surjective' +CategoryTheory.Preadditive.epi_of_isZero_cokernel' +CategoryTheory.Preadditive.mono_iff_injective' +CategoryTheory.Preadditive.mono_of_isZero_kernel' +CategoryTheory.Prefunctor.mapPath_comp' +CategoryTheory.PreOneHypercover.sieve₁_eq_pullback_sieve₁' +CategoryTheory.PreservesPullbacksOfInclusions.preservesPullbackInl' +CategoryTheory.PreservesPullbacksOfInclusions.preservesPullbackInr' +CategoryTheory.Presheaf.isLocallyInjective_toSheafify' +CategoryTheory.Presheaf.isLocallySurjective_iff_imagePresheaf_sheafify_eq_top' +CategoryTheory.Presheaf.isLocallySurjective_toSheafify' +CategoryTheory.Pretriangulated.mem_distTriang_op_iff' +CategoryTheory.Pretriangulated.Opposite.mem_distinguishedTriangles_iff' +CategoryTheory.Projective.projective_iff_preservesEpimorphisms_preadditiveCoyoneda_obj' +CategoryTheory.ProjectiveResolution.pOpcycles_comp_fromLeftDerivedZero' +CategoryTheory.Quiv.str' +CategoryTheory.Quotient.lift_unique' +CategoryTheory.RanIsSheafOfIsCocontinuous.fac' +CategoryTheory.RanIsSheafOfIsCocontinuous.liftAux_map' +CategoryTheory.regularTopology.equalizerCondition_w' +CategoryTheory.Sheaf.epi_of_isLocallySurjective' +CategoryTheory.Sheaf.isLocallySurjective_iff_epi' +CategoryTheory.SheafOfTypes.Hom.ext' +CategoryTheory.shift_neg_shift' +CategoryTheory.shift_shift' +CategoryTheory.shift_shift_neg' +CategoryTheory.shiftZero' +CategoryTheory.ShortComplex.abLeftHomologyData_f' +CategoryTheory.ShortComplex.epi_homologyMap_of_epi_cyclesMap' +CategoryTheory.ShortComplex.Exact.desc' +CategoryTheory.ShortComplex.Exact.epi_f' +CategoryTheory.ShortComplex.exact_iff_epi_imageToKernel' +CategoryTheory.ShortComplex.Exact.isIso_f' +CategoryTheory.ShortComplex.Exact.isIso_g' +CategoryTheory.ShortComplex.Exact.lift' +CategoryTheory.ShortComplex.Exact.mono_g' +CategoryTheory.ShortComplex.f'_cyclesMap' +CategoryTheory.ShortComplex.HasHomology.mk' +CategoryTheory.ShortComplex.hasHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasHomology_of_isIso_leftRightHomologyComparison' +CategoryTheory.ShortComplex.hasHomology_of_preserves' +CategoryTheory.ShortComplex.HasLeftHomology.mk' +CategoryTheory.ShortComplex.hasLeftHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasLeftHomology_of_preserves' +CategoryTheory.ShortComplex.HasRightHomology.mk' +CategoryTheory.ShortComplex.hasRightHomology_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.hasRightHomology_of_preserves' +CategoryTheory.ShortComplex.HomologyData.exact_iff' +CategoryTheory.ShortComplex.HomologyData.map_homologyMap' +CategoryTheory.ShortComplex.isIso₂_of_shortExact_of_isIso₁₃' +CategoryTheory.ShortComplex.isIso_cyclesMap_of_isIso_of_mono' +CategoryTheory.ShortComplex.isIso_homologyMap_of_epi_of_isIso_of_mono' +CategoryTheory.ShortComplex.isIso_leftRightHomologyComparison' +CategoryTheory.ShortComplex.isIso_opcyclesMap_of_isIso_of_epi' +CategoryTheory.ShortComplex.LeftHomologyData.exact_iff_epi_f' +CategoryTheory.ShortComplex.LeftHomologyData.map_cyclesMap' +CategoryTheory.ShortComplex.LeftHomologyData.map_f' +CategoryTheory.ShortComplex.LeftHomologyData.map_leftHomologyMap' +CategoryTheory.ShortComplex.LeftHomologyData.ofEpiOfIsIsoOfMono'_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofIsColimitCokernelCofork_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofIsLimitKernelFork_f' +CategoryTheory.ShortComplex.LeftHomologyData.ofZeros_f' +CategoryTheory.ShortComplex.LeftHomologyData.op_g' +CategoryTheory.ShortComplex.LeftHomologyData.unop_g' +CategoryTheory.ShortComplex.LeftHomologyData.τ₁_ofEpiOfIsIsoOfMono_f' +CategoryTheory.ShortComplex.leftHomologyπ_naturality' +CategoryTheory.ShortComplex.leftRightHomologyComparison'_eq_leftHomologpMap'_comp_iso_hom_comp_rightHomologyMap' +CategoryTheory.ShortComplex.moduleCatLeftHomologyData_f' +CategoryTheory.ShortComplex.mono_homologyMap_of_mono_opcyclesMap' +CategoryTheory.ShortComplex.opcyclesMap'_g' +CategoryTheory.ShortComplex.p_opcyclesMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_homologyMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_leftHomologyMap' +CategoryTheory.ShortComplex.quasiIso_iff_isIso_rightHomologyMap' +CategoryTheory.ShortComplex.RightHomologyData.exact_iff_mono_g' +CategoryTheory.ShortComplex.RightHomologyData.map_g' +CategoryTheory.ShortComplex.RightHomologyData.map_opcyclesMap' +CategoryTheory.ShortComplex.RightHomologyData.map_rightHomologyMap' +CategoryTheory.ShortComplex.RightHomologyData.ofEpiOfIsIsoOfMono_g' +CategoryTheory.ShortComplex.RightHomologyData.ofIsColimitCokernelCofork_g' +CategoryTheory.ShortComplex.RightHomologyData.ofIsLimitKernelFork_g' +CategoryTheory.ShortComplex.RightHomologyData.ofZeros_g' +CategoryTheory.ShortComplex.RightHomologyData.op_f' +CategoryTheory.ShortComplex.RightHomologyData.p_g' +CategoryTheory.ShortComplex.RightHomologyData.unop_f' +CategoryTheory.ShortComplex.RightHomologyData.ι_g' +CategoryTheory.ShortComplex.rightHomologyι_naturality' +CategoryTheory.ShortComplex.ShortExact.mk' +CategoryTheory.ShortComplex.ShortExact.δ_apply' +CategoryTheory.ShortComplex.ShortExact.δ_eq' +CategoryTheory.SimplicialObject.δ_comp_δ' +CategoryTheory.SimplicialObject.δ_comp_δ'' +CategoryTheory.SimplicialObject.δ_comp_δ_self' +CategoryTheory.SimplicialObject.δ_comp_σ_of_gt' +CategoryTheory.SimplicialObject.δ_comp_σ_self' +CategoryTheory.SimplicialObject.δ_comp_σ_succ' +CategoryTheory.SingleFunctors.shiftIso_add' +CategoryTheory.StrongEpi.mk' +CategoryTheory.StrongMono.mk' +CategoryTheory.Subgroupoid.coe_inv_coe' +CategoryTheory.Subgroupoid.IsNormal.conj' +CategoryTheory.Subobject.inf_eq_map_pullback' +CategoryTheory.Tor'_map_app' +CategoryTheory.Triangulated.Subcategory.ext₁' +CategoryTheory.Triangulated.Subcategory.ext₃' +CategoryTheory.Triangulated.Subcategory.W_iff' +CategoryTheory.Triangulated.Subcategory.W.mk' +CategoryTheory.TwoSquare.GuitartExact.vComp' +CategoryTheory.whiskerLeft_id' +CategoryTheory.whiskerRight_id' +CategoryTheory.yonedaEquiv_naturality' +Cauchy.comap' +CauchyFilter.mem_uniformity' +cauchy_iff' +cauchy_iInf_uniformSpace' +cauchy_map_iff' +Cauchy.mono' +cauchy_pi_iff' +cauchySeq_iff' +CauSeq.bounded' +CauSeq.mul_equiv_zero' +cfc_comp' +cfcₙ_comp' +CharP.exists' +CharP.natCast_eq_natCast' +charP_of_injective_algebraMap' +CharP.pi' +CharP.subring' +ChartedSpaceCore.open_source' +CharTwo.neg_eq' +CharTwo.sub_eq_add' +ciInf_le' +ciInf_le_of_le' +ciInf_subtype' +ciInf_subtype'' +CircleDeg1Lift.tendsto_translation_number' +CircleDeg1Lift.tendsto_translation_number₀' +CircleDeg1Lift.translationNumber_conj_eq' +CircleDeg1Lift.translationNumber_eq_of_tendsto₀' +circleIntegral.norm_integral_le_of_norm_le_const' +circleMap_mem_sphere' +ciSup_le' +ciSup_le_iff' +ciSup_mono' +ciSup_or' +ciSup_subtype' +ciSup_subtype'' +Classical.choose_eq' +CliffordAlgebra.instAlgebra' +CliffordAlgebra.star_def' +ClosedIciTopology.isClosed_ge' +ClosedIicTopology.isClosed_le' +closedUnderRestriction' +closure_smul₀' +clusterPt_iff_lift'_closure' +ClusterPt.of_le_nhds' +cmp_div_one' +cmp_mul_left' +cmp_mul_right' +CochainComplex.HomComplex.Cochain.shift_v' +CochainComplex.mappingCone.d_fst_v' +CochainComplex.mappingCone.d_snd_v' +CochainComplex.shiftFunctorAdd'_hom_app_f' +CochainComplex.shiftFunctorAdd'_inv_app_f' +CochainComplex.shiftFunctor_map_f' +CochainComplex.shiftFunctor_obj_d' +CochainComplex.shiftFunctor_obj_X' +Codisjoint.ne_bot_of_ne_top' +Codisjoint.of_codisjoint_sup_of_le' +Codisjoint.sup_left' +Codisjoint.sup_right' +coe_comp_nnnorm' +coe_nnnorm' +CofiniteTopology.isOpen_iff' +comap_norm_atTop' +comap_norm_nhdsWithin_Ioi_zero' +CommGrp.coe_comp' +CommGrp.coe_id' +CommMon_.comp' +CommMon_.id' +commProb_def' +CommRingCat.equalizer_ι_is_local_ring_hom' +CommRingCat.instCommRing' +CommRingCat.instFunLike' +CommRingCat.instFunLike'' +CommRingCat.instFunLike''' +CommSemiRingCat.instCommSemiring' +Commute.mul_self_sub_mul_self_eq' +Comon_.comp_hom' +Comon_.id_hom' +CompactIccSpace.mk' +CompactIccSpace.mk'' +CompHaus.toProfinite_obj' +compl_beattySeq' +CompleteLattice.Independent.comp' +CompleteLattice.independent_def' +CompleteLattice.independent_def'' +CompleteLattice.independent_of_dfinsupp_sumAddHom_injective' +CompleteLattice.Independent.supIndep' +CompleteLattice.inf_continuous' +CompleteLattice.sSup_continuous' +CompletelyDistribLattice.MinimalAxioms.iInf_iSup_eq' +CompleteOrthogonalIdempotents.bijective_pi' +CompleteSublattice.coe_sInf' +CompleteSublattice.coe_sSup' +Complex.abs_eq_one_iff' +Complex.AbsTheory.abs_nonneg' +Complex.affine_of_mapsTo_ball_of_exists_norm_dslope_eq_div' +Complex.conj_mul' +Complex.cos_eq_tsum' +Complex.cos_sq' +Complex.cos_two_mul' +Complex.cpow_ofNat_mul' +Complex.deriv_cos' +Complex.equivRealProd_apply_le' +Complex.exp_bound' +Complex.hasStrictFDerivAt_cpow' +Complex.hasSum_conj' +Complex.hasSum_cos' +Complex.hasSum_sin' +Complex.mul_conj' +Complex.ofReal_mul' +Complex.rank_real_complex' +Complex.restrictScalars_one_smulRight' +ComplexShape.Embedding.not_boundaryGE_next' +ComplexShape.Embedding.not_boundaryLE_prev' +ComplexShape.next_add' +ComplexShape.next_eq' +ComplexShape.next_eq_self' +ComplexShape.prev_eq' +ComplexShape.prev_eq_self' +Complex.sin_eq_tsum' +Complex.stolzCone_subset_stolzSet_aux' +Complex.tan_add' +Complex.UnitDisc.instSMulCommClass_circle' +Complex.UnitDisc.instSMulCommClass_closedBall' +compl_sInf' +compl_sSup' +CompositionAsSet.lt_length' +Composition.blocks_pos' +Composition.mem_range_embedding_iff' +Composition.one_le_blocks' +Composition.sizeUpTo_succ' +Computability.inhabitedΓ' +ComputablePred.computable_iff_re_compl_re' +Computable.vector_ofFn' +Computation.bind_pure' +Computation.eq_thinkN' +Computation.map_pure' +Computation.map_think' +Computation.results_of_terminates' +ConcaveOn.left_le_of_le_right' +ConcaveOn.left_le_of_le_right'' +ConcaveOn.left_lt_of_lt_right' +ConcaveOn.lt_right_of_left_lt' +ConcaveOn.mul' +ConcaveOn.mul_convexOn' +ConcaveOn.right_le_of_le_left' +ConcaveOn.right_le_of_le_left'' +ConcaveOn.smul' +ConcaveOn.smul'' +ConcaveOn.smul_convexOn' +Concept.ext' +Con.coe_mk' +conformalFactorAt_inner_eq_mul_inner' +CongruenceSubgroup.Gamma1_mem' +CongruenceSubgroup.Gamma_mem' +ConjAct.smulCommClass' +ConjAct.smulCommClass₀' +ConjAct.unitsSMulCommClass' +conjneg_neg' +conjugate_le_conjugate' +conjugate_lt_conjugate' +conjugate_nonneg' +conjugate_pos' +Con.mrange_mk' +ConnectedComponents.coe_eq_coe' +connectedComponents_lift_unique' +ContDiffAt.comp' +contDiffAt_id' +contDiffAt_pi' +contDiffAt_prod' +ContDiff.comp' +contDiff_id' +ContDiff.iterate_deriv' +ContDiffOn.div' +contDiffOn_id' +contDiffOn_pi' +contDiffOn_prod' +contDiff_pi' +contDiff_prod' +ContDiffWithinAt.congr' +ContDiffWithinAt.congr_of_eventually_eq' +ContDiffWithinAt.contDiffOn' +contDiffWithinAt_inter' +contDiffWithinAt_prod' +ContinuousAlgHom.coe_comp' +ContinuousAlgHom.coe_fst' +ContinuousAlgHom.coe_id' +ContinuousAlgHom.coe_mk' +ContinuousAlgHom.coe_prodMap' +ContinuousAlgHom.coe_restrictScalars' +ContinuousAlgHom.coe_snd' +ContinuousAt.comp' +continuousAt_const_cpow' +ContinuousAt.div' +continuousAt_extChartAt' +continuousAt_extChartAt_symm' +continuousAt_extChartAt_symm'' +ContinuousAt.finset_inf' +ContinuousAt.finset_sup' +continuousAt_id' +continuousAt_iff_continuous_left'_right' +ContinuousAt.inf' +continuousAt_jacobiTheta₂' +ContinuousAt.nnnorm' +ContinuousAt.norm' +continuousAt_pi' +ContinuousAt.prod_map' +ContinuousAt.sup' +Continuous.comp' +Continuous.comp_continuousOn' +Continuous.div' +continuous_div_left' +continuous_div_right' +Continuous.finset_inf' +Continuous.finset_sup' +continuous_id' +continuous_if' +Continuous.inf' +ContinuousLinearEquiv.coe_refl' +ContinuousLinearEquiv.comp_hasFDerivAt_iff' +ContinuousLinearEquiv.comp_hasFDerivWithinAt_iff' +ContinuousLinearEquiv.comp_right_hasFDerivAt_iff' +ContinuousLinearEquiv.comp_right_hasFDerivWithinAt_iff' +ContinuousLinearMap.apply_apply' +ContinuousLinearMap.applySMulCommClass' +ContinuousLinearMap.coe_add' +ContinuousLinearMap.coe_comp' +ContinuousLinearMap.coe_flipₗᵢ' +ContinuousLinearMap.coeFn_compLp' +ContinuousLinearMap.coe_fst' +ContinuousLinearMap.coe_id' +ContinuousLinearMap.coe_mk' +ContinuousLinearMap.coe_neg' +ContinuousLinearMap.coe_pi' +ContinuousLinearMap.coe_prodMap' +ContinuousLinearMap.coe_restrictScalars' +ContinuousLinearMap.coe_restrict_scalarsL' +ContinuousLinearMap.coe_smul' +ContinuousLinearMap.coe_snd' +ContinuousLinearMap.coe_sub' +ContinuousLinearMap.coe_sum' +ContinuousLinearMap.coe_zero' +ContinuousLinearMap.compFormalMultilinearSeries_apply' +ContinuousLinearMap.comp_memℒp' +ContinuousLinearMap.integral_comp_comm' +ContinuousLinearMap.measurable_apply' +ContinuousLinearMap.mul_apply' +ContinuousLinearMap.norm_extendTo𝕜' +ContinuousLinearMap.opNorm_le_of_shell' +ContinuousLinearMap.sub_apply' +ContinuousLinearMap.toSpanSingleton_smul' +ContinuousMap.coe_const' +ContinuousMap.coe_inf' +ContinuousMap.coe_sup' +ContinuousMap.comp_yonedaPresheaf' +ContinuousMap.continuous.comp' +ContinuousMap.continuous_const' +ContinuousMap.instSMul' +ContinuousMap.liftCover_coe' +ContinuousMap.liftCover_restrict' +ContinuousMap.module' +ContinuousMap.unitsLift_symm_apply_apply_inv' +ContinuousMapZero.instIsScalarTower' +ContinuousMapZero.instSMulCommClass' +Continuous.matrix_blockDiag' +Continuous.matrix_blockDiagonal' +continuousMultilinearCurryRightEquiv_apply' +continuousMultilinearCurryRightEquiv_symm_apply' +continuous_nnnorm' +Continuous.nnnorm' +continuous_norm' +Continuous.norm' +ContinuousOn.circleIntegrable' +ContinuousOn.comp' +ContinuousOn.comp'' +ContinuousOn.div' +ContinuousOn.finset_inf' +ContinuousOn.finset_sup' +continuousOn_id' +ContinuousOn.if' +continuousOn_iff' +ContinuousOn.inf' +ContinuousOn.nnnorm' +ContinuousOn.norm' +continuousOn_pi' +ContinuousOn.piecewise' +continuousOn_piecewise_ite' +ContinuousOn.sup' +Continuous.quotient_liftOn' +Continuous.quotient_map' +continuous_quotient_mk' +Continuous.strictMono_of_inj_boundedOrder' +Continuous.sup' +ContinuousWithinAt.comp' +ContinuousWithinAt.div' +ContinuousWithinAt.finset_inf' +ContinuousWithinAt.finset_sup' +ContinuousWithinAt.inf' +continuousWithinAt_inter' +ContinuousWithinAt.nnnorm' +ContinuousWithinAt.norm' +ContinuousWithinAt.preimage_mem_nhdsWithin' +ContinuousWithinAt.preimage_mem_nhdsWithin'' +ContinuousWithinAt.sup' +contMDiffAt_extChartAt' +contMDiffAt_finset_prod' +ContMDiffAt.prod_map' +contMDiff_finset_prod' +ContMDiffMap.mdifferentiable' +contMDiffOn_finset_prod' +contMDiffOn_iff_of_mem_maximalAtlas' +ContMDiffSection.mdifferentiable' +contMDiffWithinAt_finset_prod' +contMDiffWithinAt_iff_of_mem_source' +contMDiffWithinAt_inter' +ContractingWith.apriori_edist_iterate_efixedPoint_le' +ContractingWith.edist_efixedPoint_le' +ContractingWith.edist_efixedPoint_lt_top' +ContractingWith.efixedPoint_isFixedPt' +ContractingWith.efixedPoint_mem' +ContractingWith.fixedPoint_unique' +ContractingWith.one_sub_K_pos' +ContractingWith.tendsto_iterate_efixedPoint' +ConvexBody.coe_smul' +Convex.mem_toCone' +ConvexOn.le_left_of_right_le' +ConvexOn.le_left_of_right_le'' +ConvexOn.le_right_of_left_le' +ConvexOn.le_right_of_left_le'' +ConvexOn.lt_left_of_right_lt' +ConvexOn.lt_right_of_left_lt' +ConvexOn.mul' +ConvexOn.mul_concaveOn' +ConvexOn.smul' +ConvexOn.smul'' +ConvexOn.smul_concaveOn' +coord_norm' +CovBy.ne' +CoxeterSystem.alternatingWord_succ' +CoxeterSystem.exists_reduced_word' +CoxeterSystem.length_mul_ge_length_sub_length' +CoxeterSystem.simple_mul_simple_pow' +CPolynomialOn.congr' +CPolynomialOn_congr' +cpow_eq_nhds' +cross_anticomm' +csInf_le' +csInf_le_csInf' +csSup_le' +csSup_le_csSup' +csSup_le_iff' +CStarAlgebra.conjugate_le_norm_smul' +CStarAlgebra.instNonnegSpectrumClass' +CStarRing.conjugate_le_norm_smul' +CStarRing.instNonnegSpectrumClass' +CStarRing.norm_star_mul_self' +Ctop.Realizer.ext' +Cubic.degree_of_a_eq_zero' +Cubic.degree_of_a_ne_zero' +Cubic.degree_of_b_eq_zero' +Cubic.degree_of_b_ne_zero' +Cubic.degree_of_c_eq_zero' +Cubic.degree_of_c_ne_zero' +Cubic.degree_of_d_eq_zero' +Cubic.degree_of_d_ne_zero' +Cubic.leadingCoeff_of_a_ne_zero' +Cubic.leadingCoeff_of_b_ne_zero' +Cubic.leadingCoeff_of_c_eq_zero' +Cubic.leadingCoeff_of_c_ne_zero' +Cubic.monic_of_a_eq_one' +Cubic.monic_of_b_eq_one' +Cubic.monic_of_c_eq_one' +Cubic.monic_of_d_eq_one' +Cubic.natDegree_of_a_eq_zero' +Cubic.natDegree_of_a_ne_zero' +Cubic.natDegree_of_b_eq_zero' +Cubic.natDegree_of_b_ne_zero' +Cubic.natDegree_of_c_eq_zero' +Cubic.natDegree_of_c_ne_zero' +Cubic.of_a_eq_zero' +Cubic.of_b_eq_zero' +Cubic.of_c_eq_zero' +Cubic.of_d_eq_zero' +Cycle.next_reverse_eq_prev' +Cycle.prev_reverse_eq_next' +CyclotomicField.algebra' +dec_em' +Decidable.mul_lt_mul'' +Decidable.Partrec.const' +decide_False' +decide_True' +DedekindDomain.ProdAdicCompletions.algebra' +DedekindDomain.ProdAdicCompletions.algebraMap_apply' +DedekindDomain.ProdAdicCompletions.IsFiniteAdele.algebraMap' +IsDenseEmbedding.mk' +Dense.exists_ge' +Dense.exists_le' +IsDenseInducing.extend_eq_at' +IsDenseInducing.mk' +Denumerable.lower_raise' +Denumerable.raise_lower' +deriv_add_const' +Derivation.apply_aeval_eq' +Derivation.coe_mk' +deriv_const' +deriv_const_add' +deriv_const_mul_field' +deriv_id' +deriv_id'' +deriv_inv' +deriv_inv'' +deriv_mul_const_field' +deriv.neg' +deriv_neg' +deriv_neg'' +deriv_pow' +deriv_pow'' +deriv_sqrt_mul_log' +deriv.star' +derivWithin_congr_set' +derivWithin_inv' +derivWithin_pow' +deriv_zpow' +det_traceMatrix_ne_zero' +DFinsupp.coe_mk' +DFinsupp.filter_ne_eq_erase' +DFinsupp.le_iff' +DFinsupp.Lex.wellFounded' +DFinsupp.wellFoundedLT' +DFunLike.ext' +DiffContOnCl.differentiableAt' +Diffeomorph.symm_trans' +DifferentiableAt.comp' +differentiableAt_id' +differentiableAt_inv' +DifferentiableAt.inv' +differentiableAt_pi'' +Differentiable.comp' +differentiable_id' +Differentiable.inv' +DifferentiableOn.comp' +differentiableOn_id' +differentiableOn_inv' +DifferentiableOn.inv' +differentiableOn_pi'' +differentiable_pi'' +DifferentiableWithinAt.comp' +differentiableWithinAt_congr_set' +differentiableWithinAt_inter' +differentiableWithinAt_inv' +DifferentiableWithinAt.inv' +differentiableWithinAt_pi'' +DirectedOn.mono' +directedOn_pair' +DirectSum.Gmodule.mul_smul' +DirectSum.Gmodule.one_smul' +DirichletCharacter.level_one' +DirichletCharacter.toUnitHom_eq_char' +discreteTopology_iff_orderTopology_of_pred_succ' +DiscreteTopology.of_forall_le_norm' +DiscreteTopology.orderTopology_of_pred_succ' +DiscreteValuationRing.addVal_def' +Disjoint.inf_left' +Disjoint.inf_right' +Disjoint.inter_left' +Disjoint.inter_right' +Disjoint.of_disjoint_inf_of_le' +dist_eq_norm_div' +dist_le_norm_add_norm' +dist_midpoint_midpoint_le' +dist_norm_norm_le' +dist_partial_sum' +dist_pi_le_iff' +DistribMulActionHom.coe_fn_coe' +dite_eq_iff' +div_add' +div_div_cancel' +div_div_cancel_left' +div_div_div_cancel_left' +div_div_self' +div_eq_iff_eq_mul' +div_eq_of_eq_mul' +div_eq_of_eq_mul'' +div_le_div'' +div_le_div_iff' +div_le_div_left' +div_le_div_right' +div_left_inj' +div_le_iff₀' +div_le_iff_le_mul' +div_le_iff_of_neg' +div_le_one' +div_lt_div' +div_lt_div'' +div_lt_div_iff' +div_lt_div_left' +div_lt_div_right' +div_lt_iff' +div_lt_iff_lt_mul' +div_lt_iff_of_neg' +div_lt_one' +div_mul_div_cancel' +div_mul_div_cancel₀' +div_self' +div_self_mul_self' +div_sub' +Doset.disjoint_out' +Doset.out_eq' +DoubleCentralizer.nnnorm_def' +DoubleCentralizer.norm_def' +dvd_antisymm' +dvd_geom_sum₂_iff_of_dvd_sub' +edist_eq_coe_nnnorm' +EllipticCurve.coe_inv_map_Δ' +EllipticCurve.coe_inv_variableChange_Δ' +EllipticCurve.coe_map_Δ' +EllipticCurve.coe_variableChange_Δ' +em' +Embedding.mk' +EMetric.diam_pos_iff' +EMetric.diam_union' +EMetric.mem_ball' +EMetric.mem_closedBall' +EMetric.totallyBounded_iff' +ENat.sSup_eq_zero' +Encodable.mem_decode₂' +ENNReal.add_biSup' +ENNReal.biSup_add' +ENNReal.biSup_add_biSup_le' +ENNReal.div_le_iff' +ENNReal.div_le_of_le_mul' +ENNReal.div_lt_of_lt_mul' +ENNReal.exists_frequently_lt_of_liminf_ne_top' +ENNReal.exists_pos_sum_of_countable' +ENNReal.iInf_mul_left' +ENNReal.iInf_mul_right' +ENNReal.inv_le_inv' +ENNReal.inv_lt_inv' +ENNReal.log_pos_real' +ENNReal.mul_div_cancel' +ENNReal.mul_le_of_le_div' +ENNReal.mul_lt_mul_left' +ENNReal.mul_lt_mul_right' +ENNReal.mul_lt_of_lt_div' +ENNReal.mul_top' +ENNReal.nhds_top' +ENNReal.ofReal_le_ofReal_iff' +ENNReal.ofReal_lt_ofReal_iff' +ENNReal.ofReal_mul' +ENNReal.range_coe' +ENNReal.some_eq_coe' +ENNReal.toNNReal_eq_toNNReal_iff' +ENNReal.top_mul' +ENNReal.toReal_eq_toReal_iff' +ENNReal.toReal_mono' +ENNReal.toReal_ofReal' +ENNReal.tsum_eq_iSup_nat' +ENNReal.tsum_eq_iSup_sum' +ENNReal.tsum_prod' +ENNReal.tsum_sigma' +Eq.cmp_eq_eq' +eq_div_iff_mul_eq' +eq_div_iff_mul_eq'' +eq_div_of_mul_eq' +eq_div_of_mul_eq'' +eq_intCast' +eq_mul_of_div_eq' +eq_natCast' +eq_of_forall_dvd' +eq_of_prime_pow_eq' +eqOn_closure₂' +eq_one_of_inv_eq' +eq_one_of_mul_left' +eq_one_of_mul_right' +eqRec_heq' +Equiv.bijOn' +Equiv.coe_piCongr' +Equiv.exists_congr' +Equiv.existsUnique_congr' +Equiv.forall₂_congr' +Equiv.forall₃_congr' +Equiv.forall_congr' +Equiv.inhabited' +Equiv.lawfulFunctor' +Equiv.left_inv' +Equiv.Perm.cycleType_eq' +Equiv.Perm.exists_fixed_point_of_prime' +Equiv.Perm.isCycle_of_prime_order' +Equiv.Perm.isCycle_of_prime_order'' +Equiv.Perm.IsCycleOn.exists_pow_eq' +Equiv.Perm.IsCycle.pow_eq_one_iff' +Equiv.Perm.IsCycle.pow_eq_one_iff'' +Equiv.Perm.mem_support_cycleOf_iff' +Equiv.Perm.prod_comp' +Equiv.Perm.SameCycle.exists_pow_eq' +Equiv.Perm.SameCycle.exists_pow_eq'' +Equiv.Perm.signAux_swap_zero_one' +Equiv.Perm.sign_of_cycleType' +Equiv.Perm.sign_swap' +Equiv.right_inv' +EReal.add_lt_add_of_lt_of_le' +EReal.coe_neg' +EReal.nhds_bot' +EReal.nhds_top' +EReal.sign_mul_inv_abs' +essInf_const' +essSup_const' +essSup_mono_measure' +estimator' +EuclideanDomain.div_add_mod' +EuclideanDomain.mod_add_div' +EuclideanDomain.mul_div_cancel' +EuclideanGeometry.center_eq_inversion' +EuclideanGeometry.dist_center_eq_dist_center_of_mem_sphere' +EuclideanGeometry.inversion_dist_center' +EuclideanGeometry.inversion_eq_center' +EuclideanGeometry.mem_sphere' +EuclideanGeometry.Sphere.mem_coe' +eventually_cobounded_le_norm' +exists_apply_eq_apply' +exists_apply_eq_apply2' +exists_apply_eq_apply3' +exists_associated_pow_of_mul_eq_pow' +exists_Ico_subset_of_mem_nhds' +exists_increasing_or_nonincreasing_subseq' +exists_Ioc_subset_of_mem_nhds' +exists_lt_of_lt_ciSup' +exists_lt_of_lt_csSup' +exists_maximal_independent' +exists_one_lt' +exists_one_lt_mul_of_lt' +exists_reduced_fraction' +exists_seq_strictAnti_tendsto' +exists_seq_strictMono_tendsto' +exists_square_le' +exists_sum_eq_one_iff_pairwise_coprime' +exists_unique_eq' +existsUnique_zpow_near_of_one_lt' +extChartAt_preimage_mem_nhds' +extChartAt_source_mem_nhds' +extChartAt_source_mem_nhdsWithin' +extChartAt_target_mem_nhdsWithin' +ext_nat' +fderiv_continuousLinearEquiv_comp' +fderiv_id' +fderiv_list_prod' +fderiv_mul' +fderiv_mul_const' +fderivWithin_congr' +fderivWithin_congr_set' +fderivWithin_eventually_congr_set' +fderivWithin_id' +fderivWithin_list_prod' +fderivWithin_mul' +fderivWithin_mul_const' +FDRep.char_tensor' +FermatLastTheoremWith.fermatLastTheoremWith' +FiberBundleCore.open_source' +Field.finInsepDegree_def' +Field.primitive_element_iff_algHom_eq_of_eval' +Filter.atBot_basis' +Filter.atBot_basis_Iio' +Filter.atTop_basis' +Filter.atTop_basis_Ioi' +Filter.bliminf_congr' +Filter.blimsup_congr' +Filter.comap_eq_lift' +Filter.comap_eval_neBot_iff' +Filter.comap_id' +Filter.const_eventuallyEq' +Filter.coprodᵢ_bot' +Filter.coprodᵢ_eq_bot_iff' +Filter.coprodᵢ_neBot_iff' +Filter.countable_biInf_eq_iInf_seq' +Filter.disjoint_comap_iff_map' +Filter.eventually_atBot_prod_self' +Filter.eventually_atTop_prod_self' +Filter.eventuallyConst_pred' +Filter.eventuallyConst_set' +Filter.EventuallyEq.fderivWithin' +Filter.EventuallyEq.iteratedFDerivWithin' +Filter.EventuallyLE.mul_le_mul' +Filter.eventually_smallSets' +Filter.exists_forall_mem_of_hasBasis_mem_blimsup' +Filter.ext' +Filter.extraction_forall_of_eventually' +Filter.extraction_of_frequently_atTop' +Filter.frequently_atBot' +Filter.frequently_atTop' +Filter.Germ.coe_compTendsto' +Filter.Germ.coe_smul' +Filter.Germ.const_compTendsto' +Filter.Germ.instDistribMulAction' +Filter.Germ.instModule' +Filter.Germ.instMulAction' +Filter.Germ.instSMul' +Filter.hasBasis_biInf_of_directed' +Filter.hasBasis_biInf_principal' +Filter.HasBasis.cauchySeq_iff' +Filter.hasBasis_cobounded_norm' +Filter.HasBasis.cobounded_of_norm' +Filter.HasBasis.eventuallyConst_iff' +Filter.hasBasis_iInf' +Filter.hasBasis_iInf_of_directed' +Filter.HasBasis.inf' +Filter.HasBasis.lift' +Filter.HasBasis.nhds' +Filter.HasBasis.prod_nhds' +Filter.HasBasis.sup' +Filter.HasBasis.to_hasBasis' +Filter.HasBasis.to_image_id' +Filter.HasBasis.isUniformEmbedding_iff' +Filter.iInf_neBot_iff_of_directed' +Filter.iInf_sets_eq_finite' +Filter.isScalarTower' +Filter.isScalarTower'' +Filter.le_lift' +Filter.le_limsup_of_frequently_le' +Filter.le_pure_iff' +Filter.lift_lift'_same_eq_lift' +Filter.lift_lift'_same_le_lift' +Filter.lift'_mono' +Filter.lift_mono' +Filter.liminf_eq_iSup_iInf_of_nat' +Filter.liminf_le_of_frequently_le' +Filter.limsup_eq_iInf_iSup_of_nat' +Filter.map_id' +Filter.map_inf' +Filter.map_inv' +Filter.map_one' +Filter.map_prod_eq_map₂' +Filter.mem_bind' +Filter.mem_coclosed_compact' +Filter.mem_cocompact' +Filter.mem_comap' +Filter.mem_comap'' +Filter.mem_iInf' +Filter.mem_iInf_finite' +Filter.mem_inf_principal' +Filter.mem_lift' +Filter.mem_map' +Filter.mem_nhds_iff' +Filter.mem_pi' +Filter.mem_rcomap' +Filter.mono_bliminf' +Filter.mono_blimsup' +Filter.monotone_lift' +Filter.neBot_inf_comap_iff_map' +Filter.nhds_eq' +Filter.principal_le_lift' +Filter.prod_comm' +Filter.prod_lift'_lift' +Filter.prod_map_map_eq' +Filter.ptendsto_of_ptendsto' +Filter.push_pull' +Filter.rcomap'_rcomap' +Filter.sInf_neBot_of_directed' +Filter.smulCommClass_filter' +Filter.smulCommClass_filter'' +Filter.tendsto_atBot' +Filter.tendsto_atBot_add_left_of_ge' +Filter.tendsto_atBot_add_nonpos_left' +Filter.tendsto_atBot_add_nonpos_right' +Filter.tendsto_atBot_add_right_of_ge' +Filter.tendsto_atBot_mono' +Filter.tendsto_atBot_of_add_bdd_below_left' +Filter.tendsto_atBot_of_add_bdd_below_right' +Filter.tendsto_atTop' +Filter.tendsto_atTop_add_left_of_le' +Filter.tendsto_atTop_add_nonneg_left' +Filter.tendsto_atTop_add_nonneg_right' +Filter.tendsto_atTop_add_right_of_le' +Filter.tendsto_atTop_mono' +Filter.tendsto_atTop_of_add_bdd_above_left' +Filter.tendsto_atTop_of_add_bdd_above_right' +Filter.tendsto_congr' +Filter.Tendsto.congr' +Filter.Tendsto.const_div' +Filter.Tendsto.div' +Filter.Tendsto.div_const' +Filter.Tendsto.eventually_ne_atTop' +Filter.tendsto_id' +Filter.Tendsto.if' +Filter.tendsto_iff_rtendsto' +Filter.tendsto_iInf' +Filter.Tendsto.inf_nhds' +Filter.tendsto_inv₀_cobounded' +Filter.tendsto_lift' +Filter.Tendsto.nnnorm' +Filter.Tendsto.norm' +Filter.tendsto_prod_iff' +Filter.Tendsto.sup_nhds' +Filter.unbounded_of_tendsto_atBot' +Filter.unbounded_of_tendsto_atTop' +Filter.univ_mem' +Fin.card_filter_univ_succ' +Fin.castPred_zero' +Fin.cycleRange_zero' +Fin.exists_fin_succ' +Fin.find_min' +Fin.forall_fin_succ' +Fin.insertNth_last' +Fin.insertNth_zero' +Fin.isEmpty' +FiniteDimensional.finiteDimensional_pi' +FiniteField.card' +Finite.Set.finite_biUnion' +Fin.last_pos' +Finmap.ext_iff' +Fin.mem_piFinset_succ' +Fin.mul_one' +Fin.mul_zero' +Fin.one_mul' +Fin.one_pos' +Fin.orderIso_subsingleton' +Fin.partialProd_succ' +Finpartition.IsEquipartition.card_biUnion_offDiag_le' +Finpartition.IsEquipartition.sum_nonUniforms_lt' +Fin.pred_one' +Fin.preimage_apply_01_prod' +Fin.prod_congr' +finprod_emb_domain' +finprod_mem_inter_mul_diff' +finprod_mem_inter_mulSupport_eq' +Fin.prod_univ_get' +Fin.prod_univ_two' +finrank_real_complex_fact' +finRotate_last' +Finset.abs_sum_of_nonneg' +Finset.aemeasurable_prod' +Finset.aestronglyMeasurable_prod' +Finset.card_le_card_of_forall_subsingleton' +Finset.card_mul_le_card_mul' +Finset.coe_inf' +Finset.coe_max' +Finset.coe_min' +Finset.coe_sup' +Finset.Colex.toColex_sdiff_le_toColex_sdiff' +Finset.Colex.toColex_sdiff_lt_toColex_sdiff' +Finset.decidableMem' +Finset.disjoint_filter_filter' +Finset.eq_of_mem_uIcc_of_mem_uIcc' +Finset.eq_prod_range_div' +Finset.erase_injOn' +Finset.exists_le_of_prod_le' +Finset.exists_lt_of_prod_lt' +Finset.exists_mem_eq_inf' +Finset.exists_mem_eq_sup' +Finset.exists_one_lt_of_prod_one_of_exists_ne_one' +Finset.expect_boole_mul' +Finset.expect_dite_eq' +Finset.expect_ite_eq' +Finset.extract_gcd' +Finset.filter_attach' +Finset.filter_inj' +Finset.filter_ne' +Finset.forall_mem_not_eq' +Finset.Icc_mul_Icc_subset' +Finset.Icc_mul_Ico_subset' +Finset.Icc_subset_uIcc' +Finset.Ici_mul_Ici_subset' +Finset.Ici_mul_Ioi_subset' +Finset.Ico_mul_Icc_subset' +Finset.Ico_mul_Ioc_subset' +Finset.Ico_union_Ico' +Finset.Iic_mul_Iic_subset' +Finset.Iic_mul_Iio_subset' +Finset.Iio_mul_Iic_subset' +Finset.image₂_singleton_left' +Finset.image_id' +Finset.image_mul_left' +Finset.image_mul_right' +Finset.inf'_sup_inf' +Finset.insert_inj_on' +Finset.insert_sdiff_insert' +Finset.insert_val' +Finset.Ioc_mul_Ico_subset' +Finset.Ioi_mul_Ici_subset' +Finset.isGreatest_max' +Finset.isLeast_min' +Finset.isScalarTower' +Finset.isScalarTower'' +Finset.le_inf' +Finset.le_max' +Finset.le_min' +Finset.le_sum_condensed' +Finset.le_sum_schlomilch' +Finset.le_sup' +Finset.lt_max'_of_mem_erase_max' +Finset.map_filter' +Finset.max'_eq_sup' +Finset.measurable_prod' +Finset.measurable_range_sup' +Finset.measurable_range_sup'' +Finset.measurable_sup' +Finset.mem_finsuppAntidiag' +Finset.mem_inv' +Finset.mem_map' +Finset.mem_range_iff_mem_finset_range_of_mod_eq' +Finset.mem_uIcc' +Finset.min'_eq_inf' +Finset.min'_lt_max' +Finset.min'_lt_of_mem_erase_min' +Finset.mulEnergy_eq_sum_sq' +Finset.Nat.antidiagonal_eq_image' +Finset.Nat.antidiagonal_eq_map' +Finset.Nat.antidiagonal_succ' +Finset.Nat.antidiagonal_succ_succ' +Finset.Nat.prod_antidiagonal_succ' +Finset.Nat.sum_antidiagonal_succ' +Finset.nnnorm_prod_le' +Finset.noncommProd_cons' +Finset.noncommProd_insert_of_not_mem' +Finset.Nonempty.csInf_eq_min' +Finset.Nonempty.csSup_eq_max' +Finset.norm_prod_le' +Finset.nsmul_inf' +Finset.nsmul_sup' +Finset.ofDual_inf' +Finset.ofDual_max' +Finset.ofDual_min' +Finset.ofDual_sup' +Finset.one_le_prod' +Finset.one_le_prod'' +Finset.one_lt_prod' +Finset.pairwise_cons' +Finset.pairwise_subtype_iff_pairwise_finset' +Finset.piecewise_le_piecewise' +Finset.piecewise_mem_Icc' +Finset.PiFinsetCoe.canLift' +Finset.preimage_mul_left_one' +Finset.preimage_mul_right_one' +Finset.prod_dite_eq' +Finset.prod_eq_one_iff' +Finset.prod_eq_one_iff_of_le_one' +Finset.prod_eq_one_iff_of_one_le' +Finset.prod_fiberwise' +Finset.prod_fiberwise_eq_prod_filter' +Finset.prod_fiberwise_le_prod_of_one_le_prod_fiber' +Finset.prod_fiberwise_of_maps_to' +Finset.prod_finset_product' +Finset.prod_finset_product_right' +Finset.prod_Ico_add' +Finset.prod_image' +Finset.prod_le_one' +Finset.prod_le_prod_fiberwise_of_prod_fiber_le_one' +Finset.prod_le_prod_of_ne_one' +Finset.prod_le_prod_of_subset' +Finset.prod_le_prod_of_subset_of_one_le' +Finset.prod_le_univ_prod_of_one_le' +Finset.prod_lt_one' +Finset.prod_lt_prod' +Finset.prod_lt_prod_of_subset' +Finset.prod_mono_set' +Finset.prod_mono_set_of_one_le' +Finset.prod_pi_mulSingle' +Finset.prod_preimage' +Finset.prod_range_div' +Finset.prod_range_succ' +Finset.prod_sigma' +Finset.range_add_one' +Finset.sdiff_sdiff_left' +Finset.single_le_prod' +Finset.single_lt_prod' +Finset.smulCommClass_finset' +Finset.smulCommClass_finset'' +Finset.smul_prod' +Finset.smul_univ₀' +Finset.sorted_last_eq_max' +Finset.sorted_zero_eq_min' +Finset.stronglyMeasurable_prod' +Finset.subset_singleton_iff' +Finset.sum_apply' +Finset.sum_condensed_le' +Finset.sum_pow' +Finset.sum_schlomilch_le' +Finset.sup'_inf_sup' +Finset.sup_singleton' +Finset.sup_singleton'' +Finset.toDual_inf' +Finset.toDual_max' +Finset.toDual_min' +Finset.toDual_sup' +Finset.tprod_subtype' +Finset.uIcc_subset_uIcc_iff_le' +Finset.untrop_sum' +Fin.size_positive' +Fin.succ_zero_eq_one' +Finsupp.apply_single' +Finsupp.card_support_eq_one' +Finsupp.card_support_le_one' +Finsupp.equivMapDomain_refl' +Finsupp.equivMapDomain_trans' +Finsupp.ext_iff' +Finsupp.le_iff' +Finsupp.le_weight_of_ne_zero' +Finsupp.Lex.wellFounded' +Finsupp.mapDomain_apply' +Finsupp.mapRange_add' +Finsupp.mapRange_neg' +Finsupp.mapRange_sub' +Finsupp.mem_supported' +Finsupp.mulHom_ext' +Finsupp.smul_single' +Finsupp.subtypeDomain_eq_zero_iff' +Finsupp.sum_apply' +Finsupp.sum_cons' +Finsupp.sum_ite_self_eq' +Finsupp.sum_smul_index' +Finsupp.sum_smul_index_linearMap' +Finsupp.sum_sum_index' +Finsupp.support_eq_singleton' +Finsupp.support_subset_singleton' +Finsupp.univ_sum_single_apply' +Finsupp.wellFoundedLT' +Fintype.card_congr' +Fintype.card_of_finset' +Fintype.card_subtype_eq' +Fintype.expect_dite_eq' +Fintype.expect_ite_eq' +Fintype.prod_fiberwise' +Fintype.prod_mono' +Fintype.prod_strictMono' +Fin.univ_image_get' +Fin.univ_image_getElem' +Fin.val_one' +Fin.val_one'' +Fin.zero_mul' +Fin.zero_ne_one' +FirstOrder.Language.addEmptyConstants_is_expansion_on' +FirstOrder.Language.DirectLimit.cg' +FirstOrder.Language.DirectLimit.funMap_quotient_mk'_sigma_mk' +FirstOrder.Language.DirectLimit.lift_quotient_mk'_sigma_mk' +FirstOrder.Language.DirectLimit.relMap_quotient_mk'_sigma_mk' +FirstOrder.Language.Embedding.codRestrict_apply' +FirstOrder.Language.funMap_quotient_mk' +FirstOrder.Language.relMap_quotient_mk' +FirstOrder.Language.Term.realize_quotient_mk' +FixedPoints.minpoly.eval₂' +FixedPoints.smulCommClass' +forall_apply_eq_imp_iff' +forall_eq_apply_imp_iff' +forall_lt_iff_le' +forall_prop_congr' +forall_true_iff' +FormalMultilinearSeries.apply_order_ne_zero' +FormalMultilinearSeries.comp_coeff_zero' +FormalMultilinearSeries.order_eq_find' +FormalMultilinearSeries.order_eq_zero_iff' +fourier_add' +fourier_coe_apply' +fourierIntegral_gaussian_innerProductSpace' +fourierIntegral_gaussian_pi' +fourier_neg' +fourier_zero' +four_ne_zero' +FP.Float.sign' +FractionalIdeal.absNorm_eq' +FractionalIdeal.coeIdeal_eq_zero' +FractionalIdeal.coeIdeal_inj' +FractionalIdeal.coeIdeal_injective' +FractionalIdeal.coeIdeal_le_coeIdeal' +FractionalIdeal.coeIdeal_ne_zero' +FractionalIdeal.inv_zero' +FreeAbelianGroup.induction_on' +FreeAbelianGroup.lift.add' +FreeAbelianGroup.lift_neg' +FreeGroup.map.id' +FreeMagma.lift_comp_of' +FreeMagma.map_mul' +FreeMagma.traverse_mul' +FreeMagma.traverse_pure' +FreeMonoid.countP_of' +FreeSemigroup.lift_comp_of' +FreeSemigroup.map_mul' +FreeSemigroup.traverse_mul' +FreeSemigroup.traverse_pure' +frontier_closedBall' +frontier_Ici' +frontier_Iic' +frontier_Iio' +frontier_Ioi' +frontier_sphere' +Function.Antiperiodic.funext' +Function.Antiperiodic.mul_const' +Function.Antiperiodic.sub_eq' +Function.Bijective.of_comp_iff' +Function.Commute.iterate_pos_le_iff_map_le' +Function.Commute.iterate_pos_lt_iff_map_lt' +Function.Commute.iterate_pos_lt_of_map_lt' +Function.Exact.of_ladder_addEquiv_of_exact' +Function.Exact.split_tfae' +Function.extend_apply' +FunctionField.InftyValuation.map_add_le_max' +FunctionField.InftyValuation.map_mul' +FunctionField.InftyValuation.map_one' +FunctionField.InftyValuation.map_zero' +Function.Injective.eq_iff' +Function.Injective.ne_iff' +Function.Injective.of_comp_iff' +Function.Injective.surjective_comp_right' +Function.iterate_succ' +Function.iterate_succ_apply' +Function.minimalPeriod_iterate_eq_div_gcd' +Function.mulSupport_add_one' +Function.mulSupport_curry' +Function.mulSupport_inv' +Function.mulSupport_one' +Function.mulSupport_one_add' +Function.mulSupport_one_sub' +Function.mulSupport_prod_mk' +Function.mulSupport_subset_iff' +Function.Periodic.mul_const' +Function.periodicOrbit_chain' +Function.Periodic.sub_eq' +Function.support_div' +Function.support_inv' +Function.support_mul' +Function.support_pow' +Function.Surjective.of_comp_iff' +Function.update_comp_eq_of_forall_ne' +Function.update_comp_eq_of_injective' +Function.update_comp_eq_of_not_mem_range' +GaloisCoinsertion.isCoatom_iff' +GaloisConnection.l_csSup' +GaloisConnection.l_u_l_eq_l' +GaloisConnection.u_csInf' +GaloisConnection.u_l_u_eq_u' +GaloisInsertion.isAtom_iff' +gauge_gaugeRescale' +gauge_lt_eq' +gauge_zero' +GaussianFourier.norm_cexp_neg_mul_sq_add_mul_I' +GaussianInt.toComplex_def' +gcd_assoc' +gcd_comm' +gcd_mul_left' +gcd_mul_right' +gcd_neg' +gcd_one_left' +gcd_one_right' +gcd_zero_left' +gcd_zero_right' +GenContFract.of_convs_eq_convs' +ge_of_tendsto' +geom_sum_Ico' +geom_sum_pos' +geom_sum_succ' +GradedTensorProduct.algebraMap_def' +gradient_const' +gradient_eq_deriv' +gramSchmidt_def' +gramSchmidt_def'' +gramSchmidtNormed_unit_length' +gramSchmidtOrthonormalBasis_inv_triangular' +Group.conjugatesOfSet_subset' +Group.fg_iff' +GroupTopology.ext' +Grp.coe_comp' +Grp.coe_id' +Grp.SurjectiveOfEpiAuxs.h_apply_fromCoset' +Grp.SurjectiveOfEpiAuxs.τ_apply_fromCoset' +HahnModule.mul_smul' +HahnModule.one_smul' +HahnModule.support_smul_subset_vadd_support' +HahnModule.zero_smul' +HahnSeries.add_coeff' +HahnSeries.algebraMap_apply' +HahnSeries.mul_assoc' +HahnSeries.mul_coeff_left' +HahnSeries.mul_coeff_right' +HahnSeries.neg_coeff' +HahnSeries.sub_coeff' +HasCompactMulSupport.intro' +HasCompactMulSupport.inv' +HasCompactMulSupport.mono' +HasDerivAt.complexToReal_fderiv' +hasDerivAt_exp_smul_const' +hasDerivAt_exp_smul_const_of_mem_ball' +HasDerivAtFilter.hasGradientAtFilter' +HasDerivAt.hasGradientAt' +hasDerivAt_id' +hasDerivAt_neg' +HasDerivWithinAt.complexToReal_fderiv' +hasDerivWithinAt_congr_set' +hasDerivWithinAt_iff_tendsto_slope' +hasDerivWithinAt_inter' +HasDerivWithinAt.limsup_slope_le' +hasFDerivAt_exp_smul_const' +hasFDerivAt_exp_smul_const_of_mem_ball' +hasFDerivAtFilter_pi' +hasFDerivAt_list_prod' +hasFDerivAt_list_prod_attach' +hasFDerivAt_list_prod_finRange' +HasFDerivAt.mul' +HasFDerivAt.mul_const' +hasFDerivAt_pi' +hasFDerivAt_pi'' +HasFDerivWithinAt.congr' +hasFDerivWithinAt_congr_set' +hasFDerivWithinAt_inter' +HasFDerivWithinAt.list_prod' +HasFDerivWithinAt.mul' +HasFDerivWithinAt.mul_const' +hasFDerivWithinAt_pi' +hasFDerivWithinAt_pi'' +HasFiniteFPowerSeriesOnBall.mk' +hasFPowerSeriesAt_iff' +HasFPowerSeriesOnBall.factorial_smul' +hasFTaylorSeriesUpToOn_pi' +HasFTaylorSeriesUpToOn.zero_eq' +HasFTaylorSeriesUpTo.zero_eq' +HasGradientAtFilter.hasDerivAtFilter' +HasGradientAt.hasDerivAt' +hasGradientWithinAt_congr_set' +HasLineDerivWithinAt.congr' +HasLineDerivWithinAt.hasLineDerivAt' +HasMFDerivAt.mul' +hasMFDerivWithinAt_inter' +HasMFDerivWithinAt.mul' +HasOrthogonalProjection.map_linearIsometryEquiv' +hasProd_nat_add_iff' +HasStrictDerivAt.complexToReal_fderiv' +hasStrictDerivAt_exp_smul_const' +hasStrictDerivAt_exp_smul_const_of_mem_ball' +hasStrictFDerivAt_exp_smul_const' +hasStrictFDerivAt_exp_smul_const_of_mem_ball' +hasStrictFDerivAt_list_prod' +HasStrictFDerivAt.list_prod' +hasStrictFDerivAt_list_prod_attach' +hasStrictFDerivAt_list_prod_finRange' +HasStrictFDerivAt.mul' +HasStrictFDerivAt.mul_const' +hasStrictFDerivAt_pi' +hasStrictFDerivAt_pi'' +hasSum_choose_mul_geometric_of_norm_lt_one' +hasSum_geometric_two' +HasSum.matrix_blockDiag' +HasSum.matrix_blockDiagonal' +hasSum_sum_range_mul_of_summable_norm' +Homeomorph.comp_continuousAt_iff' +Homeomorph.comp_continuous_iff' +Homeomorph.comp_isOpenMap_iff' +HomogeneousIdeal.ext' +HomologicalComplex₂.d₁_eq' +HomologicalComplex₂.d₁_eq_zero' +HomologicalComplex₂.d₂_eq' +HomologicalComplex₂.d₂_eq_zero' +HomologicalComplex₂.totalAux.d₁_eq' +HomologicalComplex₂.totalAux.d₂_eq' +HomologicalComplex.exactAt_iff' +HomologicalComplex.extend.d_none_eq_zero' +HomologicalComplex.homotopyCofiber.desc_f' +HomologicalComplex.homotopyCofiber.ext_from_X' +HomologicalComplex.homotopyCofiber.ext_to_X' +HomologicalComplex.homotopyCofiber.inlX_d' +HomologicalComplex.isZero_extend_X' +HomologicalComplex.mapBifunctor.d₁_eq' +HomologicalComplex.mapBifunctor.d₁_eq_zero' +HomologicalComplex.mapBifunctor.d₂_eq' +HomologicalComplex.mapBifunctor.d₂_eq_zero' +HomologicalComplex.restrictionMap_f' +HomotopyCategory.Pretriangulated.invRotate_distinguished_triangle' +HomotopyCategory.Pretriangulated.rotate_distinguished_triangle' +HurwitzZeta.jacobiTheta₂'_functional_equation' +HurwitzZeta.oddKernel_def' +Hyperreal.isSt_st' +Icc_mem_nhdsWithin_Ici' +Icc_mem_nhdsWithin_Iic' +Icc_mem_nhdsWithin_Iio' +Icc_mem_nhdsWithin_Ioi' +Ico_mem_nhdsWithin_Ici' +Ico_mem_nhdsWithin_Iio' +Ico_mem_nhdsWithin_Ioi' +Ideal.comap_map_of_surjective' +Ideal.comap_sInf' +Ideal.eq_jacobson_iff_sInf_maximal' +Ideal.isJacobson_iff_sInf_maximal' +Ideal.isJacobson_of_isIntegral' +Ideal.isMaximal_comap_of_isIntegral_of_isMaximal' +Ideal.IsMaximal.isPrime' +Ideal.isMaximal_of_isIntegral_of_isMaximal_comap' +Ideal.isPrime_ideal_prod_top' +Ideal.IsPrime.inf_le' +Ideal.isPrime_of_isPrime_prod_top' +Ideal.mem_span_insert' +Ideal.mem_span_singleton' +Ideal.MvPolynomial.quotient_mk_comp_C_isIntegral_of_jacobson' +Ideal.Polynomial.isMaximal_comap_C_of_isJacobson' +Ideal.quotientInfToPiQuotient_mk' +Ideal.Quotient.smulCommClass' +Ideal.span_mul_span' +Ideal.subset_union_prime' +IfExpr.eval_ite_ite' +iInf₂_mono' +iInf_le' +iInf_mono' +iInf_prod' +iInf_psigma' +iInf_range' +iInf_sigma' +iInf_subtype' +iInf_subtype'' +imageSubobjectIso_imageToKernel' +Imo1962Q1.ProblemPredicate' +imo1962_q4' +Imo1969Q1.not_prime_of_int_mul' +Imo2001Q2.imo2001_q2' +imp_or' +induced_orderTopology' +Inducing.continuousAt_iff' +Inducing.isClosed_iff' +inf_compl_eq_bot' +inf_eq_half_smul_add_sub_abs_sub' +inner_map_polarization' +InnerProductSpaceable.add_left_aux2' +InnerProductSpaceable.add_left_aux4' +Inseparable.specializes' +Int.add_le_zero_iff_le_neg' +Int.add_nonnneg_iff_neg_le' +Int.ceil_eq_on_Ioc' +Int.coprime_of_sq_sum' +Int.dist_eq' +integrable_cexp_quadratic' +integrableOn_Icc_iff_integrableOn_Ico' +integrableOn_Icc_iff_integrableOn_Ioc' +integrableOn_Icc_iff_integrableOn_Ioo' +integrableOn_Ici_iff_integrableOn_Ioi' +integrableOn_Ico_iff_integrableOn_Ioo' +integrableOn_Iic_iff_integrableOn_Iio' +integrableOn_Ioc_iff_integrableOn_Ioo' +Int.eq_one_or_neg_one_of_mul_eq_neg_one' +Int.eq_one_or_neg_one_of_mul_eq_one' +interior_closedBall' +interior_eq_nhds' +interior_Ici' +interior_Iic' +interior_sphere' +IntermediateField.algebra' +IntermediateField.charP' +IntermediateField.eq_of_le_of_finrank_le'' +IntermediateField.exists_algHom_adjoin_of_splits'' +IntermediateField.exists_algHom_of_splits' +IntermediateField.exists_finset_of_mem_supr' +IntermediateField.exists_finset_of_mem_supr'' +IntermediateField.expChar' +IntermediateField.finInsepDegree_bot' +IntermediateField.finiteDimensional_iSup_of_finset' +IntermediateField.finrank_bot' +IntermediateField.finrank_top' +IntermediateField.finSepDegree_bot' +IntermediateField.insepDegree_bot' +IntermediateField.lift_insepDegree_bot' +IntermediateField.lift_sepDegree_bot' +IntermediateField.module' +IntermediateField.normalClosure_def' +IntermediateField.normalClosure_def'' +IntermediateField.normal_iff_forall_map_eq' +IntermediateField.normal_iff_forall_map_le' +IntermediateField.rank_bot' +IntermediateField.rank_top' +IntermediateField.sepDegree_bot' +intermediate_value_Ico' +intermediate_value_Ioc' +intermediate_value_Ioo' +IntervalIntegrable.aestronglyMeasurable' +intervalIntegrable_iff' +IntervalIntegrable.mono_fun' +IntervalIntegrable.mono_set' +intervalIntegral.continuous_parametric_intervalIntegral_of_continuous' +intervalIntegral.integral_congr_ae' +intervalIntegral.integral_const' +intervalIntegral.integral_deriv_comp_mul_deriv' +intervalIntegral.integral_deriv_comp_smul_deriv' +intervalIntegral.integral_deriv_eq_sub' +intervalIntegral.integral_interval_sub_interval_comm' +Int.even_add' +Int.even_or_odd' +Int.even_pow' +Int.even_sub' +Int.even_xor'_odd' +Int.exists_gcd_one' +Int.floor_eq_on_Ico' +Int.Matrix.exists_ne_zero_int_vec_norm_le' +Int.ModEq.add_left_cancel' +Int.ModEq.add_right_cancel' +Int.ModEq.mul_left' +Int.ModEq.mul_right' +Int.natAbs_ofNat' +Int.odd_add' +Int.odd_pow' +Int.odd_sub' +Int.Prime.dvd_mul' +Int.Prime.dvd_pow' +Int.toNat_lt' +Int.two_pow_sub_pow' +inv_div' +inv_le' +inv_le_div_iff_le_mul' +inv_le_iff_one_le_mul' +inv_le_inv' +inv_lt' +inv_lt_div_iff_lt_mul' +inv_lt_iff_one_lt_mul' +inv_lt_inv' +inv_mul' +inv_mul_le_iff' +inv_mul_le_iff_le_mul' +inv_mul_lt_iff' +inv_mul_lt_iff_lt_mul' +inv_neg' +inv_neg'' +invOf_mul_cancel_left' +invOf_mul_cancel_right' +invOf_mul_self' +invOf_one' +inv_pos_le_iff_one_le_mul' +inv_pos_lt_iff_one_lt_mul' +inv_zpow' +Ioc_mem_nhdsWithin_Iic' +Ioc_mem_nhdsWithin_Iio' +Ioc_mem_nhdsWithin_Ioi' +Ioo_mem_nhdsWithin_Iio' +Ioo_mem_nhdsWithin_Ioi' +IsAbsoluteValue.abv_one' +isAddFundamentalDomain_Ioc' +isAdjointPair_toBilin' +isAdjointPair_toLinearMap₂' +IsAlgClosed.algebraMap_surjective_of_isIntegral' +IsAntichain.eq' +IsAntichain.interior_eq_empty' +isArtinian_of_fg_of_artinian' +isArtinian_submodule' +IsBaseChange.algHom_ext' +IsBoundedBilinearMap.isBigO' +isBounded_iff_forall_norm_le' +isBoundedUnder_ge_finset_inf' +isBoundedUnder_le_finset_sup' +IsCauSeq.bounded' +isClosed_induced_iff' +isCoboundedUnder_ge_finset_inf' +isCoboundedUnder_le_finset_sup' +IsCompact.elim_nhds_subcover' +IsCompact.elim_nhds_subcover_nhdsSet' +IsCompact.exists_bound_of_continuousOn' +isCompact_iff_ultrafilter_le_nhds' +IsCompact.tendsto_subseq' +isComplete_iff_ultrafilter' +IsCoprime.isUnit_of_dvd' +IsCyclotomicExtension.neZero' +IsCyclotomicExtension.Rat.discr_odd_prime' +IsDedekindDomain.HeightOneSpectrum.adicCompletion.algebra' +IsDedekindDomain.HeightOneSpectrum.adicCompletion.instIsScalarTower' +IsDedekindDomain.HeightOneSpectrum.adicValued.has_uniform_continuous_const_smul' +IsDedekindDomain.HeightOneSpectrum.algebraMap_adicCompletion' +isField_of_isIntegral_of_isField' +IsFractionRing.mk'_num_den' +IsFractionRing.num_mul_den_eq_num_iff_eq' +IsGLB.exists_between' +IsGLB.exists_between_self_add' +isGLB_inv' +IsGroupHom.inv_iff_ker' +IsGroupHom.inv_ker_one' +IsGroupHom.map_mul' +IsGroupHom.one_iff_ker_inv' +IsGroupHom.one_ker_inv' +IsIntegralClosure.algebraMap_mk' +isIntegral_localization' +IsIntegral.minpoly_splits_tower_top' +IsIntegral.of_mem_closure'' +IsInvariantSubring.coe_subtypeHom' +IsKleinFour.card_four' +IsLindelof.elim_nhds_subcover' +IsLinearMap.isLinearMap_smul' +IsLocalization.algebraMap_mk' +IsLocalization.algEquiv_mk' +IsLocalization.algEquiv_symm_mk' +IsLocalization.map_id_mk' +IsLocalization.map_mk' +IsLocalization.mem_invSubmonoid_iff_exists_mk' +IsLocalization.mk'_eq_iff_eq' +IsLocalization.mk'_eq_of_eq' +IsLocalization.mk'_mul_mk'_eq_one' +IsLocalization.mk'_self' +IsLocalization.mk'_self'' +IsLocalization.mk'_spec' +IsLocalization.ringEquivOfRingEquiv_mk' +IsLocalization.smul_mk' +IsLocalization.surj'' +IsLocalization.toInvSubmonoid_eq_mk' +isLocalizedModule_iff_isLocalization' +IsLocalizedModule.iso_symm_apply' +IsLocalizedModule.map_mk' +IsLocalizedModule.mk'_add_mk' +IsLocalizedModule.mk'_cancel' +IsLocalizedModule.mk_eq_mk' +IsLocalizedModule.mk'_eq_zero' +IsLocalizedModule.mk'_mul_mk' +IsLocalizedModule.mk'_sub_mk' +IsLowerSet.cthickening' +IsLowerSet.thickening' +isLUB_csSup' +IsLUB.exists_between' +IsLUB.exists_between_sub_self' +isLUB_hasProd' +isLUB_inv' +IsMax.not_isMin' +IsMin.not_isMax' +isNoetherian_iff' +isNoetherian_submodule' +IsometryEquiv.comp_continuous_iff' +isOpen_extChartAt_preimage' +isOpen_gt' +isOpen_iff_ultrafilter' +IsOpen.ite' +isOpen_lt' +isOpen_pi_iff' +IsPathConnected.exists_path_through_family' +IsPGroup.to_sup_of_normal_left' +IsPGroup.to_sup_of_normal_right' +IsPreconnected.union' +IsPrimitiveRoot.card_rootsOfUnity' +IsPrimitiveRoot.finite_quotient_span_sub_one' +IsPrimitiveRoot.isPrimitiveRoot_iff' +IsPrimitiveRoot.isUnit_unit' +IsPrimitiveRoot.neZero' +IsPrimitiveRoot.zmodEquivZPowers_symm_apply_pow' +IsPrimitiveRoot.zmodEquivZPowers_symm_apply_zpow' +isQuasiregular_iff_isUnit' +isRegular_iff_ne_zero' +isRegular_of_ne_zero' +IsScalarTower.coe_toAlgHom' +IsScalarTower.subalgebra' +IsScalarTower.to_smulCommClass' +IsSelfAdjoint.conjugate' +isSemisimpleModule_of_isSemisimpleModule_submodule' +IsUnifLocDoublingMeasure.eventually_measure_le_scaling_constant_mul' +IsUnifLocDoublingMeasure.exists_measure_closedBall_le_mul' +isUnit_iff_exists_inv' +IsUnit.map' +IsUnit.val_inv_unit' +iSup₂_mono' +iSup_mono' +iSup_of_empty' +IsUpperSet.cthickening' +IsUpperSet.thickening' +iSup_prod' +iSup_psigma' +iSup_range' +iSup_sigma' +iSup_subtype' +iSup_subtype'' +ite_eq_iff' +iteratedFDeriv_add_apply' +iteratedFDeriv_const_smul_apply' +iteratedFDerivWithin_eventually_congr_set' +iter_deriv_inv' +iter_deriv_pow' +iter_deriv_zpow' +jacobiTheta₂'_add_left' +KaehlerDifferential.isScalarTower' +KaehlerDifferential.module' +LatticeHom.coe_comp_inf_hom' +LatticeHom.coe_comp_sup_hom' +LawfulFix.fix_eq' +lcm_assoc' +lcm_comm' +le_abs' +le_add_tsub' +Lean.Elab.Tactic.TacticM.runCore' +le_ciInf_iff' +le_ciSup_iff' +le_csInf_iff' +le_csInf_iff'' +le_csSup_iff' +le_div_iff₀' +le_div_iff_mul_le' +le_div_iff_of_neg' +LeftOrdContinuous.map_sSup' +Left.pow_lt_one_iff' +legendreSym.eq_neg_one_iff' +legendreSym.eq_one_iff' +le_hasProd' +le_iff_exists_mul' +le_iff_forall_one_lt_lt_mul' +le_inv' +le_iSup' +le_map_add_map_div' +le_mul_iff_one_le_left' +le_mul_iff_one_le_right' +le_mul_of_le_of_one_le' +le_mul_of_one_le_left' +le_mul_of_one_le_right' +le_nhdsAdjoint_iff' +le_of_eq_of_le' +le_of_forall_le' +le_of_forall_lt' +le_of_forall_one_lt_lt_mul' +le_of_le_of_eq' +le_of_mul_le_mul_left' +le_of_mul_le_mul_right' +le_of_pow_le_pow_left' +le_of_tendsto' +le_of_tendsto_of_tendsto' +le_tprod' +le_trans' +Lex.instDistribMulAction' +Lex.instDistribSMul' +Lex.instIsScalarTower' +Lex.instIsScalarTower'' +Lex.instModule' +Lex.instMulAction' +Lex.instMulActionWithZero' +Lex.instPow' +Lex.instSMulCommClass' +Lex.instSMulCommClass'' +Lex.instSMulWithZero' +LieAlgebra.IsKilling.apply_coroot_eq_cast' +LieAlgebra.IsKilling.coe_corootSpace_eq_span_singleton' +LieAlgebra.lieCharacter_apply_lie' +LieAlgebra.mem_corootSpace' +LieIdeal.map_sup_ker_eq_map' +LieModule.chainTop_isNonZero' +LieModule.coe_chainTop' +LieModule.genWeightSpaceChain_def' +LieModule.independent_genWeightSpace' +LieModule.instIsTrivialOfSubsingleton' +LieModule.isNilpotent_of_top_iff' +LieModule.iSup_genWeightSpace_eq_top' +LieModule.Weight.ext_iff' +LieSubalgebra.coe_incl' +LieSubalgebra.ext_iff' +LieSubalgebra.mem_normalizer_iff' +LieSubmodule.iSup_induction' +LieSubmodule.lieIdeal_oper_eq_linear_span' +LieSubmodule.mem_mk_iff' +LieSubmodule.module' +LieSubmodule.Quotient.mk_eq_zero' +LieSubmodule.Quotient.module' +LieSubmodule.Quotient.range_mk' +LieSubmodule.Quotient.surjective_mk' +LieSubmodule.Quotient.toEnd_comp_mk' +LieSubmodule.sInf_coe_toSubmodule' +LieSubmodule.sSup_coe_toSubmodule' +liftOfDerivationToSquareZero_mk_apply' +lift_rank_lt_rank_dual' +LightProfinite.proj_comp_transitionMap' +LightProfinite.proj_comp_transitionMapLE' +liminf_finset_inf' +limsup_finset_sup' +linearDependent_comp_subtype' +LinearEquiv.apply_smulCommClass' +LinearEquiv.coe_toContinuousLinearEquiv' +LinearEquiv.coe_toContinuousLinearEquiv_symm' +LinearEquiv.isRegular_congr' +LinearEquiv.isSMulRegular_congr' +LinearEquiv.isWeaklyRegular_congr' +LinearEquiv.mk_coe' +linearIndependent_algHom_toLinearMap' +LinearIndependent.cardinal_le_rank' +linearIndependent_equiv' +LinearIndependent.eq_zero_of_pair' +linearIndependent_fin_succ' +linearIndependent_iff' +linearIndependent_iff'' +linearIndependent_inl_union_inr' +linearIndependent_insert' +linearIndependent_le_span_aux' +linearIndependent_option' +LinearIndependent.span_eq_top_of_card_eq_finrank' +LinearIndependent.to_subtype_range' +LinearIsometry.completeSpace_map' +LinearIsometryEquiv.coe_coe'' +LinearIsometryEquiv.comp_fderiv' +LinearIsometryEquiv.comp_hasFDerivAt_iff' +LinearIsometryEquiv.comp_hasFDerivWithinAt_iff' +LinearIsometry.isComplete_image_iff' +LinearIsometry.isComplete_map_iff' +LinearIsometry.map_orthogonalProjection' +LinearMap.apply_smulCommClass' +LinearMap.BilinForm.mul_toMatrix' +LinearMap.BilinForm.nondegenerate_toBilin'_of_det_ne_zero' +LinearMap.BilinForm.Nondegenerate.toMatrix' +LinearMap.BilinForm.toMatrix'_toBilin' +LinearMap.coe_toContinuousLinearMap' +LinearMap.detAux_def'' +LinearMap.det_toLin' +LinearMap.det_toMatrix' +LinearMap.det_zero' +LinearMap.det_zero'' +LinearMap.disjoint_ker' +LinearMap.dualMap_apply' +LinearMap.extendScalarsOfIsLocalization_apply' +LinearMap.IsProj.eq_conj_prod_map' +LinearMap.IsScalarTower.compatibleSMul' +LinearMap.IsSymmetric.orthogonalComplement_iSup_eigenspaces_eq_bot' +LinearMap.IsSymmetric.orthogonalFamily_eigenspaces' +LinearMap.ker_eq_bot' +LinearMap.ker_smul' +LinearMap.lcomp_apply' +LinearMap.llcomp_apply' +LinearMap.map_le_map_iff' +LinearMap.minpoly_toMatrix' +LinearMap.mkContinuous₂_norm_le' +LinearMap.mul_apply' +LinearMap.mul_toMatrix' +LinearMap.ofIsCompl_eq' +LinearMap.range_smul' +LinearMap.separatingLeft_toLinearMap₂'_of_det_ne_zero' +LinearMap.SeparatingLeft.toMatrix₂' +LinearMap.stdBasis_apply' +LinearMap.toMatrixAlgEquiv_apply' +LinearMap.toMatrixAlgEquiv'_toLinAlgEquiv' +LinearMap.toMatrixAlgEquiv_transpose_apply' +LinearMap.toMatrix_apply' +LinearMap.toMatrix'_toLin' +LinearMap.toMatrix'_toLinearMap₂' +LinearMap.toMatrix'_toLinearMapₛₗ₂' +LinearMap.toMatrix_transpose_apply' +LinearMap.trace_comp_comm' +LinearMap.trace_conj' +LinearMap.trace_eq_sum_trace_restrict' +LinearMap.trace_mul_cycle' +LinearMap.trace_prodMap' +LinearMap.trace_tensorProduct' +LinearMap.trace_transpose' +LinearOrderedCommGroup.mul_lt_mul_left' +LinearPMap.closure_def' +LinearPMap.ext' +LinearPMap.mem_graph_iff' +LinearPMap.mem_graph_snd_inj' +LinearPMap.toFun' +lineDerivWithin_congr' +LipschitzOnWith.of_dist_le' +LipschitzWith.const' +LipschitzWith.integral_inv_smul_sub_mul_tendsto_integral_lineDeriv_mul' +LipschitzWith.nnorm_le_mul' +LipschitzWith.norm_le_mul' +LipschitzWith.of_dist_le' +lipschitzWith_one_nnnorm' +lipschitzWith_one_norm' +List.aemeasurable_prod' +List.aestronglyMeasurable_prod' +List.alternatingProd_cons' +List.alternatingProd_cons_cons' +list_casesOn' +List.chain'_cons' +List.Chain'.cons' +List.chain'_map_of_chain' +list_cons' +List.cons_sublist_cons' +List.count_cons' +List.decidableChain' +List.dedup_cons_of_mem' +List.dedup_cons_of_not_mem' +List.destutter_cons' +List.destutter'_is_chain' +List.destutter_is_chain' +List.destutter_of_chain' +List.drop_take_succ_join_eq_get' +List.exists_le_of_prod_le' +List.exists_lt_of_prod_lt' +List.ext_get?' +List.ext_get?_iff' +List.filter_attach' +List.filter_subset' +list_foldl' +List.foldl_eq_foldr' +List.foldl_eq_of_comm' +List.foldl_fixed' +List.foldr_eq_of_comm' +List.foldr_fixed' +List.Forall₂.prod_le_prod' +List.getLast_append' +List.getLast_concat' +List.getLast_singleton' +List.get_reverse' +List.get?_zipWith' +List.inter_nil' +List.isRotated_nil_iff' +List.isRotated_singleton_iff' +List.LE' +List.left_unique_forall₂' +List.le_maximum_of_mem' +List.length_foldr_permutationsAux2' +List.length_mergeSort' +List.length_rotate' +List.length_sublists' +List.lookmap_id' +List.LT' +List.map₂Left_eq_map₂Left' +List.map₂Right_eq_map₂Right' +List.map_filter' +List.map_mergeSort' +List.map_permutations' +List.map_permutationsAux2' +List.measurable_prod' +List.mem_destutter' +List.mem_mergeSort' +List.mem_permutations' +List.mem_permutationsAux2' +List.mem_sublists' +List.minimum_le_of_mem' +List.Nat.antidiagonal_succ' +List.Nat.antidiagonal_succ_succ' +List.next_cons_cons_eq' +List.nnnorm_prod_le' +List.nodup_sublists' +List.norm_prod_le' +List.not_lt_maximum_of_mem' +List.not_lt_minimum_of_mem' +List.ofFn_succ' +List.Pairwise.chain' +List.pairwise_map' +List.Pairwise.sublists' +List.perm_mergeSort' +List.Perm.permutations' +List.permutations_perm_permutations' +List.prev_cons_cons_eq' +List.prev_cons_cons_of_ne' +List.prev_getLast_cons' +List.prod_le_prod' +List.prod_lt_prod' +List.replicate_right_inj' +List.replicate_succ' +list_reverse' +List.reverse_concat' +List.reverse_cons' +List.revzip_sublists' +List.right_unique_forall₂' +List.rotate_eq_rotate' +List.rotate'_rotate' +Lists' +Lists.lt_sizeof_cons' +Lists'.mem_of_subset' +List.smul_prod' +List.sorted_mergeSort' +List.stronglyMeasurable_prod' +List.SublistForall₂.prod_le_prod' +List.sublists_eq_sublists' +List.sublistsLen_sublist_sublists' +List.sublists_perm_sublists' +List.support_formPerm_le' +List.support_formPerm_of_nodup' +List.takeD_left' +List.takeI_left' +List.tendsto_insertNth' +List.zipLeft_eq_zipLeft' +List.zipRight_eq_zipRight' +List.zipWith_swap_prod_support' +localCohomology.moduleCat_enoughProjectives' +Localization.algEquiv_mk' +Localization.algEquiv_symm_mk' +Localization.Away.mk_eq_monoidOf_mk' +Localization.epi' +Localization.liftOn₂_mk' +Localization.liftOn_mk' +Localization.localRingHom_mk' +Localization.mk_eq_mk' +Localization.mk_eq_mk_iff' +Localization.mk_eq_monoidOf_mk' +Localization.mulEquivOfQuotient_mk' +Localization.mulEquivOfQuotient_symm_mk' +localization_unit_isIso' +LocalizedModule.add_assoc' +LocalizedModule.add_comm' +LocalizedModule.add_zero' +LocalizedModule.algebra' +LocalizedModule.algebraMap_mk' +LocalizedModule.isModule' +LocalizedModule.mul_smul' +LocalizedModule.nsmul_succ' +LocalizedModule.nsmul_zero' +LocalizedModule.zero_add' +LocallyFinite.continuous' +LocallyFinite.continuousOn_iUnion' +LocallyFinite.option_elim' +LocalRing.of_surjective' +logDeriv_id' +lowerClosure_interior_subset' +lp.eq_zero' +lp.norm_le_of_forall_le' +lp.norm_nonneg' +lp.tsum_mul_le_mul_norm' +LSeries.abscissaOfAbsConv_le_of_forall_lt_LSeriesSummable' +lt_div_iff' +lt_div_iff_mul_lt' +lt_div_iff_of_neg' +lt_iff_lt_of_le_iff_le' +lt_inv' +lt_inv_iff_mul_lt_one' +LT.lt.ne' +lt_mul_iff_one_lt_left' +lt_mul_iff_one_lt_right' +lt_mul_of_le_of_one_lt' +lt_mul_of_lt_of_one_le' +lt_mul_of_lt_of_one_lt' +lt_mul_of_one_lt_left' +lt_mul_of_one_lt_of_lt' +lt_mul_of_one_lt_right' +lt_of_eq_of_lt' +lt_of_le_of_lt' +lt_of_le_of_ne' +lt_of_lt_of_eq' +lt_of_lt_of_le' +lt_of_mul_lt_mul_left' +lt_of_mul_lt_mul_right' +lt_of_pow_lt_pow_left' +lt_trans' +mabs_le' +Magma.AssocQuotient.lift_comp_of' +MapClusterPt.tendsto_comp' +map_comp_div' +map_comp_zpow' +map_div' +map_extChartAt_nhds' +map_extChartAt_nhdsWithin' +map_extChartAt_nhdsWithin_eq_image' +map_extChartAt_symm_nhdsWithin' +map_extChartAt_symm_nhdsWithin_range' +map_finset_inf' +map_finset_sup' +map_natCast' +map_ofNat' +map_preNormEDS' +mapsTo_omegaLimit' +map_zpow' +Mathlib.Meta.Finset.range_succ' +Mathlib.Meta.Finset.range_zero' +Mathlib.Meta.FunProp.StateList.toList' +Mathlib.Meta.List.range_succ_eq_map' +Mathlib.Meta.List.range_zero' +Mathlib.Meta.Multiset.range_succ' +Mathlib.Meta.Multiset.range_zero' +Mathlib.Meta.NormNum.jacobiSymNat.qr₁' +Mathlib.Meta.Positivity.lt_of_le_of_ne' +Mathlib.Tactic.ComputeDegree.coeff_pow_of_natDegree_le_of_eq_ite' +Mathlib.Tactic.ComputeDegree.degree_eq_of_le_of_coeff_ne_zero' +Mathlib.Tactic.Group.zpow_trick_one' +Mathlib.Tactic.Ring.atom_pf' +Mathlib.Util.addAndCompile' +Mathlib.Vector.eraseIdx_insertNth' +Mathlib.Vector.prod_set' +Mathlib.WhatsNew.mkHeader' +Matrix.blockDiag'_blockDiagonal' +Matrix.blockDiagonal'_apply' +Matrix.blockDiagonal_apply' +Matrix.blockTriangular_blockDiagonal' +Matrix.blockTriangular_stdBasisMatrix' +Matrix.blockTriangular_transvection' +Matrix.cons_val' +Matrix.cons_val_succ' +Matrix.cons_val_zero' +Matrix.det_apply' +Matrix.det_units_conj' +Matrix.det_updateColumn_smul' +Matrix.det_updateRow_smul' +Matrix.diagonal_apply_ne' +Matrix.diagonal_intCast' +Matrix.diagonal_mul_diagonal' +Matrix.diagonal_natCast' +Matrix.diagonal_ofNat' +Matrix.diagonal_toLin' +Matrix.dotProduct_diagonal' +Matrix.dotProduct_zero' +Matrix.empty_val' +Matrix.exists_mulVec_eq_zero_iff' +Matrix.exp_blockDiagonal' +Matrix.exp_conj' +Matrix.exp_units_conj' +Matrix.head_val' +Matrix.induction_on' +Matrix.inv_pow' +Matrix.inv_smul' +Matrix.inv_zpow' +Matrix.isAdjointPair_equiv' +Matrix.ker_diagonal_toLin' +Matrix.kronecker_assoc' +Matrix.kroneckerTMul_assoc' +Matrix.map_id' +Matrix.mem_orthogonalGroup_iff' +Matrix.mem_unitaryGroup_iff' +Matrix.minpoly_toLin' +Matrix.mul_apply' +Matrix.Nondegenerate.toBilin' +Matrix.Nondegenerate.toLinearMap₂' +Matrix.one_apply_ne' +Matrix.PosDef.of_toQuadraticForm' +Matrix.PosDef.toQuadraticForm' +Matrix.pow_inv_comm' +Matrix.pow_sub' +Matrix.range_toLin' +Matrix.represents_iff' +Matrix.tail_val' +Matrix.toBilin'_apply' +Matrix.toBilin'_toMatrix' +Matrix.toLinAlgEquiv'_toMatrixAlgEquiv' +Matrix.toLin'_apply' +Matrix.toLinearMap₂'_apply' +Matrix.toLinearMap₂'_toMatrix' +Matrix.toLinearMapₛₗ₂'_toMatrix' +Matrix.toLin'_toMatrix' +Matrix.trace_blockDiagonal' +Matrix.trace_mul_cycle' +Matrix.twoBlockTriangular_det' +Matrix.vec2_dotProduct' +Matrix.vec3_dotProduct' +Matrix.zero_dotProduct' +Matrix.zpow_mul' +Matroid.Base.exchange_base_of_indep' +Matroid.base_restrict_iff' +Matroid.Basis.basis' +Matroid.basis_iff' +Matroid.basis_iff_basis_closure_of_subset' +Matroid.basis_restrict_iff' +Matroid.closure_def' +Matroid.coindep_iff_exists' +Matroid.dual_base_iff' +Matroid.dual_indep_iff_exists' +Matroid.exists_basis' +Matroid.Finitary.sum' +Matroid.Indep.mem_closure_iff' +Matroid.map_basis_iff' +Matroid.mapSetEmbedding_indep_iff' +Matroid.mem_closure_of_mem' +Matroid.restrictSubtype_dual' +Matroid.subset_closure_of_subset' +Matroid.uniqueBaseOn_indep_iff' +Matroid.uniqueBaseOn_restrict' +max_def' +max_div_div_left' +max_div_div_right' +max_div_min_eq_mabs' +maximal_subset_iff' +max_inv_inv' +max_mul_mul_le_max_mul_max' +max_rec' +mdifferentiableWithinAt_iff' +mdifferentiableWithinAt_inter' +Measurable.comp' +Measurable.comp_aemeasurable' +Measurable.const_smul' +Measurable.div' +MeasurableEmbedding.withDensity_ofReal_comap_apply_eq_integral_abs_deriv_mul' +Measurable.ennreal_tsum' +MeasurableEquiv.withDensity_ofReal_map_symm_apply_eq_integral_abs_deriv_mul' +measurable_findGreatest' +measurable_from_prod_countable' +measurable_id' +measurable_id'' +Measurable.inf' +Measurable.iSup' +Measurable.lintegral_kernel_prod_left' +Measurable.lintegral_kernel_prod_right' +Measurable.lintegral_kernel_prod_right'' +Measurable.mul' +measurable_of_isClosed' +measurable_quotient_mk' +measurable_quotient_mk'' +measurableSet_eq_fun' +MeasurableSet.image_inclusion' +measurableSet_le' +measurableSet_lt' +Measurable.sup' +measurable_to_countable' +measurable_tProd_elim' +MeasureTheory.abs_toReal_measure_sub_le_measure_symmDiff' +MeasureTheory.adapted_predictablePart' +MeasureTheory.addContent_union' +MeasureTheory.AECover.integrable_of_lintegral_nnnorm_bounded' +MeasureTheory.AECover.integrable_of_lintegral_nnnorm_tendsto' +MeasureTheory.ae_eq_comp' +MeasureTheory.ae_eq_dirac' +MeasureTheory.ae_eq_of_forall_setIntegral_eq_of_sigmaFinite' +MeasureTheory.ae_eq_trim_iff_of_aeStronglyMeasurable' +MeasureTheory.ae_lt_top' +MeasureTheory.aemeasurable_withDensity_ennreal_iff' +MeasureTheory.ae_restrict_iff' +MeasureTheory.AEStronglyMeasurable.comp_ae_measurable' +MeasureTheory.AEStronglyMeasurable.const_smul' +MeasureTheory.AEStronglyMeasurable.convolution_integrand' +MeasureTheory.AEStronglyMeasurable.convolution_integrand_snd' +MeasureTheory.AEStronglyMeasurable.convolution_integrand_swap_snd' +MeasureTheory.AEStronglyMeasurable'.of_subsingleton' +MeasureTheory.ae_withDensity_iff' +MeasureTheory.ae_withDensity_iff_ae_restrict' +MeasureTheory.average_eq' +MeasureTheory.condexp_bot' +MeasureTheory.condexpIndL1Fin_smul' +MeasureTheory.condexpIndL1_smul' +MeasureTheory.condexpInd_smul' +MeasureTheory.condexpIndSMul_smul' +MeasureTheory.condexpL1CLM_of_aestronglyMeasurable' +MeasureTheory.condexpL1_of_aestronglyMeasurable' +MeasureTheory.condexp_of_aestronglyMeasurable' +MeasureTheory.Content.innerContent_mono' +MeasureTheory.diracProba_toMeasure_apply' +MeasureTheory.eLpNorm_add_le' +MeasureTheory.eLpNorm'_const' +MeasureTheory.eLpNorm_const' +MeasureTheory.eLpNorm_eq_eLpNorm' +MeasureTheory.eLpNorm'_eq_zero_of_ae_zero' +MeasureTheory.eLpNorm_indicator_const' +MeasureTheory.eLpNorm'_le_eLpNorm'_mul_eLpNorm' +MeasureTheory.eLpNorm_nnreal_eq_eLpNorm' +MeasureTheory.eLpNorm_one_le_of_le' +MeasureTheory.eLpNorm'_smul_le_mul_eLpNorm' +MeasureTheory.eLpNorm_sub_le' +MeasureTheory.eLpNorm'_zero' +MeasureTheory.eLpNorm_zero' +MeasureTheory.exp_llr_of_ac' +MeasureTheory.exp_neg_llr' +MeasureTheory.Filtration.stronglyMeasurable_limit_process' +MeasureTheory.hasFiniteIntegral_congr' +MeasureTheory.HasFiniteIntegral.congr' +MeasureTheory.HasFiniteIntegral.mono' +MeasureTheory.hasFiniteIntegral_prod_iff' +MeasureTheory.HasPDF.congr' +MeasureTheory.Ico_ae_eq_Icc' +MeasureTheory.Ico_ae_eq_Ioc' +MeasureTheory.Iio_ae_eq_Iic' +MeasureTheory.inducedOuterMeasure_eq' +MeasureTheory.inducedOuterMeasure_eq_extend' +MeasureTheory.Integrable.add' +MeasureTheory.Integrable.bdd_mul' +MeasureTheory.Integrable.comp_mul_left' +MeasureTheory.Integrable.comp_mul_right' +MeasureTheory.integrable_congr' +MeasureTheory.Integrable.congr' +MeasureTheory.Integrable.const_mul' +MeasureTheory.integrable_finset_sum' +MeasureTheory.Integrable.mono' +MeasureTheory.Integrable.mul_const' +MeasureTheory.integrable_of_forall_fin_meas_le' +MeasureTheory.Integrable.simpleFunc_mul' +MeasureTheory.Integrable.toL1_smul' +MeasureTheory.integrable_withDensity_iff_integrable_smul' +MeasureTheory.integral_add' +MeasureTheory.integral_countable' +MeasureTheory.integral_dirac' +MeasureTheory.integral_Icc_eq_integral_Ico' +MeasureTheory.integral_Icc_eq_integral_Ioc' +MeasureTheory.integral_Icc_eq_integral_Ioo' +MeasureTheory.integral_Ici_eq_integral_Ioi' +MeasureTheory.integral_Ico_eq_integral_Ioo' +MeasureTheory.integral_Iic_eq_integral_Iio' +MeasureTheory.integral_Ioc_eq_integral_Ioo' +MeasureTheory.integral_neg' +MeasureTheory.integral_singleton' +MeasureTheory.integral_sub' +MeasureTheory.integral_zero' +MeasureTheory.Ioc_ae_eq_Icc' +MeasureTheory.Ioi_ae_eq_Ici' +MeasureTheory.Ioo_ae_eq_Icc' +MeasureTheory.Ioo_ae_eq_Ico' +MeasureTheory.Ioo_ae_eq_Ioc' +MeasureTheory.isClosed_aeStronglyMeasurable' +MeasureTheory.isComplete_aeStronglyMeasurable' +MeasureTheory.IsFundamentalDomain.integral_eq_tsum' +MeasureTheory.IsFundamentalDomain.integral_eq_tsum'' +MeasureTheory.IsFundamentalDomain.lintegral_eq_tsum' +MeasureTheory.IsFundamentalDomain.lintegral_eq_tsum'' +MeasureTheory.IsFundamentalDomain.measure_eq_tsum' +MeasureTheory.IsFundamentalDomain.setIntegral_eq_tsum' +MeasureTheory.IsFundamentalDomain.setLIntegral_eq_tsum' +MeasureTheory.IsStoppingTime.measurableSet_eq' +MeasureTheory.IsStoppingTime.measurableSet_eq_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_eq_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSet_ge' +MeasureTheory.IsStoppingTime.measurableSet_ge_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_ge_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSet_gt' +MeasureTheory.IsStoppingTime.measurableSet_le' +MeasureTheory.IsStoppingTime.measurableSet_lt' +MeasureTheory.IsStoppingTime.measurableSet_lt_of_countable' +MeasureTheory.IsStoppingTime.measurableSet_lt_of_countable_range' +MeasureTheory.IsStoppingTime.measurableSpace_le' +MeasureTheory.L1.norm_setToL1_le' +MeasureTheory.L1.norm_setToL1_le_mul_norm' +MeasureTheory.L1.setToL1_add_left' +MeasureTheory.L1.setToL1_congr_left' +MeasureTheory.L1.setToL1_eq_setToL1' +MeasureTheory.L1.setToL1_mono_left' +MeasureTheory.L1.setToL1_smul_left' +MeasureTheory.L1.setToL1_zero_left' +MeasureTheory.L1.SimpleFunc.norm_setToL1SCLM_le' +MeasureTheory.L1.SimpleFunc.setToL1S_add_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_add_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_congr_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_mono_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_smul_left' +MeasureTheory.L1.SimpleFunc.setToL1SCLM_zero_left' +MeasureTheory.L1.SimpleFunc.setToL1S_mono_left' +MeasureTheory.L1.SimpleFunc.setToL1S_smul_left' +MeasureTheory.L1.SimpleFunc.setToL1S_zero_left' +MeasureTheory.L2.add_left' +MeasureTheory.L2.norm_sq_eq_inner' +MeasureTheory.L2.smul_left' +MeasureTheory.laverage_eq' +MeasureTheory.lintegral_add_left' +MeasureTheory.lintegral_add_right' +MeasureTheory.lintegral_const_mul' +MeasureTheory.lintegral_const_mul'' +MeasureTheory.lintegral_count' +MeasureTheory.lintegral_countable' +MeasureTheory.lintegral_dirac' +MeasureTheory.lintegral_eq_zero_iff' +MeasureTheory.lintegral_finset_sum' +MeasureTheory.lintegral_iInf' +MeasureTheory.lintegral_map' +MeasureTheory.lintegral_mono' +MeasureTheory.lintegral_mono_fn' +MeasureTheory.lintegral_mono_set' +MeasureTheory.lintegral_mul_const' +MeasureTheory.lintegral_mul_const'' +MeasureTheory.lintegral_rpow_nnnorm_eq_rpow_eLpNorm' +MeasureTheory.lintegral_singleton' +MeasureTheory.lintegral_sub' +MeasureTheory.lintegral_sub_le' +MeasureTheory.lmarginal_union' +MeasureTheory.locallyIntegrable_finset_sum' +MeasureTheory.lowerCrossingTime_stabilize' +MeasureTheory.Lp.ae_tendsto_of_cauchy_eLpNorm' +MeasureTheory.Lp.eLpNorm'_lim_le_liminf_eLpNorm' +MeasureTheory.Lp.eLpNorm'_sum_norm_sub_le_tsum_of_cauchy_eLpNorm' +MeasureTheory.lpMeas.aeStronglyMeasurable' +MeasureTheory.Lp.norm_const' +MeasureTheory.Lp.simpleFunc.eq' +MeasureTheory.Lp.tendsto_Lp_iff_tendsto_ℒp' +MeasureTheory.Lp.tendsto_Lp_iff_tendsto_ℒp'' +MeasureTheory.measurableSet_filtrationOfSet' +MeasureTheory.measurableSet_sigmaFiniteSetWRT' +MeasureTheory.Measure.ae_sum_iff' +MeasureTheory.Measure.bind_zero_right' +MeasureTheory.Measure.count_apply_eq_top' +MeasureTheory.Measure.count_apply_finite' +MeasureTheory.Measure.count_apply_finset' +MeasureTheory.Measure.count_apply_lt_top' +MeasureTheory.Measure.count_eq_zero_iff' +MeasureTheory.Measure.count_injective_image' +MeasureTheory.Measure.count_ne_zero' +MeasureTheory.Measure.count_ne_zero'' +MeasureTheory.Measure.count_singleton' +MeasureTheory.measure_diff' +MeasureTheory.measure_diff_null' +MeasureTheory.Measure.dirac_apply' +MeasureTheory.Measure.empty_of_count_eq_zero' +MeasureTheory.Measure.ext_iff' +MeasureTheory.Measure.haveLebesgueDecompositionSMul' +MeasureTheory.Measure.InnerRegularWRT.map' +MeasureTheory.Measure.integral_toReal_rnDeriv' +MeasureTheory.measure_inter_conull' +MeasureTheory.Measure.inv_rnDeriv' +MeasureTheory.measure_iUnion_null_iff' +MeasureTheory.Measure.LebesgueDecomposition.iSup_mem_measurableLE' +MeasureTheory.Measure.LebesgueDecomposition.iSup_monotone' +MeasureTheory.Measure.le_iff' +MeasureTheory.Measure.lt_iff' +MeasureTheory.Measure.map_id' +MeasureTheory.Measure.measurable_bind' +MeasureTheory.Measure.MeasureDense.nonempty' +MeasureTheory.Measure.nonpos_iff_eq_zero' +MeasureTheory.Measure.pi_noAtoms' +MeasureTheory.MeasurePreserving.integral_comp' +MeasureTheory.Measure.restrict_apply₀' +MeasureTheory.Measure.restrict_apply_eq_zero' +MeasureTheory.Measure.restrict_restrict' +MeasureTheory.Measure.restrict_restrict₀' +MeasureTheory.Measure.restrict_singleton' +MeasureTheory.Measure.restrict_union' +MeasureTheory.Measure.restrict_union_add_inter' +MeasureTheory.Measure.rnDeriv_mul_rnDeriv' +MeasureTheory.Measure.rnDeriv_pos' +MeasureTheory.Measure.setIntegral_toReal_rnDeriv' +MeasureTheory.Measure.setIntegral_toReal_rnDeriv_eq_withDensity' +MeasureTheory.Measure.setLIntegral_rnDeriv' +MeasureTheory.Measure.sum_apply_eq_zero' +MeasureTheory.Measure.toSphere_apply' +MeasureTheory.Measure.toSphere_apply_univ' +MeasureTheory.measure_union' +MeasureTheory.measure_union₀' +MeasureTheory.measure_union_add_inter' +MeasureTheory.measure_union_add_inter₀' +MeasureTheory.memℒp_finset_sum' +MeasureTheory.Memℒp.integrable_norm_rpow' +MeasureTheory.Memℒp.meas_ge_lt_top' +MeasureTheory.mem_lpMeas_iff_aeStronglyMeasurable' +MeasureTheory.mem_lpMeasSubgroup_iff_aeStronglyMeasurable' +MeasureTheory.Memℒp.mono' +MeasureTheory.norm_indicatorConstLp' +MeasureTheory.norm_setIntegral_le_of_norm_le_const' +MeasureTheory.norm_setIntegral_le_of_norm_le_const_ae' +MeasureTheory.norm_setIntegral_le_of_norm_le_const_ae'' +MeasureTheory.norm_setToFun_le' +MeasureTheory.norm_setToFun_le_mul_norm' +MeasureTheory.NullMeasurable.measurable' +MeasureTheory.OuterMeasure.empty' +MeasureTheory.OuterMeasure.isCaratheodory_iff_le' +MeasureTheory.OuterMeasure.iUnion_null_iff' +MeasureTheory.OuterMeasure.le_boundedBy' +MeasureTheory.OuterMeasure.mono' +MeasureTheory.OuterMeasure.mono'' +MeasureTheory.OuterMeasure.top_apply' +MeasureTheory.OuterMeasure.trim_eq_iInf' +MeasureTheory.pdf.eq_of_map_eq_withDensity' +MeasureTheory.pdf.quasiMeasurePreserving_hasPDF' +MeasureTheory.piPremeasure_pi' +MeasureTheory.ProbabilityMeasure.tendsto_measure_of_null_frontier_of_tendsto' +MeasureTheory.ProgMeasurable.finset_prod' +MeasureTheory.progMeasurable_of_tendsto' +MeasureTheory.restrict_dirac' +MeasureTheory.restrict_withDensity' +MeasureTheory.setAverage_eq' +MeasureTheory.setIntegral_dirac' +MeasureTheory.setIntegral_tilted' +MeasureTheory.setLaverage_eq' +MeasureTheory.setLIntegral_dirac' +MeasureTheory.setLIntegral_eq_zero_iff' +MeasureTheory.setLIntegral_mono' +MeasureTheory.setLIntegral_mono_ae' +MeasureTheory.setLIntegral_tilted' +MeasureTheory.setLIntegral_withDensity_eq_lintegral_mul₀' +MeasureTheory.setLIntegral_withDensity_eq_setLIntegral_mul_non_measurable₀' +MeasureTheory.setToFun_add_left' +MeasureTheory.setToFun_congr_left' +MeasureTheory.setToFun_finset_sum' +MeasureTheory.setToFun_measure_zero' +MeasureTheory.setToFun_mono_left' +MeasureTheory.setToFun_smul_left' +MeasureTheory.setToFun_zero_left' +MeasureTheory.sigmaFinite_restrict_sigmaFiniteSetWRT' +MeasureTheory.SigmaFinite.withDensity_of_ne_top' +MeasureTheory.SignedMeasure.eq_singularPart' +MeasureTheory.SignedMeasure.exists_subset_restrict_nonpos' +MeasureTheory.SignedMeasure.haveLebesgueDecomposition_mk' +MeasureTheory.SignedMeasure.restrictNonposSeq_disjoint' +MeasureTheory.SignedMeasure.someExistsOneDivLT_subset' +MeasureTheory.SimpleFunc.extend_apply' +MeasureTheory.SimpleFunc.extend_comp_eq' +MeasureTheory.SimpleFunc.lintegral_eq_of_subset' +MeasureTheory.SimpleFunc.lintegral_map' +MeasureTheory.SimpleFunc.setToSimpleFunc_add_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_congr' +MeasureTheory.SimpleFunc.setToSimpleFunc_const' +MeasureTheory.SimpleFunc.setToSimpleFunc_mono_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_nonneg' +MeasureTheory.SimpleFunc.setToSimpleFunc_smul_left' +MeasureTheory.SimpleFunc.setToSimpleFunc_zero' +MeasureTheory.SimpleFunc.simpleFunc_bot' +MeasureTheory.stoppedProcess_eq' +MeasureTheory.stoppedProcess_eq'' +MeasureTheory.stoppedValue_eq' +MeasureTheory.stoppedValue_piecewise_const' +MeasureTheory.stoppedValue_sub_eq_sum' +MeasureTheory.StronglyMeasurable.aeStronglyMeasurable' +MeasureTheory.StronglyMeasurable.const_smul' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_left' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_left'' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_right' +MeasureTheory.StronglyMeasurable.integral_kernel_prod_right'' +MeasureTheory.Submartingale.stoppedValue_leastGE_eLpNorm_le' +MeasureTheory.Subsingleton.aestronglyMeasurable' +MeasureTheory.Subsingleton.stronglyMeasurable' +MeasureTheory.TendstoInMeasure.congr' +MeasureTheory.TendstoInMeasure.exists_seq_tendsto_ae' +MeasureTheory.tendsto_sum_indicator_atTop_iff' +MeasureTheory.tilted_apply' +MeasureTheory.tilted_apply_eq_ofReal_integral' +MeasureTheory.tilted_const' +MeasureTheory.tilted_neg_same' +MeasureTheory.tilted_zero' +MeasureTheory.upcrossingsBefore_zero' +MeasureTheory.upperCrossingTime_stabilize' +MeasureTheory.upperCrossingTime_zero' +MeasureTheory.VectorMeasure.ext_iff' +MeasureTheory.VectorMeasure.le_iff' +MeasureTheory.weightedSMul_union' +MeasureTheory.withDensity_apply' +MeasureTheory.withDensity_apply_eq_zero' +MeasureTheory.withDensity_smul' +MeasureTheory.withDensityᵥ_add' +MeasureTheory.withDensityᵥ_neg' +MeasureTheory.withDensityᵥ_smul' +MeasureTheory.withDensityᵥ_smul_eq_withDensityᵥ_withDensity' +MeasureTheory.withDensityᵥ_sub' +MeasureTheory.zero_mem_ℒp' +mem_ball_iff_norm'' +mem_ball_iff_norm''' +mem_closedBall_iff_norm'' +mem_closedBall_iff_norm''' +mem_closure_iff_nhds' +mem_closure_iff_nhds_basis' +mem_coclosed_Lindelof' +mem_codiscrete' +mem_coLindelof' +memℓp_gen' +mem_nhds_prod_iff' +mem_pairSelfAdjointMatricesSubmodule' +mem_rootsOfUnity' +mem_rootsOfUnity_prime_pow_mul_iff' +mem_selfAdjointMatricesSubmodule' +mem_skewAdjointMatricesSubmodule' +mem_sphere_iff_norm' +Metric.ball_eq_ball' +Metric.ball_subset_ball' +Metric.closedBall_subset_ball' +Metric.closedBall_subset_closedBall' +Metric.closedBall_zero' +Metric.continuousAt_iff' +Metric.continuous_iff' +Metric.continuousOn_iff' +Metric.continuousWithinAt_iff' +Metric.cthickening_eq_iInter_cthickening' +Metric.cthickening_eq_iInter_thickening' +Metric.cthickening_eq_iInter_thickening'' +Metric.mem_ball' +Metric.mem_closedBall' +Metric.mem_of_closed' +Metric.mem_sphere' +midpoint_eq_iff' +min_def' +min_div_div_left' +min_div_div_right' +minimal_subset_iff' +min_inv_inv' +min_mul_distrib' +min_mul_min_le_min_mul_mul' +minpoly.dvd_map_of_isScalarTower' +minpoly.eq_X_sub_C' +minpoly.unique' +min_rec' +Miu.le_pow2_and_pow2_eq_mod3' +mk_eq_mk_of_basis' +Mod_.comp_hom' +Mod_.id_hom' +ModularCyclotomicCharacter.toFun_spec' +ModularCyclotomicCharacter.toFun_spec'' +ModularCyclotomicCharacter.toFun_unique' +Module.Baer.ExtensionOfMaxAdjoin.extendIdealTo_wd' +ModuleCat.CoextendScalars.smul_apply' +ModuleCat.hasLimits' +ModuleCat.restrictScalars.smul_def' +Module.End_algebraMap_isUnit_inv_apply_eq_iff' +Module.End.smulCommClass' +Module.free_of_finite_type_torsion_free' +Module.Free.of_subsingleton' +Module.mem_support_iff' +Module.not_mem_support_iff' +Module.projective_def' +Monad.mapM' +Monad.sequence' +Mon_.comp_hom' +Mon_.id_hom' +MonoidAlgebra.lift_apply' +MonoidAlgebra.lift_unique' +Monoid.CoprodI.lift_comp_of' +Monoid.CoprodI.lift_of' +Monoid.Coprod.induction_on' +Monoid.exponent_eq_iSup_orderOf' +Monoid.exponent_min' +MonoidHom.coe_toAdditive' +MonoidHom.coe_toAdditive'' +MonoidHom.comap_bot' +MonoidHom.map_zpow' +MonoidHom.prod_map_comap_prod' +Monoid.PushoutI.NormalWord.base_smul_def' +Monoid.PushoutI.NormalWord.summand_smul_def' +Monotone.const_mul' +Monotone.mul_const' +MonotoneOn.const_mul' +MonotoneOn.mul_const' +MulActionHom.comp_inverse' +MulActionHom.inverse_eq_inverse' +MulActionHom.inverse'_inverse' +MulAction.mem_fixedPoints' +MulAction.mem_stabilizer_finset' +MulAction.mem_stabilizer_set' +MulAction.orbitRel.quotient_eq_of_quotient_subgroup_eq' +MulAction.orbitRel.Quotient.mem_subgroup_orbit_iff' +MulAction.orbitZPowersEquiv_symm_apply' +MulAction.Quotient.coe_smul_out' +MulAction.Quotient.mk_smul_out' +MulAction.right_quotientAction' +MulChar.star_apply' +mul_div_assoc' +mul_div_cancel_of_imp' +mul_eq_mul_iff_eq_and_eq_of_pos' +mul_eq_of_eq_div' +mul_eq_one' +MulEquiv.mk_coe' +MulHom.prod_map_comap_prod' +mul_inv_le_iff' +mul_inv_le_iff_le_mul' +mul_inv_le_mul_inv_iff' +mul_inv_lt_iff' +mul_inv_lt_iff_le_mul' +mul_inv_lt_mul_inv_iff' +mul_invOf_cancel_left' +mul_invOf_cancel_right' +mul_invOf_self' +mul_left_cancel'' +mul_left_inj' +mul_le_iff_le_one_left' +mul_le_iff_le_one_right' +mul_le_mul' +mul_le_mul_left' +mul_le_mul_of_nonneg' +mul_le_mul_of_nonneg_of_nonpos' +mul_le_mul_of_nonpos_of_nonneg' +mul_le_mul_of_nonpos_of_nonpos' +mul_le_mul_right' +mul_le_of_le_of_le_one' +mul_le_of_le_one_left' +mul_le_of_le_one_of_le' +mul_le_of_le_one_right' +mul_lt_iff_lt_one_left' +mul_lt_iff_lt_one_right' +mul_lt_mul_left' +mul_lt_mul_of_pos' +mul_lt_mul_right' +mul_lt_of_le_of_lt_one' +mul_lt_of_le_one_of_lt' +mul_lt_of_lt_of_le_one' +mul_lt_of_lt_of_lt_one' +mul_lt_of_lt_one_left' +mul_lt_of_lt_one_of_le' +mul_lt_of_lt_one_of_lt' +mul_lt_of_lt_one_right' +mul_ne_one' +mul_right_cancel'' +mul_right_inj' +mul_rotate' +MulSemiringActionHom.coe_fn_coe' +MultilinearMap.mkContinuousLinear_norm_le' +MultilinearMap.mkContinuousMultilinear_norm_le' +Multipliable.sigma' +Multiplicative.isometricSMul' +Multiplicative.isometricVAdd'' +multiplicity.is_greatest' +multiplicity.mul' +multiplicity.pow' +multiplicity.unique' +Multiset.add_le_add_iff_left' +Multiset.aemeasurable_prod' +Multiset.aestronglyMeasurable_prod' +Multiset.antidiagonal_coe' +Multiset.attach_map_val' +Multiset.count_sum' +Multiset.dedup_subset' +Multiset.ext' +Multiset.extract_gcd' +Multiset.filter_attach' +Multiset.filter_eq' +Multiset.foldl_induction' +Multiset.foldr_induction' +Multiset.induction_on' +Multiset.map_const' +Multiset.map_filter' +Multiset.map_id' +Multiset.measurable_prod' +Multiset.Nat.antidiagonal_succ' +Multiset.Nat.antidiagonal_succ_succ' +Multiset.noncommProd_cons' +Multiset.powersetAux_perm_powersetAux' +Multiset.powersetCard_coe' +Multiset.powerset_coe' +Multiset.prod_hom' +Multiset.prod_lt_prod' +Multiset.prod_lt_prod_of_nonempty' +Multiset.prod_map_inv' +Multiset.prod_X_add_C_coeff' +Multiset.quot_mk_to_coe' +Multiset.quot_mk_to_coe'' +Multiset.revzip_powersetAux' +Multiset.revzip_powersetAux_perm_aux' +Multiset.smul_prod' +Multiset.stronglyMeasurable_prod' +Multiset.subset_dedup' +MvFunctor.f' +MvFunctor.g' +MvFunctor.id_map' +MvPFunctor.liftP_iff' +MvPFunctor.M.bisim' +MvPFunctor.M.dest_corec' +MvPFunctor.M.dest'_eq_dest' +MvPFunctor.M.dest_eq_dest' +MvPFunctor.wDest'_wMk' +MvPolynomial.aeval_zero' +MvPolynomial.algHom_ext' +MvPolynomial.C_mul' +MvPolynomial.coeff_monomial_mul' +MvPolynomial.coeff_mul_monomial' +MvPolynomial.coeff_mul_X' +MvPolynomial.coeff_X' +MvPolynomial.coeff_X_mul' +MvPolynomial.degrees_X' +MvPolynomial.eval₂_eq' +MvPolynomial.eval₂Hom_congr' +MvPolynomial.eval₂Hom_X' +MvPolynomial.eval₂Hom_zero' +MvPolynomial.eval_eq' +MvPolynomial.eval_eq_eval_mv_eval' +MvPolynomial.eval_zero' +MvPolynomial.finSuccEquiv_support' +MvPolynomial.homogeneousComponent_eq_zero' +MvPolynomial.isLocalization_C_mk' +MvPolynomial.monomial_zero' +MvPolynomial.support_esymm' +MvPolynomial.support_esymm'' +MvPolynomial.weightedHomogeneousComponent_eq_zero' +MvPowerSeries.algebraMap_apply' +MvPowerSeries.algebraMap_apply'' +MvPowerSeries.invOfUnit_eq' +MvQPF.Cofix.dest_corec' +MvQPF.liftR_map_last' +MvQPF.recF_eq' +MvQPF.wEquiv.abs' +Nat.add_descFactorial_eq_ascFactorial' +Nat.ascFactorial_eq_factorial_mul_choose' +Nat.bit_add' +Nat.card_eq_two_iff' +Nat.cauchy_induction' +Nat.choose_eq_asc_factorial_div_factorial' +Nat.choose_succ_succ' +Nat.coprime_of_dvd' +Nat.count_add' +Nat.count_succ' +Nat.decreasingInduction_succ' +Nat.digits_def' +Nat.digits_zero_succ' +Nat.dist_tri_left' +Nat.dist_tri_right' +Nat.div_add_mod' +Nat.div_le_of_le_mul' +Nat.div_le_self' +Nat.div_lt_iff_lt_mul' +Nat.dvd_sub' +Nat.eq_sqrt' +Nat.eq_sub_of_add_eq' +Nat.equivProdNatFactoredNumbers_apply' +Nat.equivProdNatSmoothNumbers_apply' +Nat.even_add' +Nat.even_or_odd' +Nat.even_pow' +Nat.even_sub' +Nat.even_xor_odd' +Nat.exists_mul_self' +Nat.factorial_inj' +Nat.find_min' +Nat.floor_eq_iff' +Nat.floor_eq_on_Ico' +Nat.floor_lt' +Nat.Icc_eq_range' +Nat.Ico_eq_range' +Nat.iInf_le_succ' +Nat.iInf_lt_succ' +Nat.Ioc_eq_range' +Nat.Ioo_eq_range' +Nat.iSup_le_succ' +Nat.iSup_lt_succ' +Nat.le_div_iff_mul_le' +Nat.le_floor_iff' +Nat.le_minFac' +Nat.le_nth_count' +Nat.leRecOn_succ' +Nat.leRec_succ' +Nat.le_sqrt' +Nat.log_eq_one_iff' +Nat.lt_sub_iff_add_lt' +Nat.lt_succ_sqrt' +Nat.mem_primeFactorsList' +Nat.mod_add_div' +Nat.ModEq.add_left_cancel' +Nat.ModEq.add_right_cancel' +Nat.ModEq.cancel_left_div_gcd' +Nat.ModEq.cancel_right_div_gcd' +Nat.modEq_list_prod_iff' +Nat.ModEq.mul_left' +Nat.ModEq.mul_left_cancel_iff' +Nat.ModEq.mul_right' +Nat.ModEq.mul_right_cancel_iff' +Nat.monotone_primeCounting' +Nat.mul_add_mod' +Nat.mul_div_cancel_left' +nat_mul_inj' +Nat.mul_lt_mul'' +Nat.not_exists_sq' +Nat.not_prime_mul' +Nat.nth_le_nth' +Nat.nth_lt_nth' +Nat.odd_add' +Nat.odd_sub' +Nat.ofDigits_modEq' +Nat.ofDigits_zmodeq' +Nat.one_le_pow' +Nat.one_lt_pow' +Nat.one_lt_two_pow' +Nat.pair_unpair' +Nat.Partrec.Code.encode_lt_rfind' +Nat.Partrec.Code.rec_prim' +Nat.Partrec'.comp' +Nat.Partrec.merge' +Nat.Partrec.prec' +Nat.Partrec.rfind' +Nat.pow_lt_ascFactorial' +Nat.pow_sub_lt_descFactorial' +Nat.prime_def_lt' +Nat.prime_def_lt'' +Nat.Prime.eq_two_or_odd' +Nat.primeFactorsList_chain' +Nat.Prime.not_prime_pow' +Nat.Prime.one_lt' +Nat.Primrec.casesOn' +Nat.Primrec'.comp' +Nat.Primrec'.prec' +Nat.Primrec.swap' +Nat.prod_divisorsAntidiagonal' +Nat.rfind_dom' +Nat.rfind_min' +Nat.sInf_add' +Nat.size_shiftLeft' +Nat.sq_mul_squarefree_of_pos' +Nat.sqrt_add_eq' +Nat.sqrt_eq' +Nat.sqrt_le' +Nat.sqrt_lt' +Nat.sqrt_mul_sqrt_lt_succ' +Nat.sub_eq_of_eq_add' +Nat.sub_lt_iff_lt_add' +Nat.succ_le_succ_sqrt' +Nat.succ_pos' +Nat.sum_totient' +Nat.surjective_primeCounting' +Nat.tendsto_primeCounting' +Nat.uIcc_eq_range' +Ne.bot_lt' +neg_div' +neg_gcd' +neg_of_smul_neg_left' +neg_of_smul_neg_right' +neg_pow' +Ne.lt_of_le' +Ne.lt_top' +ne_of_irrefl' +ne_of_ne_of_eq' +newton_seq_dist_tendsto' +NeZero.ne' +NeZero.of_gt' +ne_zero_of_irreducible_X_pow_sub_C' +nhds_basis_Ioo' +nhds_basis_uniformity' +nhds_def' +nhds_eq_comap_uniformity' +nhds_eq_uniformity' +nhds_left'_sup_nhds_right' +nhds_left_sup_nhds_right' +nhds_one_symm' +nhdsWithin_eq_nhdsWithin' +nhdsWithin_extChartAt_target_eq' +nhdsWithin_Ici_basis' +nhdsWithin_Ici_eq' +nhdsWithin_Ici_eq'' +nhdsWithin_Iic_basis' +nhdsWithin_Iic_eq' +nhdsWithin_Iic_eq'' +nhdsWithin_Iio_basis' +nhdsWithin_Iio_neBot' +nhdsWithin_Iio_self_neBot' +nhdsWithin_inter' +nhdsWithin_inter_of_mem' +nhdsWithin_Ioi_basis' +nhdsWithin_Ioi_neBot' +nhdsWithin_Ioi_self_neBot' +nhdsWithin_pi_eq' +nhdsWithin_restrict' +nhdsWithin_restrict'' +nndist_eq_nnnorm_vsub' +nndist_midpoint_midpoint_le' +nndist_nnnorm_nnnorm_le' +nnnorm_algebraMap' +nnnorm_eq_zero' +nnnorm_inv' +nnnorm_le_nnnorm_add_nnnorm_div' +nnnorm_le_pi_nnnorm' +nnnorm_mul_le' +nnnorm_ne_zero_iff' +nnnorm_one' +nnnorm_pos' +NNRat.instSMulCommClass' +NNReal.ball_zero_eq_Ico' +NNReal.closedBall_zero_eq_Icc' +NNReal.div_le_iff' +NNReal.div_le_of_le_mul' +NNReal.div_lt_iff' +NNReal.inner_le_Lp_mul_Lq_tsum' +NNReal.le_div_iff' +NNReal.list_prod_map_rpow' +NNReal.Lp_add_le_tsum' +NNReal.lt_div_iff' +NNReal.nndist_zero_eq_val' +NNReal.rpow_add' +NNReal.rpow_add_intCast' +NNReal.rpow_add_natCast' +NNReal.rpow_add_one' +NNReal.rpow_one_add' +NNReal.rpow_one_sub' +NNReal.rpow_sub' +NNReal.rpow_sub_intCast' +NNReal.rpow_sub_natCast' +NNReal.rpow_sub_one' +NNReal.tendsto_coe' +NonUnitalAlgHom.coe_inverse' +NonUnitalAlgHom.coe_restrictScalars' +NonUnitalStarAlgebra.adjoin_induction' +NonUnitalStarAlgHom.coe_mk' +NonUnitalStarAlgHom.coe_restrictScalars' +NonUnitalStarSubalgebra.instIsScalarTower' +NonUnitalStarSubalgebra.instSMulCommClass' +NonUnitalStarSubalgebra.module' +NonUnitalSubalgebra.instIsScalarTower' +NonUnitalSubalgebra.instModule' +NonUnitalSubalgebra.instSMulCommClass' +NonUnitalSubring.coe_mk' +NonUnitalSubring.eq_top_iff' +NonUnitalSubring.mem_mk' +NonUnitalSubsemiring.coe_mk' +NonUnitalSubsemiring.eq_top_iff' +NonUnitalSubsemiring.mem_mk' +normalClosure_eq_iSup_adjoin' +norm_algebraMap' +NormedAddCommGroup.cauchy_series_of_le_geometric' +NormedAddCommGroup.cauchy_series_of_le_geometric'' +NormedAddGroupHom.coe_mkNormedAddGroupHom' +NormedAddGroupHom.completion_coe' +NormedAddGroupHom.norm_comp_le_of_le' +NormedRing.inverse_one_sub_nth_order' +NormedSpace.exp_conj' +NormedSpace.expSeries_apply_eq' +NormedSpace.expSeries_apply_eq_div' +NormedSpace.exp_series_hasSum_exp' +NormedSpace.expSeries_hasSum_exp_of_mem_ball' +NormedSpace.expSeries_summable' +NormedSpace.expSeries_summable_of_mem_ball' +NormedSpace.exp_units_conj' +NormedSpace.isVonNBounded_iff' +NormedSpace.norm_expSeries_summable' +NormedSpace.norm_expSeries_summable_of_mem_ball' +norm_eq_of_mem_sphere' +norm_eq_zero'' +norm_eq_zero''' +norm_inv' +norm_le_norm_add_const_of_dist_le' +norm_le_norm_add_norm_div' +norm_le_of_mem_closedBall' +norm_le_pi_norm' +norm_le_zero_iff'' +norm_le_zero_iff''' +norm_lt_of_mem_ball' +norm_ne_zero_iff' +norm_nonneg' +norm_of_subsingleton' +norm_one' +norm_pos_iff'' +norm_pos_iff''' +norm_sub_norm_le' +norm_toNNReal' +not_dvd_index_sylow' +not_lt_zero' +not_mem_of_lt_csInf' +npow_mul' +nsmul_eq_mul' +nullMeasurableSet_lt' +Num.add_ofNat' +NumberField.InfinitePlace.orbitRelEquiv_apply_mk'' +NumberField.mixedEmbedding.convexBodySumFun_apply' +NumberField.mixedEmbedding.norm_eq_zero_iff' +NumberField.Units.regulator_eq_det' +Num.cast_sub' +Num.cast_succ' +Num.cast_zero' +Num.mem_ofZNum' +Num.of_to_nat' +Num.succ_ofInt' +odd_add_one_self' +odd_add_self_one' +ofReal_norm_eq_coe_nnnorm' +OmegaCompletePartialOrder.const_continuous' +OmegaCompletePartialOrder.ContinuousHom.bind_continuous' +OmegaCompletePartialOrder.ContinuousHom.forall_forall_merge' +OmegaCompletePartialOrder.ContinuousHom.ite_continuous' +OmegaCompletePartialOrder.ContinuousHom.map_continuous' +OmegaCompletePartialOrder.ContinuousHom.seq_continuous' +OmegaCompletePartialOrder.Continuous.of_bundled' +OmegaCompletePartialOrder.flip₁_continuous' +OmegaCompletePartialOrder.flip₂_continuous' +OmegaCompletePartialOrder.id_continuous' +OmegaCompletePartialOrder.ScottContinuous.continuous' +one_le_div' +one_le_finprod' +one_le_pow_of_one_le' +one_le_thickenedIndicator_apply' +one_le_two' +one_lt_div' +one_lt_finprod' +one_lt_pow' +one_lt_zpow' +one_ne_zero' +OnePoint.continuousAt_infty' +OnePoint.isOpen_iff_of_mem' +OnePoint.tendsto_nhds_infty' +ONote.exists_lt_mul_omega0' +ONote.exists_lt_omega0_opow' +ONote.fastGrowing_zero' +ONote.NF.below_of_lt' +ONote.nf_repr_split' +ONote.NF.snd' +ONote.split_eq_scale_split' +OpenEmbedding.tendsto_nhds_iff' +openSegment_eq_image' +openSegment_eq_Ioo' +Option.bind_congr' +Option.bind_eq_bind' +Option.bind_eq_some' +Option.guard_eq_some' +Option.map_bind' +Option.map_coe' +Option.none_bind' +Option.none_orElse' +Option.orElse_eq_none' +Option.orElse_eq_some' +Option.orElse_none' +Option.some_bind' +Option.some_orElse' +or_congr_left' +or_congr_right' +OrderDual.continuousConstSMul' +OrderDual.instDistribMulAction' +OrderDual.instDistribSMul' +OrderDual.instIsScalarTower' +OrderDual.instIsScalarTower'' +OrderDual.instModule' +OrderDual.instMulAction' +OrderDual.instMulActionWithZero' +OrderDual.instPow' +OrderDual.instSMulCommClass' +OrderDual.instSMulCommClass'' +OrderDual.instSMulWithZero' +Order.height_le_iff' +Order.Ideal.IsMaximal.isCoatom' +OrderIso.isGLB_image' +OrderIso.isGLB_preimage' +OrderIso.isLUB_image' +OrderIso.isLUB_preimage' +OrderIso.map_bot' +OrderIso.map_csInf' +OrderIso.map_csSup' +OrderIso.map_top' +OrderIso.subsingleton_of_wellFoundedGT' +OrderIso.subsingleton_of_wellFoundedLT' +Order.isPredPrelimitRecOn_pred' +Order.isSuccPrelimitRecOn_succ' +Order.not_isPredPrelimit_iff' +Order.not_isSuccPrelimit_iff' +orderOf_eq_zero_iff' +orderOf_pow' +Ordinal.add_lt_add_iff_left' +Ordinal.blsub_eq_lsub' +Ordinal.brange_bfamilyOfFamily' +Ordinal.bsup_eq_sup' +Ordinal.cof_eq' +Ordinal.comp_bfamilyOfFamily' +Ordinal.comp_familyOfBFamily' +Ordinal.enum_le_enum' +Ordinal.enum_zero_le' +Ordinal.IsNormal.le_set' +Ordinal.lift_down' +Ordinal.lift.principalSeg_top' +Ordinal.liftPrincipalSeg_top' +Ordinal.lsub_eq_blsub' +Ordinal.lt_nmul_iff₃' +Ordinal.mul_eq_zero' +Ordinal.nhds_right' +Ordinal.nmul_le_iff₃' +Ordinal.nmul_nadd_le₃' +Ordinal.nmul_nadd_lt₃' +Ordinal.pred_eq_iff_not_succ' +Ordinal.range_familyOfBFamily' +Ordinal.relIso_enum' +Ordinal.succ_le_iff' +Ordinal.sup_eq_bsup' +Ordinal.toPGame_moveLeft' +Ordinal.type_def' +Ordinal.typein_le_typein' +Ordinal.type_le_iff' +Ordinal.zero_opow' +Ordnode.all_balance' +Ordnode.all_node' +Ordnode.balance_eq_balance' +Ordnode.balanceL_eq_balance' +Ordnode.balanceR_eq_balance' +Ordnode.dual_balance' +Ordnode.dual_node' +Ordnode.length_toList' +Ordnode.Raised.dist_le' +Ordnode.size_balance' +Ordnode.Sized.balance' +Ordnode.Sized.eq_node' +Ordnode.Sized.node' +Ordnode.Valid'.balance' +Ordnode.Valid'.node' +OreLocalization.add' +OreLocalization.add'' +OreLocalization.div_eq_one' +OreLocalization.inv' +OreLocalization.mul_cancel' +OreLocalization.oreDiv_add_char' +OreLocalization.smul' +OreLocalization.smul_cancel' +OreLocalization.zero_oreDiv' +Orientation.inner_rightAngleRotation_swap' +Orientation.kahler_comp_rightAngleRotation' +Orientation.rightAngleRotation_map' +Orientation.volumeForm_robust' +Padic.complete' +Padic.complete'' +Padic.lim' +padicNormE.eq_padic_norm' +padicNormE.image' +padicNorm.sum_le' +padicNorm.sum_lt' +Padic.rat_dense' +padicValNat_def' +padicValNat.div' +PartENat.casesOn' +PartENat.get_natCast' +PartENat.get_ofNat' +PartENat.toWithTop_natCast' +PartENat.toWithTop_one' +PartENat.toWithTop_top' +PartENat.toWithTop_zero' +Part.eq_none_iff' +Part.Fix.approx_mono' +Part.fix_def' +PartialEquiv.image_source_inter_eq' +PartialEquiv.symm_image_target_inter_eq' +PartialEquiv.trans_refl_restr' +PartialEquiv.trans_source' +PartialEquiv.trans_source'' +PartialEquiv.trans_target' +PartialEquiv.trans_target'' +PartialHomeomorph.contDiffWithinAt_extend_coord_change' +PartialHomeomorph.continuousAt_extend_symm' +PartialHomeomorph.eventually_left_inverse' +PartialHomeomorph.eventually_nhds' +PartialHomeomorph.eventually_nhdsWithin' +PartialHomeomorph.eventually_right_inverse' +PartialHomeomorph.extend_coord_change_source_mem_nhdsWithin' +PartialHomeomorph.extend_target' +PartialHomeomorph.image_source_inter_eq' +PartialHomeomorph.IsImage.iff_preimage_eq' +PartialHomeomorph.IsImage.iff_symm_preimage_eq' +PartialHomeomorph.isOpen_extend_preimage' +PartialHomeomorph.ofSet_trans' +PartialHomeomorph.prod_eq_prod_of_nonempty' +PartialHomeomorph.restr_source' +PartialHomeomorph.restr_toPartialEquiv' +PartialHomeomorph.trans_of_set' +PartialHomeomorph.trans_source' +PartialHomeomorph.trans_source'' +PartialHomeomorph.trans_target' +PartialHomeomorph.trans_target'' +PartitionOfUnity.exists_finset_nhd' +PartitionOfUnity.sum_finsupport' +Part.map_id' +Partrec₂.unpaired' +Partrec.const' +Partrec.merge' +PathConnectedSpace.exists_path_through_family' +Path.extend_extends' +pcontinuous_iff' +Pell.eq_of_xn_modEq' +Perfection.coeff_iterate_frobenius' +Perfection.coeff_pow_p' +PerfectionMap.comp_equiv' +PerfectionMap.comp_symm_equiv' +PFunctor.Approx.head_succ' +PFunctor.liftp_iff' +PFunctor.M.agree_iff_agree' +PFunctor.M.bisim' +PFunctor.M.casesOn_mk' +PFunctor.M.ext' +PFunctor.M.head_eq_head' +PFunctor.M.isPath_cons' +Pi.compact_Icc_space' +Pi.continuous_postcomp' +Pi.continuous_precomp' +Pi.cstarRing' +Pi.distribMulAction' +Pi.distribSMul' +pi_Icc_mem_nhds' +pi_Ici_mem_nhds' +pi_Ico_mem_nhds' +pi_Iic_mem_nhds' +pi_Iio_mem_nhds' +Pi.induced_precomp' +Pi.infConvergenceClass' +Pi.instBoundedSMul' +pi_Ioc_mem_nhds' +pi_Ioi_mem_nhds' +pi_Ioo_mem_nhds' +Pi.isometricSMul' +Pi.isometricSMul'' +Pi.isScalarTower' +Pi.isScalarTower'' +Pi.lawfulFix' +Pi.Lex.noMaxOrder' +Pi.module' +Pi.mulAction' +Pi.mulActionWithZero' +Pi.mulDistribMulAction' +pinGroup.star_eq_inv' +pi_nnnorm_const' +pi_nnnorm_const_le' +Pi.nnnorm_def' +pi_nnnorm_le_iff' +pi_nnnorm_lt_iff' +pi_norm_const' +pi_norm_const_le' +Pi.norm_def' +pi_norm_le_iff_of_nonempty' +Pi.orderClosedTopology' +Pi.smul' +Pi.smul_apply' +Pi.smulCommClass' +Pi.smulCommClass'' +Pi.smul_def' +Pi.smulWithZero' +Pi.smulZeroClass' +PiSubtype.canLift' +Pi.supConvergenceClass' +PiTensorProduct.add_tprodCoeff' +PiTensorProduct.distribMulAction' +PiTensorProduct.hasSMul' +PiTensorProduct.isScalarTower' +PiTensorProduct.lift.unique' +PiTensorProduct.module' +PiTensorProduct.smulCommClass' +PiTensorProduct.smul_tprodCoeff' +PiTensorProduct.zero_tprodCoeff' +Pi.uniformContinuous_postcomp' +Pi.uniformContinuous_precomp' +Pi.uniformSpace_comap_precomp' +PNat.coe_toPNat' +PNat.div_add_mod' +PNat.dvd_iff' +PNat.factorMultiset_le_iff' +PNat.find_min' +PNat.gcd_rel_left' +PNat.gcd_rel_right' +PNat.mod_add_div' +PNat.XgcdType.reduce_isReduced' +PNat.XgcdType.reduce_isSpecial' +pNilradical_eq_bot' +Pointed.Hom.comp_toFun' +Pointed.Hom.id_toFun' +Polynomial.add' +Polynomial.addHom_ext' +Polynomial.aeval_apply_smul_mem_of_le_comap' +Polynomial.aeval_eq_sum_range' +Polynomial.as_sum_range' +Polynomial.card_roots' +Polynomial.card_roots_sub_C' +Polynomial.card_support_eq' +Polynomial.card_support_eraseLead' +Polynomial.C_mul' +Polynomial.coeff_expand_mul' +Polynomial.coeff_mul_X_pow' +Polynomial.coeff_restriction' +Polynomial.coeff_toSubring' +Polynomial.coeff_X_pow_mul' +Polynomial.coeff_zero_eq_aeval_zero' +Polynomial.degree_eq_card_roots' +Polynomial.degree_mul' +Polynomial.degree_pow' +Polynomial.div_tendsto_atBot_of_degree_gt' +Polynomial.div_tendsto_atTop_of_degree_gt' +Polynomial.eq_zero_of_natDegree_lt_card_of_eval_eq_zero' +Polynomial.eval₂_comp' +Polynomial.eval₂_eq_sum_range' +Polynomial.eval₂_mul' +Polynomial.eval₂_mul_C' +Polynomial.eval₂_pow' +Polynomial.eval_eq_sum_range' +Polynomial.eval_smul' +Polynomial.exists_root_of_splits' +Polynomial.expand_contract' +Polynomial.hasseDeriv_one' +Polynomial.hasseDeriv_zero' +Polynomial.HasSeparableContraction.dvd_degree' +Polynomial.hermite_eq_deriv_gaussian' +Polynomial.isRoot_cyclotomic_iff' +Polynomial.isUnit_iff' +Polynomial.isUnitTrinomial_iff' +Polynomial.isUnitTrinomial_iff'' +Polynomial.leadingCoeff_add_of_degree_lt' +Polynomial.leadingCoeff_map' +Polynomial.leadingCoeff_mul' +Polynomial.leadingCoeff_pow' +Polynomial.leadingCoeff_sub_of_degree_lt' +Polynomial.lhom_ext' +Polynomial.lt_rootMultiplicity_iff_isRoot_iterate_derivative_of_mem_nonZeroDivisors' +Polynomial.lt_rootMultiplicity_of_isRoot_iterate_derivative_of_mem_nonZeroDivisors' +Polynomial.map_dvd_map' +Polynomial.map_rootOfSplits' +Polynomial.mem_aroots' +Polynomial.mem_roots' +Polynomial.mem_rootSet' +Polynomial.mem_roots_sub_C' +Polynomial.mkDerivation_one_eq_derivative' +PolynomialModule.eval_map' +PolynomialModule.isScalarTower' +Polynomial.Monic.geom_sum' +Polynomial.Monic.irreducible_iff_natDegree' +Polynomial.Monic.natDegree_mul' +Polynomial.monic_zero_iff_subsingleton' +Polynomial.mul' +Polynomial.mul_scaleRoots' +Polynomial.natDegree_eq_card_roots' +Polynomial.natDegree_eq_support_max' +Polynomial.natDegree_mul' +Polynomial.natDegree_pow' +Polynomial.natDegree_removeFactor' +Polynomial.natTrailingDegree_eq_support_min' +Polynomial.natTrailingDegree_mul' +Polynomial.neg' +Polynomial.ringHom_ext' +Polynomial.rootMultiplicity_eq_natTrailingDegree' +Polynomial.rootMultiplicity_mul' +Polynomial.rootMultiplicity_pos' +Polynomial.rootSet_maps_to' +Polynomial.roots_ne_zero_of_splits' +Polynomial.scaleRoots_dvd' +Polynomial.separable_def' +Polynomial.Separable.of_pow' +Polynomial.separable_prod' +Polynomial.separable_prod_X_sub_C_iff' +polynomial_smul_apply' +Polynomial.splits_of_splits_mul' +Polynomial.SplittingField.algebra' +Polynomial.SplittingFieldAux.algebra' +Polynomial.SplittingFieldAux.algebra'' +Polynomial.SplittingFieldAux.algebra''' +Polynomial.SplittingFieldAux.scalar_tower' +Polynomial.sum_add' +Polynomial.sum_smul_index' +Polynomial.support_binomial' +Polynomial.support_C_mul_X' +Polynomial.support_C_mul_X_pow' +Polynomial.support_monomial' +Polynomial.support_trinomial' +Polynomial.taylor_zero' +Polynomial.trailingDegree_mul' +Polynomial.trinomial_leading_coeff' +Polynomial.trinomial_trailing_coeff' +PosNum.cast_one' +PosNum.cast_sub' +PosNum.of_to_nat' +PosNum.one_sub' +PosNum.pred'_succ' +PosNum.succ'_pred' +pow_add_pow_le' +pow_card_eq_one' +pow_eq_zero_iff' +PowerBasis.exists_eq_aeval' +PowerBasis.mem_span_pow' +PowerSeries.algebraMap_apply' +PowerSeries.algebraMap_apply'' +PowerSeries.algebraPolynomial' +PowerSeries.coeff_mul_X_pow' +PowerSeries.coeff_X_pow_mul' +PowerSeries.derivative_inv' +PowerSeries.invOfUnit_eq' +PowerSeries.trunc_derivative' +PowerSeries.trunc_zero' +pow_le_one' +pow_le_pow_iff_right' +pow_le_pow_left' +pow_le_pow_right' +pow_le_pow_right_of_le_one' +pow_lt_one' +pow_lt_pow_iff_right' +pow_lt_pow_left' +pow_lt_pow_right' +pow_mul' +pow_mul_comm' +pow_right_strictMono' +pow_succ' +pow_three' +ppow_mul' +PProd.exists' +PProd.forall' +PredOrder.prelimitRecOn_pred' +preimage_nhdsWithin_coinduced' +PresheafOfModules.sheafificationHomEquiv_hom' +Pretrivialization.apply_symm_apply' +Pretrivialization.coe_fst' +Pretrivialization.continuousLinearMap_symm_apply' +Pretrivialization.ext' +Pretrivialization.mk_proj_snd' +Pretrivialization.proj_symm_apply' +PrimeMultiset.prod_dvd_iff' +PrimeSpectrum.iSup_basicOpen_eq_top_iff' +Primrec₂.nat_iff' +Primrec₂.unpaired' +Primrec.nat_casesOn' +Primrec.nat_omega_rec' +Primrec.nat_rec' +Primrec.vector_get' +Primrec.vector_ofFn' +PrincipalSeg.coe_coe_fn' +ProbabilityTheory.centralMoment_one' +ProbabilityTheory.cgf_const' +ProbabilityTheory.cgf_zero' +ProbabilityTheory.cond_apply' +ProbabilityTheory.cond_cond_eq_cond_inter' +ProbabilityTheory.uniformOn_inter' +ProbabilityTheory.condexp_ae_eq_integral_condexpKernel' +ProbabilityTheory.condexpKernel_ae_eq_condexp' +ProbabilityTheory.CondIndepSets.condIndep' +ProbabilityTheory.cond_mul_eq_inter' +ProbabilityTheory.evariance_def' +ProbabilityTheory.gaussianReal_absolutelyContinuous' +ProbabilityTheory.hasFiniteIntegral_compProd_iff' +ProbabilityTheory.iIndep.iIndepSets' +ProbabilityTheory.IndepFun.integral_mul' +ProbabilityTheory.IndepFun.mgf_add' +ProbabilityTheory.IndepSets.indep' +ProbabilityTheory.IsMarkovKernel.is_probability_measure' +ProbabilityTheory.IsMeasurableRatCDF.stieltjesFunctionAux_def' +ProbabilityTheory.Kernel.borelMarkovFromReal_apply' +ProbabilityTheory.Kernel.comap_apply' +ProbabilityTheory.Kernel.comap_id' +ProbabilityTheory.Kernel.comapRight_apply' +ProbabilityTheory.Kernel.comp_apply' +ProbabilityTheory.Kernel.const_comp' +ProbabilityTheory.Kernel.deterministic_apply' +ProbabilityTheory.Kernel.ext_iff' +ProbabilityTheory.Kernel.finset_sum_apply' +ProbabilityTheory.Kernel.fst_apply' +ProbabilityTheory.Kernel.iIndep.iIndepSets' +ProbabilityTheory.Kernel.IndepSets.indep' +ProbabilityTheory.Kernel.integral_deterministic' +ProbabilityTheory.Kernel.integral_integral_add' +ProbabilityTheory.Kernel.integral_integral_sub' +ProbabilityTheory.Kernel.lintegral_deterministic' +ProbabilityTheory.Kernel.map_apply' +ProbabilityTheory.Kernel.map_id' +ProbabilityTheory.Kernel.measurable_kernel_prod_mk_left' +ProbabilityTheory.Kernel.measure_eq_zero_or_one_of_indepSet_self' +ProbabilityTheory.Kernel.piecewise_apply' +ProbabilityTheory.Kernel.prod_apply' +ProbabilityTheory.Kernel.prodMkLeft_apply' +ProbabilityTheory.Kernel.prodMkRight_apply' +ProbabilityTheory.Kernel.restrict_apply' +ProbabilityTheory.Kernel.rnDeriv_def' +ProbabilityTheory.Kernel.rnDeriv_eq_top_iff' +ProbabilityTheory.Kernel.setIntegral_deterministic' +ProbabilityTheory.Kernel.setLIntegral_deterministic' +ProbabilityTheory.Kernel.snd_apply' +ProbabilityTheory.Kernel.sum_apply' +ProbabilityTheory.Kernel.swapLeft_apply' +ProbabilityTheory.Kernel.swapRight_apply' +ProbabilityTheory.Kernel.withDensity_apply' +ProbabilityTheory.Kernel.withDensity_one' +ProbabilityTheory.Kernel.withDensity_zero' +ProbabilityTheory.lintegral_mul_eq_lintegral_mul_lintegral_of_indepFun'' +ProbabilityTheory.measurable_preCDF' +ProbabilityTheory.mgf_const' +ProbabilityTheory.mgf_pos' +ProbabilityTheory.mgf_zero' +ProbabilityTheory.variance_def' +ProbabilityTheory.variance_smul' +Prod.exists' +Prod.forall' +Prod.isometricSMul' +Prod.isometricSMul'' +Prod.map_apply' +Prod.map_fst' +Prod.map_id' +Prod.map_snd' +prod_mul_tprod_nat_mul' +Profinite.NobelingProof.coe_πs' +Profinite.NobelingProof.contained_C' +Profinite.NobelingProof.injective_πs' +Profinite.NobelingProof.Products.eval_πs' +Profinite.NobelingProof.Products.eval_πs_image' +Profinite.NobelingProof.Products.max_eq_o_cons_tail' +Projectivization.submodule_mk'' +Prop.countable' +QPF.Cofix.bisim' +QPF.liftp_iff' +QPF.recF_eq' +QPF.Wequiv.abs' +quadraticChar_eq_pow_of_char_ne_two' +QuadraticForm.equivalent_weightedSumSquares_units_of_nondegenerate' +QuadraticForm.posDef_of_toMatrix' +QuadraticForm.posDef_toMatrix' +QuadraticMap.isSymm_toMatrix' +QuadraticMap.map_sum' +quasiIsoAt_iff' +quasiIsoAt_iff_exactAt' +QuaternionAlgebra.self_add_star' +QuaternionAlgebra.star_add_self' +Quaternion.normSq_def' +Quaternion.self_add_star' +Quaternion.star_add_self' +Quiver.Hom.unop_op' +Quiver.Path.comp_inj' +QuotientAddGroup.btw_coe_iff' +Quotient.eq' +Quotient.eq'' +Quotient.exact' +QuotientGroup.coe_mk' +QuotientGroup.congr_mk' +QuotientGroup.kerLift_mk' +QuotientGroup.ker_mk' +QuotientGroup.lift_mk' +QuotientGroup.map_mk' +QuotientGroup.mk'_eq_mk' +QuotientGroup.out_eq' +Quotient.hrecOn₂'_mk'' +Quotient.hrecOn'_mk'' +Quotient.liftOn₂'_mk'' +Quotient.liftOn'_mk'' +Quotient.map₂'_mk'' +Quotient.map'_mk'' +quotientMap_quotient_mk' +Quotient.mk_out' +Quotient.out_eq' +Quotient.sound' +Quotient.surjective_liftOn' +range_pow_padicValNat_subset_divisors' +rank_finsupp' +rank_fun' +rank_lt_rank_dual' +Rat.add_def'' +Rat.add_num_den' +Rat.cast_mk' +Rat.div_def' +Rat.divInt_mul_divInt' +Rat.divInt_self' +Rat.floor_def' +RatFunc.liftAlgHom_apply_div' +RatFunc.liftMonoidWithZeroHom_apply_div' +RatFunc.liftRingHom_apply_div' +RatFunc.mk_eq_div' +RatFunc.mk_eq_mk' +RatFunc.mk_one' +RatFunc.num_div' +RatFunc.ofFractionRing_mk' +Rat.instSMulCommClass' +Rat.inv_def' +Rat.inv_divInt' +Rat.le_toNNRat_iff_coe_le' +Rat.mk'_mul_mk' +Rat.mul_num_den' +Rat.normalize_eq_mk' +Rat.sub_def'' +Rat.substr_num_den' +Rat.toNNRat_div' +Rat.toNNRat_lt_toNNRat_iff' +RCLike.hasSum_conj' +RCLike.I_im' +RCLike.normSq_eq_def' +RCLike.zero_re' +Real.arcsin_le_iff_le_sin' +Real.arcsin_lt_iff_lt_sin' +Real.arcsin_sin' +Real.binEntropy_eq_negMulLog_add_negMulLog_one_sub' +Real.b_ne_one' +Real.coe_toNNReal' +Real.continuousAt_const_rpow' +Real.continuous_log' +Real.cosh_sq' +Real.cos_sq' +Real.cos_two_mul' +Real.deriv_cos' +Real.deriv_log' +Real.deriv_rpow_const' +Real.eulerMascheroniConstant_lt_eulerMascheroniSeq' +Real.eulerMascheroniSeq_lt_eulerMascheroniSeq' +Real.exp_approx_end' +Real.exp_bound' +Real.exp_bound_div_one_sub_of_interval' +Real.fourierIntegral_continuousLinearMap_apply' +Real.fourierIntegral_continuousMultilinearMap_apply' +Real.fourierIntegral_eq' +Real.fourierIntegralInv_eq' +Real.hasDerivAt_arctan' +Real.inner_le_Lp_mul_Lq_tsum_of_nonneg' +Real.le_arcsin_iff_sin_le' +Real.le_def' +Real.le_sqrt' +Real.le_toNNReal_iff_coe_le' +Real.list_prod_map_rpow' +Real.logb_nonpos_iff' +Real.log_nonpos_iff' +Real.Lp_add_le_tsum_of_nonneg' +Real.lt_arcsin_iff_sin_lt' +Real.natCastle_toNNReal' +Real.nndist_eq' +Real.rpow_add' +Real.rpow_add_intCast' +Real.rpow_add_natCast' +Real.rpow_add_one' +Real.rpow_le_rpow_of_exponent_ge' +Real.rpow_lt_one_iff' +Real.rpow_one_add' +Real.rpow_one_sub' +Real.rpow_sub' +Real.rpow_sub_intCast' +Real.rpow_sub_natCast' +Real.rpow_sub_one' +Real.sin_arcsin' +Real.sqrt_div' +Real.sqrt_div_self' +Real.sqrt_eq_zero' +Real.sqrt_le_sqrt_iff' +Real.sqrt_lt' +Real.sqrt_mul' +Real.sqrt_ne_zero' +Real.strictAnti_eulerMascheroniSeq' +Real.surjOn_log' +Real.surjOn_logb' +Real.tan_add' +Real.tan_eq_zero_iff' +Real.tendsto_eulerMascheroniSeq' +Real.tendsto_integral_gaussian_smul' +Real.toNNReal_div' +Real.toNNReal_le_toNNReal_iff' +Real.toNNReal_lt_natCast' +Real.toNNReal_lt_toNNReal_iff' +RegularExpression.rmatch_iff_matches' +Relation.ReflTransGen.lift' +Relation.TransGen.closed' +Relation.TransGen.head' +Relation.TransGen.lift' +Relation.TransGen.tail' +RelSeries.last_snoc' +RelSeries.toList_chain' +RightOrdContinuous.map_sInf' +Ring.choose_one_right' +Ring.choose_zero_right' +RingCon.smulCommClass' +RingEquiv.mk_coe' +RingHom.eq_intCast' +RingHom.surjectiveOnStalks_iff_forall_maximal' +Ring.inverse_eq_inv' +Ring.mul_inverse_rev' +Ring.multichoose_one_right' +Ring.multichoose_zero_right' +RingQuot.ringQuot_ext' +RingTheory.Sequence.IsRegular.cons' +RingTheory.Sequence.isRegular_cons_iff' +RingTheory.Sequence.isWeaklyRegular_append_iff' +RingTheory.Sequence.IsWeaklyRegular.cons' +RingTheory.Sequence.isWeaklyRegular_cons_iff' +RootPairing.coroot_eq_coreflection_of_root_eq' +RootPairing.ne_zero' +rootsOfUnity.integer_power_of_ringEquiv' +root_X_pow_sub_C_ne_zero' +SameRay.of_subsingleton' +schnirelmannDensity_congr' +sdiff_eq_self_iff_disjoint' +sdiff_le' +sdiff_le_iff' +sdiff_sdiff_left' +sdiff_sdiff_right' +sdiff_sdiff_sup_sdiff' +sdiff_sup_self' +sdiff_symmDiff' +segment_eq_Icc' +segment_eq_image' +Semigroup.opposite_smulCommClass' +Seminorm.ball_finset_sup' +Seminorm.ball_zero' +Seminorm.closedBall_finset_sup' +Seminorm.closedBall_zero' +Seminorm.coe_sSup_eq' +Seminorm.continuous' +Seminorm.continuousAt_zero' +Seminorm.uniformContinuous' +Semiquot.blur_eq_blur' +Semiquot.mem_blur' +Semiquot.mem_pure' +SeparationQuotient.uniformContinuous_lift' +Set.biInter_and' +Set.biInter_finsetSigma' +Set.biInter_le_succ' +Set.biInter_lt_succ' +Set.biInter_sigma' +Set.bijOn_of_subsingleton' +Set.biUnion_and' +Set.biUnion_finsetSigma' +Set.biUnion_finsetSigma_univ' +Set.biUnion_le_succ' +Set.biUnion_lt_succ' +Set.biUnion_sigma' +SetCoe.exists' +SetCoe.forall' +Set.empty_card' +Set.encard_exchange' +Set.eq_of_mem_uIcc_of_mem_uIcc' +Set.eq_of_mem_uIoc_of_mem_uIoc' +Set.eq_of_nonempty_of_subsingleton' +Set.EqOn.piecewise_ite' +Set.eval_preimage' +Set.exists_intermediate_set' +Set.finite' +Set.finite_diff_iUnion_Ioo' +Set.Finite.eq_of_subset_of_encard_le' +Set.Finite.preimage' +Set.Finite.seq' +Set.Finite.toFinset_insert' +Set.fintypeBind' +Set.fintypeBiUnion' +Set.fintypeSeq' +Set.Icc_mul_Icc_subset' +Set.Icc_mul_Ico_subset' +Set.Icc_subset_uIcc' +Set.Icc_union_Icc' +Set.Icc_union_Ici' +Set.Ici_mul_Ici_subset' +Set.Ici_mul_Ioi_subset' +Set.Ico_mul_Icc_subset' +Set.Ico_mul_Ioc_subset' +Set.Ico_union_Ici' +Set.Ico_union_Ico' +Set.Iic_mul_Iic_subset' +Set.Iic_mul_Iio_subset' +Set.Iic_union_Icc' +Set.Iic_union_Ioc' +Set.iInter₂_mono' +Set.iInter_iInter_eq' +Set.iInter_mono' +Set.iInter_mono'' +Set.iInter_sigma' +Set.Iio_mul_Iic_subset' +Set.Iio_union_Ico' +Set.Iio_union_Ioo' +Set.image_affine_Icc' +Set.image_mul_left' +Set.image_mul_left_Icc' +Set.image_mul_right' +Set.image_mul_right_Icc' +Set.Infinite.preimage' +setIntegral_withDensity_eq_setIntegral_smul₀' +Set.Ioc_mul_Ico_subset' +Set.Ioc_subset_uIoc' +Set.Ioc_union_Ioc' +Set.Ioc_union_Ioi' +Set.Ioi_mul_Ici_subset' +Set.Ioo_union_Ioi' +Set.Ioo_union_Ioo' +Set.isScalarTower' +Set.isScalarTower'' +Set.iUnion₂_mono' +Set.iUnion_iUnion_eq' +Set.iUnion_mono' +Set.iUnion_mono'' +Set.iUnion_sigma' +Set.LeftInvOn.image_image' +Set.LeftInvOn.image_inter' +SetLike.ext' +Set.mapsTo' +Set.mapsTo_of_subsingleton' +Set.mulIndicator_apply_le' +Set.mulIndicator_compl' +Set.mulIndicator_diff' +Set.mulIndicator_div' +Set.mulIndicator_empty' +Set.mulIndicator_eq_one' +Set.mulIndicator_inv' +Set.mulIndicator_le' +Set.mulIndicator_le_mulIndicator' +Set.mulIndicator_le_self' +Set.mulIndicator_mul' +Set.mulIndicator_one' +Set.ncard_eq_toFinset_card' +Set.ncard_exchange' +Set.nonempty_of_ssubset' +Set.Nonempty.preimage' +Setoid.comm' +Setoid.eqv_class_mem' +Setoid.ext' +Setoid.ker_apply_mk_out' +Setoid.refl' +Setoid.symm' +Setoid.trans' +Set.ordConnected_iInter' +Set.OrdConnected.inter' +Set.ordConnected_pi' +Set.PairwiseDisjoint.elim' +Set.Pairwise.mono' +Set.piecewise_mem_Icc' +Set.pi_eq_empty_iff' +Set.PiSetCoe.canLift' +Set.preimage_eq_preimage' +Set.preimage_id' +Set.preimage_mul_left_one' +Set.preimage_mul_right_one' +Set.Quotient.range_mk'' +Set.range_id' +Set.range_ite_subset' +Set.range_quotient_lift_on' +Set.range_quotient_mk' +Set.setOf_eq_eq_singleton' +Set.singleton_pi' +Set.Sized.subsingleton' +Set.smulCommClass_set' +Set.smulCommClass_set'' +Set.smul_inter_ne_empty_iff' +Set.smul_univ₀' +Set.star_inv' +Set.star_mem_centralizer' +Set.surjOn_of_subsingleton' +SetTheory.Game.birthday_neg' +SetTheory.PGame.add_le_add_right' +SetTheory.PGame.Equiv.not_fuzzy' +SetTheory.PGame.Fuzzy.not_equiv' +SetTheory.PGame.LF.not_equiv' +SetTheory.PGame.moveLeft_neg' +SetTheory.PGame.moveLeft_neg_symm' +SetTheory.PGame.moveLeft_nim' +SetTheory.PGame.moveRight_neg' +SetTheory.PGame.moveRight_neg_symm' +SetTheory.PGame.moveRight_nim' +SetTheory.PGame.ofLists_moveLeft' +SetTheory.PGame.ofLists_moveRight' +SetTheory.PGame.relabel_moveLeft' +SetTheory.PGame.relabel_moveRight' +SetTheory.PGame.Subsequent.mk_right' +SetTheory.PGame.zero_lf_inv' +Set.uIcc_subset_uIcc_iff_le' +Set.union_diff_cancel' +Set.WellFoundedOn.mono' +Sigma.exists' +Sigma.forall' +sigma_mk_preimage_image' +SimpleGraph.Adj.ne' +SimpleGraph.cliqueSet_mono' +SimpleGraph.cycleGraph_adj' +SimpleGraph.dart_edge_eq_mk'_iff' +SimpleGraph.FarFromTriangleFree.cliqueFinset_nonempty' +SimpleGraph.Subgraph.connected_iff' +SimpleGraph.Subgraph.Connected.mono' +SimpleGraph.Subgraph.degree_le' +SimpleGraph.TripartiteFromTriangles.Graph.in₀₁_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₀₂_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₁₀_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₁₂_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₂₀_iff' +SimpleGraph.TripartiteFromTriangles.Graph.in₂₁_iff' +SimpleGraph.Walk.coe_support_append' +SimpleGraph.Walk.IsPath.mk' +simple_iff_isSimpleModule' +SimplexCategory.eq_comp_δ_of_not_surjective' +SimplexCategory.eq_σ_comp_of_not_injective' +SimplexCategory.Hom.ext' +SimplexCategory.δ_comp_δ' +SimplexCategory.δ_comp_δ'' +SimplexCategory.δ_comp_δ_self' +SimplexCategory.δ_comp_σ_of_gt' +SimplexCategory.δ_comp_σ_self' +SimplexCategory.δ_comp_σ_succ' +SimplicialObject.Splitting.hom_ext' +SimplicialObject.Splitting.IndexSet.ext' +sInf_eq_iInf' +sInf_image' +skewAdjoint.conjugate' +SlashInvariantForm.slash_action_eqn' +small_biInter' +small_iInter' +small_sInter' +smoothAt_finset_prod' +smooth_finset_prod' +SmoothManifoldWithCorners.mk' +SmoothMap.instSMul' +SmoothMap.module' +SmoothMap.smul_comp' +smoothOn_finset_prod' +SmoothPartitionOfUnity.sum_finsupport' +smoothWithinAt_finset_prod' +smul_ball'' +smul_closedBall' +smul_closedBall'' +SMulCommClass.nnrat' +SMulCommClass.rat' +smul_div' +smul_eq_smul_iff_eq_and_eq_of_pos' +smul_finprod' +smul_inv' +smul_left_injective' +smul_le_smul' +smul_lt_smul' +smul_lt_smul_of_le_of_lt' +smul_lt_smul_of_lt_of_le' +smul_mul' +smul_nonneg' +smul_pos' +smul_pow' +smul_sphere' +spec' +SpectralMap.coe_comp_continuousMap' +spinGroup.star_eq_inv' +sq_le_sq' +sq_lt_sq' +sSup_eq_bot' +sSup_eq_iSup' +sSup_image' +StarAlgHom.coe_mk' +star_comm_self' +StarConvex.sub' +star_inv' +Stream' +Stream'.drop_tail' +Stream'.get_succ_iterate' +Stream'.Seq1.map_join' +Stream'.tail_drop' +Stream'.take_succ' +StrictAnti.const_mul' +StrictAnti.ite' +StrictAnti.mul_const' +StrictAntiOn.const_mul' +StrictAntiOn.mul_const' +StrictMono.const_mul' +StrictMono.ite' +StrictMono.mul_const' +StrictMonoOn.const_mul' +StrictMonoOn.mul_const' +StrictWeakOrder.not_lt_of_equiv' +String.LT' +StructureGroupoid.LocalInvariantProp.congr' +StructureGroupoid.LocalInvariantProp.congr_nhdsWithin' +StructureGroupoid.LocalInvariantProp.liftPropWithinAt_inter' +Subalgebra.algebra' +Subalgebra.coe_valA' +Subalgebra.module' +Subbimodule.smul_mem' +sub_div' +Subgroup.center_eq_infi' +Subgroup.comap_equiv_eq_map_symm' +Subgroup.commutator_def' +Subgroup.disjoint_def' +Subgroup.eq_top_iff' +Subgroup.finiteIndex_iInf' +Subgroup.map_equiv_eq_comap_symm' +Subgroup.map_le_map_iff' +Subgroup.mem_normalizer_iff' +Subgroup.mem_normalizer_iff'' +Subgroup.mem_sup' +Subgroup.Normal.conj_mem' +Subgroup.quotient_finite_of_isOpen' +Subgroup.smul_diff' +Subgroup.smul_diff_smul' +Subgroup.smul_opposite_image_mul_preimage' +Subgroup.transferTransversal_apply' +Subgroup.transferTransversal_apply'' +Sublattice.coe_inf' +SubmoduleClass.module' +Submodule.coe_continuous_linearProjOfClosedCompl' +Submodule.coe_prodEquivOfIsCompl' +Submodule.coe_subtypeL' +Submodule.comap_smul' +Submodule.disjoint_def' +Submodule.disjoint_span_singleton' +Submodule.eq_top_iff' +Submodule.hasSMul' +Submodule.inhabited' +Submodule.isScalarTower' +Submodule.ker_liftQ_eq_bot' +Submodule.le_sInf' +Submodule.linearProjOfIsCompl_apply_right' +Submodule.map_smul' +Submodule.map_smul'' +Submodule.map_toAddSubmonoid' +Submodule.mem_annihilator' +Submodule.mem_colon' +Submodule.mem_ideal_smul_span_iff_exists_sum' +Submodule.mem_localized' +Submodule.mem_span_insert' +Submodule.mem_sup' +Submodule.module' +Submodule.orderIsoMapComap_apply' +Submodule.orderIsoMapComap_symm_apply' +Submodule.Quotient.distribMulAction' +Submodule.Quotient.distribSMul' +Submodule.Quotient.eq' +Submodule.Quotient.instSMul' +Submodule.Quotient.mk'_eq_mk' +Submodule.Quotient.module' +Submodule.Quotient.mulAction' +Submodule.Quotient.smulZeroClass' +Submodule.sInf_le' +Submodule.smul_mem_iff' +Submodule.smul_mem_span_smul' +Submodule.span_image' +Submodule.unique' +Submonoid.disjoint_def' +Submonoid.eq_top_iff' +Submonoid.LocalizationMap.eq' +Submonoid.LocalizationMap.map_mk' +Submonoid.LocalizationMap.mk'_eq_iff_eq' +Submonoid.LocalizationMap.mk'_eq_of_eq' +Submonoid.LocalizationMap.mk'_self' +Submonoid.LocalizationMap.mk'_spec' +Submonoid.LocalizationMap.mulEquivOfMulEquiv_mk' +Submonoid.LocalizationMap.mul_mk'_one_eq_mk' +Submonoid.LocalizationMap.sec_spec' +Submonoid.LocalizationMap.symm_comp_ofMulEquivOfLocalizations_apply' +Submonoid.mrange_inl' +Submonoid.mrange_inr' +SubMulAction.isScalarTower' +SubMulAction.mem_one' +SubMulAction.smul' +SubMulAction.smul_mem_iff' +Subring.closure_induction' +Subring.coe_mk' +Subring.eq_top_iff' +Subring.mem_mk' +Subsemigroup.eq_top_iff' +Subsemiring.closure_induction' +Subsemiring.coe_mk' +Subsemiring.eq_top_iff' +Subsemiring.mem_mk' +subset_interior_mul' +Subsingleton.antitone' +Subsingleton.monotone' +sub_sq' +Subtype.preimage_coe_compl' +SuccOrder.prelimitRecOn_succ' +suffixLevenshtein_nil' +sum_bernoulli' +summable_geometric_two' +Summable.matrix_blockDiag' +summable_matrix_blockDiagonal' +Summable.matrix_blockDiagonal' +summable_mul_of_summable_norm' +summable_of_isBigO' +summable_of_isBigO_nat' +summable_star_iff' +summable_sum_mul_antidiagonal_of_summable_norm' +summable_sum_mul_range_of_summable_norm' +sup_eq_half_smul_add_add_abs_sub' +sup_sdiff_cancel' +Surreal.dyadicMap_apply_pow' +Surreal.nsmul_pow_two_powHalf' +Sym2.instDecidableRel' +Sym2.mem_iff' +Sym2.other_eq_other' +Sym2.other_invol' +Sym2.other_mem' +Sym2.other_spec' +Sym2.rel_iff' +Sym.inhabitedSym' +symmDiff_eq' +symmDiff_eq_Xor' +symmDiff_symmDiff_right' +symmDiff_symmDiff_self' +symmDiff_top' +SymplecticGroup.coe_inv' +SymplecticGroup.mem_iff' +t0Space_iff_uniformity' +Tactic.NormNum.int_gcd_helper' +Tactic.NormNum.nat_gcd_helper_1' +Tactic.NormNum.nat_gcd_helper_2' +tendsto_ceil_left' +tendsto_ceil_right' +tendsto_const_mul_pow_nhds_iff' +tendsto_floor_left' +tendsto_floor_right' +tendsto_fract_left' +tendsto_fract_right' +tendsto_gauge_nhds_zero' +tendsto_indicator_const_apply_iff_eventually' +tendsto_indicator_const_iff_forall_eventually' +tendsto_indicator_const_iff_tendsto_pi_pure' +tendsto_measure_Icc_nhdsWithin_right' +tendsto_nhds_bot_mono' +tendsto_nhds_top_mono' +tendsto_nhds_unique' +tendsto_norm' +tendsto_norm_atTop_iff_cobounded' +tendsto_norm_cobounded_atTop' +tendsto_norm_cocompact_atTop' +tendsto_norm_zero' +TensorProduct.ext' +TensorProduct.finsuppLeft_smul' +TensorProduct.isPushout' +TensorProduct.lift.tmul' +TensorProduct.smul_tmul' +Theorems100.«82».Cube.hw' +Theorems100.num_series' +three_ne_zero' +toIcoDiv_add_left' +toIcoDiv_add_right' +toIcoDiv_add_zsmul' +toIcoDiv_neg' +toIcoDiv_sub' +toIcoDiv_sub_eq_toIcoDiv_add' +toIcoDiv_sub_zsmul' +toIcoMod_add_left' +toIcoMod_add_right' +toIcoMod_add_zsmul' +toIcoMod_mem_Ico' +toIcoMod_neg' +toIcoMod_sub' +toIcoMod_sub_zsmul' +toIcoMod_zsmul_add' +toIocDiv_add_left' +toIocDiv_add_right' +toIocDiv_add_zsmul' +toIocDiv_neg' +toIocDiv_sub' +toIocDiv_sub_eq_toIocDiv_add' +toIocDiv_sub_zsmul' +toIocMod_add_left' +toIocMod_add_right' +toIocMod_add_zsmul' +toIocMod_neg' +toIocMod_sub' +toIocMod_sub_zsmul' +toIocMod_zsmul_add' +toIxxMod_total' +TopCat.GlueData.preimage_image_eq_image' +TopCat.openEmbedding_iff_comp_isIso' +TopCat.openEmbedding_iff_isIso_comp' +TopCat.Presheaf.germ_stalkSpecializes' +TopCat.Presheaf.pushforward_eq' +TopCat.Presheaf.pushforward_map_app' +TopologicalGroup.of_nhds_one' +TopologicalSpace.OpenNhds.map_id_obj' +TopologicalSpace.Opens.coe_inclusion' +TopologicalSpace.Opens.map_comp_obj' +TopologicalSpace.Opens.map_functor_eq' +TopologicalSpace.Opens.map_id_obj' +TopologicalSpace.Opens.openEmbedding' +TopologicalSpace.Opens.set_range_forget_map_inclusion' +TopologicalSpace.SecondCountableTopology.mk' +Topology.WithScott.isOpen_iff_isUpperSet_and_scottHausdorff_open' +top_sdiff' +top_symmDiff' +toSubalgebra_toIntermediateField' +T_pow' +tprod_comm' +tprod_eq_prod' +tprod_eq_zero_mul' +tprod_le_of_prod_le' +tprod_prod' +tprod_sigma' +Traversable.map_traverse' +Traversable.naturality' +Traversable.traverse_eq_map_id' +Traversable.traverse_map' +Trivialization.apply_symm_apply' +Trivialization.coe_coordChangeL' +Trivialization.coe_fst' +Trivialization.coe_fst_eventuallyEq_proj' +Trivialization.continuousLinearEquivAt_apply' +Trivialization.ext' +Trivialization.mk_proj_snd' +Trivialization.proj_symm_apply' +TrivSqZeroExt.algebra' +TrivSqZeroExt.algebraMap_eq_inl' +TrivSqZeroExt.algHom_ext' +TrivSqZeroExt.snd_pow_of_smul_comm' +TruncatedWittVector.commutes' +TruncatedWittVector.commutes_symm' +tsum_choose_mul_geometric_of_norm_lt_one' +tsum_geometric_two' +tsum_mul_tsum_eq_tsum_sum_antidiagonal_of_summable_norm' +tsum_mul_tsum_eq_tsum_sum_range_of_summable_norm' +tsum_mul_tsum_of_summable_norm' +Tuple.proj_equiv₁' +Turing.PartrecToTM2.trStmts₁_supports' +Turing.Reaches₀.tail' +Turing.Tape.exists_mk' +Turing.Tape.map_mk' +Turing.Tape.move_left_mk' +Turing.Tape.move_right_mk' +Turing.Tape.write_mk' +Turing.TM1to1.trTape_mk' +Turing.tr_eval' +two_ne_zero' +TwoSidedIdeal.mem_mk' +TypeVec.appendFun_comp' +TypeVec.drop_append1' +TypeVec.dropFun_RelLast' +TypeVec.subtypeVal_toSubtype' +TypeVec.toSubtype'_of_subtype' +ULift.distribMulAction' +ULift.distribSMul' +ULift.isometricSMul' +ULift.isScalarTower' +ULift.isScalarTower'' +ULift.module' +ULift.mulAction' +ULift.mulActionWithZero' +ULift.mulDistribMulAction' +ULift.smulWithZero' +ULift.smulZeroClass' +Ultrafilter.le_of_inf_neBot' +Ultrafilter.map_id' +UniformCauchySeqOn.prod' +uniformContinuous_comap' +UniformContinuous.const_mul' +uniformContinuous_div_const' +UniformContinuous.div_const' +UniformContinuous.mul_const' +uniformContinuous_mul_left' +uniformContinuous_mul_right' +uniformContinuous_nnnorm' +uniformContinuous_norm' +isUniformEmbedding_iff' +UniformGroup.mk' +isUniformInducing_iff' +IsUniformInducing.mk' +uniformity_basis_edist' +uniformity_basis_edist_le' +uniformity_eq_comap_nhds_one' +UniformSpace.Completion.ext' +unique' +uniqueDiffWithinAt_inter' +UniqueDiffWithinAt.inter' +UniqueFactorizationMonoid.exists_reduced_factors' +UniqueMDiffWithinAt.inter' +UniqueMDiffWithinAt.smooth_bundle_preimage' +Unique.subsingleton_unique' +Unique.subtypeEq' +unitary.star_eq_inv' +Unitization.algHom_ext'' +Unitization.quasispectrum_eq_spectrum_inr' +Units.coe_map' +Units.conj_pow' +Units.inv_mul' +Units.mul_inv' +UniversalEnvelopingAlgebra.lift_ι_apply' +update_le_update_iff' +upperClosure_interior_subset' +UpperHalfPlane.cosh_dist' +UpperHalfPlane.ext_iff' +UpperHalfPlane.ModularGroup.det_coe' +UpperHalfPlane.mul_smul' +UV.compress_of_disjoint_of_le' +Valuation.Integers.one_of_isUnit' +Valuation.map_add' +Valuation.map_sum_lt' +ValuationSubring.isIntegral_of_mem_ringOfIntegers' +Vector.continuous_insertNth' +VitaliFamily.ae_tendsto_lintegral_div' +volume_regionBetween_eq_integral' +volume_regionBetween_eq_lintegral' +WCovBy.of_le_of_le' +WeakBilin.instModule' +WeakSpace.instModule' +WeierstrassCurve.Affine.CoordinateRing.mk_XYIdeal'_mul_mk_XYIdeal' +WeierstrassCurve.Affine.equation_iff' +WeierstrassCurve.Affine.nonsingular_iff' +WeierstrassCurve.Affine.Point.add_of_X_ne' +WeierstrassCurve.Affine.Point.add_of_Y_ne' +WeierstrassCurve.Affine.Point.add_self_of_Y_ne' +WeierstrassCurve.baseChange_preΨ' +WeierstrassCurve.coeff_preΨ' +WeierstrassCurve.Jacobian.add_of_Y_ne' +WeierstrassCurve.Jacobian.addX_eq' +WeierstrassCurve.Jacobian.addX_of_X_eq' +WeierstrassCurve.Jacobian.addY_of_X_eq' +WeierstrassCurve.Jacobian.dblXYZ_of_Y_eq' +WeierstrassCurve.Jacobian.dblZ_ne_zero_of_Y_ne' +WeierstrassCurve.Jacobian.equiv_iff_eq_of_Z_eq' +WeierstrassCurve.Jacobian.isUnit_dblZ_of_Y_ne' +WeierstrassCurve.Jacobian.negAddY_eq' +WeierstrassCurve.Jacobian.negAddY_of_X_eq' +WeierstrassCurve.Jacobian.neg_of_Z_eq_zero' +WeierstrassCurve.Jacobian.Y_eq_iff' +WeierstrassCurve.Jacobian.Y_eq_of_Y_ne' +WeierstrassCurve.Jacobian.Y_ne_negY_of_Y_ne' +WeierstrassCurve.leadingCoeff_preΨ' +WeierstrassCurve.map_preΨ' +WeierstrassCurve.natDegree_coeff_preΨ' +WeierstrassCurve.natDegree_preΨ' +WeierstrassCurve.Projective.addX_eq' +WeierstrassCurve.Projective.addY_of_X_eq' +WeierstrassCurve.Projective.addZ_eq' +WeierstrassCurve.Projective.dblX_eq' +WeierstrassCurve.Projective.dblY_of_Y_eq' +WeierstrassCurve.Projective.dblZ_ne_zero_of_Y_ne' +WeierstrassCurve.Projective.equiv_iff_eq_of_Z_eq' +WeierstrassCurve.Projective.isUnit_dblZ_of_Y_ne' +WeierstrassCurve.Projective.negAddY_eq' +WeierstrassCurve.Projective.negAddY_of_X_eq' +WeierstrassCurve.Projective.negDblY_eq' +WeierstrassCurve.Projective.negDblY_of_Y_eq' +WeierstrassCurve.Projective.Y_eq_iff' +WeierstrassCurve.Projective.Y_eq_of_Y_ne' +WeierstrassCurve.Projective.Y_ne_negY_of_Y_ne' +WellFounded.monotone_chain_condition' +WfDvdMonoid.max_power_factor' +WithBot.bot_mul' +WithBot.coe_sInf' +WithBot.coe_sSup' +WithBot.le_coe_unbot' +WithBot.mul_bot' +WithBot.unbot_one' +WithTop.coe_sInf' +WithTop.coe_sSup' +WithTop.distrib' +WithTop.mul_top' +WithTop.top_mul' +WithTop.untop_one' +WithZero.map'_map' +WittVector.aeval_verschiebung_poly' +WittVector.exists_eq_pow_p_mul' +WittVector.idIsPolyI' +WittVector.nth_mul_coeff' +WittVector.poly_eq_of_wittPolynomial_bind_eq' +WittVector.RecursionBase.solution_spec' +WittVector.RecursionMain.succNthVal_spec' +WittVector.truncate_mk' +WriterT.callCC' +WriterT.goto_mkLabel' +WriterT.mkLabel' +WType.cardinal_mk_eq_sum' +WType.WType' +Xor' +xor_iff_not_iff' +X_pow_sub_C_eq_prod' +zero_le' +zero_lt_one_add_norm_sq' +zero_mem_ℓp' +zero_ne_one' +ZFSet.IsTransitive.sUnion' +ZMod.cast_add' +ZMod.cast_id' +ZMod.cast_intCast' +ZMod.cast_mul' +ZMod.cast_natCast' +ZMod.cast_one' +ZMod.cast_pow' +ZMod.cast_sub' +ZMod.intCast_eq_intCast_iff' +ZMod.invDFT_apply' +ZMod.invDFT_def' +ZMod.natCast_eq_natCast_iff' +ZMod.natCast_self' +ZMod.neg_val' +ZMod.nontrivial' +ZMod.val_mul' +ZMod.val_neg' +ZMod.val_one' +ZMod.val_one'' +ZMod.val_unit' +ZNum.cast_zero' +ZNum.of_to_int' +zpow_add' +zpow_eq_zpow_emod' +zpow_le_zpow' +zpow_le_zpow_iff' +zpow_lt_zpow' +zpow_lt_zpow_iff' +zpow_mul' +zsmul_eq_mul' +Zsqrtd.norm_eq_one_iff' diff --git a/scripts/nolints.json b/scripts/nolints.json index c85078ae6db23..8b556db384b5e 100644 --- a/scripts/nolints.json +++ b/scripts/nolints.json @@ -23,7 +23,6 @@ ["docBlame", "RightInverse"], ["docBlame", "Writer"], ["docBlame", "WriterT"], - ["docBlame", "Zero"], ["docBlame", "cancelDenominators"], ["docBlame", "cancelDenominatorsAt"], ["docBlame", "cancelDenominatorsTarget"], @@ -85,8 +84,6 @@ ["docBlame", "Combinator.I"], ["docBlame", "Combinator.K"], ["docBlame", "Combinator.S"], - ["docBlame", "CommRingCat.forget_obj_eq_coe"], - ["docBlame", "CommSemiRingCat.forget_obj_eq_coe"], ["docBlame", "CompleteBooleanAlgebra.toCompleteAtomicBooleanAlgebra"], ["docBlame", "Computation.parallelRec"], ["docBlame", "Congr!.elabConfig"], @@ -285,7 +282,6 @@ ["docBlame", "PowerBasis.basis"], ["docBlame", "PowerBasis.dim"], ["docBlame", "PowerBasis.gen"], - ["docBlame", "PresheafOfModules.presheaf"], ["docBlame", "Pretrivialization.baseSet"], ["docBlame", "PrimeSpectrum.asIdeal"], ["docBlame", "ProbabilityTheory.«termEVar[_]»"], @@ -314,13 +310,11 @@ ["docBlame", "ReaderT.callCC"], ["docBlame", "ReaderT.mk"], ["docBlame", "ReaderT.mkLabel"], - ["docBlame", "RingCat.forget_obj_eq_coe"], ["docBlame", "RingQuot.preLift"], ["docBlame", "RingQuot.preLiftAlgHom"], ["docBlame", "RingQuot.toQuot"], ["docBlame", "RootableBy.root"], ["docBlame", "SchwartzMap.toFun"], - ["docBlame", "SemiRingCat.forget_obj_eq_coe"], ["docBlame", "Semigrp.forget_obj_eq_coe"], ["docBlame", "Shrink.rec"], ["docBlame", "SlashAction.map"], @@ -375,7 +369,6 @@ ["docBlame", "WriterT.mkLabel'"], ["docBlame", "WriterT.run"], ["docBlame", "WriterT.runThe"], - ["docBlame", "Zero.zero"], ["docBlame", "Zsqrtd.im"], ["docBlame", "Zsqrtd.re"], ["docBlame", "algebraMap.coeHTCT"], @@ -543,7 +536,6 @@ ["docBlame", "Order.PFilter.dual"], ["docBlame", "PProd.mk.injArrow"], ["docBlame", "PicardLindelof.FunSpace.toFun"], - ["docBlame", "PresheafOfModules.Hom.hom"], ["docBlame", "Prod.mk.injArrow"], ["docBlame", "QuaternionAlgebra.Basis.i"], ["docBlame", "QuaternionAlgebra.Basis.j"], @@ -716,10 +708,6 @@ ["docBlame", "Mathlib.Command.Variable.variable?.maxSteps"], ["docBlame", "Mathlib.Meta.NormNum.evalEq.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalEq.ratArm"], - ["docBlame", "Mathlib.Meta.NormNum.evalLE.intArm"], - ["docBlame", "Mathlib.Meta.NormNum.evalLE.ratArm"], - ["docBlame", "Mathlib.Meta.NormNum.evalLT.intArm"], - ["docBlame", "Mathlib.Meta.NormNum.evalLT.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMinFac.aux"], ["docBlame", "Mathlib.Meta.NormNum.evalMinFac.core"], ["docBlame", "Mathlib.Meta.NormNum.evalNatPrime.core"], @@ -753,6 +741,10 @@ ["docBlame", "Mathlib.Tactic.Says.says.verify"], ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalAdd.core.ratArm"], + ["docBlame", "Mathlib.Meta.NormNum.evalLE.core.intArm"], + ["docBlame", "Mathlib.Meta.NormNum.evalLE.core.ratArm"], + ["docBlame", "Mathlib.Meta.NormNum.evalLT.core.intArm"], + ["docBlame", "Mathlib.Meta.NormNum.evalLT.core.ratArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.intArm"], ["docBlame", "Mathlib.Meta.NormNum.evalMul.core.ratArm"], - ["unusedArguments", "Combinator.K"]] \ No newline at end of file + ["unusedArguments", "Combinator.K"]] diff --git a/scripts/noshake.json b/scripts/noshake.json index f7776819fcd27..6448419d87171 100644 --- a/scripts/noshake.json +++ b/scripts/noshake.json @@ -194,7 +194,8 @@ "ignoreAll": ["Batteries.Tactic.Basic", "Mathlib.Mathport.Syntax", "Mathlib.Tactic.Linter"], "ignore": - {"Mathlib.Topology.Sheaves.Forget": ["Mathlib.Algebra.Category.Ring.Limits"], + {"Mathlib.Topology.UniformSpace.Basic": ["Mathlib.Tactic.Monotonicity.Basic"], + "Mathlib.Topology.Sheaves.Forget": ["Mathlib.Algebra.Category.Ring.Limits"], "Mathlib.Topology.Order.LeftRightNhds": ["Mathlib.Algebra.Ring.Pointwise.Set"], "Mathlib.Topology.Germ": ["Mathlib.Analysis.Normed.Module.Basic"], @@ -240,8 +241,7 @@ ["Mathlib.Tactic.LinearCombination.Lemmas"], "Mathlib.Tactic.Lemma": ["Lean.Parser.Command"], "Mathlib.Tactic.IrreducibleDef": ["Mathlib.Data.Subtype"], - "Mathlib.Tactic.ITauto": - ["Batteries.Tactic.Init", "Mathlib.Logic.Basic"], + "Mathlib.Tactic.ITauto": ["Batteries.Tactic.Init", "Mathlib.Logic.Basic"], "Mathlib.Tactic.Group": ["Mathlib.Algebra.Group.Commutator"], "Mathlib.Tactic.GCongr.Core": ["Mathlib.Order.Defs"], "Mathlib.Tactic.GCongr": ["Mathlib.Tactic.Positivity.Core"], @@ -302,11 +302,18 @@ "Mathlib.Tactic.Basic": ["Mathlib.Tactic.Linter.OldObtain"], "Mathlib.Tactic.Attr.Register": ["Lean.Meta.Tactic.Simp.SimpTheorems"], "Mathlib.Tactic.ArithMult": ["Mathlib.Tactic.ArithMult.Init"], + "Mathlib.Tactic.Algebraize": ["Mathlib.Algebra.Algebra.Tower"], "Mathlib.RingTheory.PowerSeries.Basic": ["Mathlib.Algebra.CharP.Defs", "Mathlib.Tactic.MoveAdd"], "Mathlib.RingTheory.PolynomialAlgebra": ["Mathlib.Data.Matrix.DMatrix"], "Mathlib.RingTheory.MvPolynomial.Homogeneous": ["Mathlib.Algebra.DirectSum.Internal"], + "Mathlib.RingTheory.KrullDimension.Basic": + ["Mathlib.Algebra.MvPolynomial.CommRing", "Mathlib.Algebra.Polynomial.Basic"], + "Mathlib.RingTheory.IntegralClosure.IsIntegral.Defs": + ["Mathlib.Tactic.Algebraize"], + "Mathlib.RingTheory.Finiteness": + ["Mathlib.Algebra.Algebra.RestrictScalars", "Mathlib.Tactic.Algebraize"], "Mathlib.RingTheory.Binomial": ["Mathlib.Algebra.Order.Floor"], "Mathlib.RepresentationTheory.FdRep": ["Mathlib.CategoryTheory.Monoidal.Rigid.Braided"], @@ -358,13 +365,13 @@ ["Batteries.Data.Nat.Lemmas", "Mathlib.Data.List.Basic"], "Mathlib.Data.List.Lemmas": ["Mathlib.Data.List.InsertNth"], "Mathlib.Data.List.Defs": ["Batteries.Data.RBMap.Basic"], - "Mathlib.Data.List.Basic": ["Mathlib.Data.Option.Basic"], + "Mathlib.Data.List.Basic": + ["Mathlib.Control.Basic", "Mathlib.Data.Option.Basic"], "Mathlib.Data.LazyList.Basic": ["Mathlib.Lean.Thunk"], "Mathlib.Data.Int.Order.Basic": ["Mathlib.Data.Int.Notation"], "Mathlib.Data.Int.Defs": ["Batteries.Data.Int.Order"], "Mathlib.Data.FunLike.Basic": ["Mathlib.Logic.Function.Basic"], "Mathlib.Data.Finset.Basic": ["Mathlib.Data.Finset.Attr"], - "Mathlib.Data.DFinsupp.Notation": ["Mathlib.Data.Finsupp.Notation"], "Mathlib.Data.ByteArray": ["Batteries.Data.ByteSubarray"], "Mathlib.Data.Bool.Basic": ["Batteries.Tactic.Init"], "Mathlib.Control.Traversable.Instances": ["Mathlib.Control.Applicative"], @@ -382,13 +389,13 @@ ["Mathlib.CategoryTheory.Limits.Shapes.Pullback.HasPullback", "Mathlib.CategoryTheory.Limits.Shapes.Pullbacks"], "Mathlib.CategoryTheory.Limits.IsLimit": ["Batteries.Tactic.Congr"], - "Mathlib.CategoryTheory.Bicategory.Adjunction": - ["Mathlib.Tactic.CategoryTheory.Bicategory.Basic"], + "Mathlib.CategoryTheory.Category.Basic": ["Mathlib.Tactic.StacksAttribute"], "Mathlib.CategoryTheory.Bicategory.Functor.Oplax": ["Mathlib.Tactic.CategoryTheory.ToApp"], "Mathlib.CategoryTheory.Bicategory.Functor.Lax": ["Mathlib.Tactic.CategoryTheory.ToApp"], - "Mathlib.CategoryTheory.Category.Basic": ["Mathlib.Tactic.StacksAttribute"], + "Mathlib.CategoryTheory.Bicategory.Adjunction": + ["Mathlib.Tactic.CategoryTheory.Bicategory.Basic"], "Mathlib.Analysis.Normed.Operator.LinearIsometry": ["Mathlib.Algebra.Star.Basic"], "Mathlib.Analysis.InnerProductSpace.Basic": diff --git a/scripts/polyrith_sage.py b/scripts/polyrith_sage.py index 42f7f58ccc7fd..9833e5923864e 100644 --- a/scripts/polyrith_sage.py +++ b/scripts/polyrith_sage.py @@ -1,10 +1,13 @@ # This file is part of the `polyrith` tactic in `src/tactic/polyrith.lean`. # It interfaces between Lean and the Sage web interface. -import requests import json -import sys from os.path import join, dirname +import sys +from typing import Dict, Any +import urllib.error +import urllib.parse +import urllib.request # These functions are used to format the output of Sage for parsing in Lean. # They are stored here as a string since they are passed to Sage via the web API. @@ -59,15 +62,19 @@ def __init__(self, ename, evalue, message='Error in Sage communication'): self.message = message super().__init__(self.message) -def parse_response(resp: str) -> str: +def parse_response(resp: str) -> Dict[str, Any]: exp, data = resp.split(';', 1) return dict(power=int(exp), coeffs=json.loads(data)) -def evaluate_in_sage(query: str) -> str: - data = {'code': query} - headers = {'content-type': 'application/x-www-form-urlencoded'} - response = requests.post('https://sagecell.sagemath.org/service', data, headers=headers).json() +def evaluate_in_sage(query: str) -> Dict[str, Any]: + data = urllib.parse.urlencode({'code': query}).encode('utf-8') + headers = {'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': 'LeanProver (https://leanprover-community.github.io/)'} + req = urllib.request.Request('https://sagecell.sagemath.org/service', data=data, headers=headers) + with urllib.request.urlopen(req) as response: + response_data = response.read().decode() + response = json.loads(response_data) if response['success']: return parse_response(response.get('stdout')) elif 'execute_reply' in response and 'ename' in response['execute_reply'] and 'evalue' in response['execute_reply']: diff --git a/scripts/technical-debt-metrics.sh b/scripts/technical-debt-metrics.sh index acf261f75f01b..ce9a3a5202b16 100755 --- a/scripts/technical-debt-metrics.sh +++ b/scripts/technical-debt-metrics.sh @@ -52,8 +52,8 @@ printf '%s|%s\n' "$(grep -c 'docBlame' scripts/nolints.json)" "documentation nol # We count the number of large files, making sure to avoid counting the test file `test/Lint.lean`. printf '%s|%s\n' "$(git grep '^set_option linter.style.longFile [0-9]*' Mathlib | wc -l)" "large files" printf '%s|%s\n' "$(git grep "^open .*Classical" | grep -v " in$" -c)" "bare open (scoped) Classical" -# We print the number of files, not the number of matches --- hence, the nested grep. -printf '%s|%s\n' "$(git grep -c 'autoImplicit true' | grep -c -v 'test')" "non-test files with autoImplicit true" + +printf '%s|%s\n' "$(wc -l < scripts/no_lints_prime_decls.txt)" "exceptions for the docPrime linter" deprecatedFiles="$(git ls-files '**/Deprecated/*.lean' | xargs wc -l | sed 's=^ *==')" diff --git a/test/CategoryTheory/Elementwise.lean b/test/CategoryTheory/Elementwise.lean index c28cc0073a784..4b8056c788b1f 100644 --- a/test/CategoryTheory/Elementwise.lean +++ b/test/CategoryTheory/Elementwise.lean @@ -92,7 +92,7 @@ lemma bar''' {M N K : MonCat} {f : M ⟶ N} {g : N ⟶ K} {h : M ⟶ K} (w : f g (f x) = h x := by apply foo_apply w example (M N K : MonCat) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : - g (f m) = h m := by erw [elementwise_of% w]; rfl -- Porting note: was `rw`, switched to `erw; rfl` + g (f m) = h m := by rw [elementwise_of% w] example (M N K : MonCat) (f : M ⟶ N) (g : N ⟶ K) (h : M ⟶ K) (w : f ≫ g = h) (m : M) : g (f m) = h m := by diff --git a/test/Continuity.lean b/test/Continuity.lean index 7df66051c1b4e..bf0d389a95e2a 100644 --- a/test/Continuity.lean +++ b/test/Continuity.lean @@ -1,6 +1,6 @@ import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic import Mathlib.Topology.Basic -import Mathlib.Topology.ContinuousFunction.Basic +import Mathlib.Topology.ContinuousMap.Basic set_option autoImplicit true section basic @@ -45,7 +45,7 @@ example : Continuous (fun x : ℝ => exp ((max x (-x)) + sin x)^2) := by example : Continuous (fun x : ℝ => exp ((max x (-x)) + sin (cos x))^2) := by continuity --- Examples taken from `Topology.ContinuousFunction.Basic`: +-- Examples taken from `Topology.ContinuousMap.Basic`: example (b : Y) : Continuous (fun _ : X => b) := by continuity @@ -53,8 +53,7 @@ example (f : C(X, Y)) (g : C(Y, Z)) : Continuous (g ∘ f) := by continuity example (f : C(X, Y)) (g : C(X, Z)) : Continuous (fun x => (f x, g x)) := by continuity -example (f : C(X, Y)) (g : C(W, Z)) : Continuous (Prod.map f g) := --by continuity - f.continuous.prod_map g.continuous +example (f : C(X, Y)) (g : C(W, Z)) : Continuous (Prod.map f g) := by continuity example (f : ∀ i, C(X, X' i)) : Continuous (fun a i => f i a) := by continuity diff --git a/test/DocPrime.lean b/test/DocPrime.lean new file mode 100644 index 0000000000000..3809fa9675e65 --- /dev/null +++ b/test/DocPrime.lean @@ -0,0 +1,80 @@ +import Mathlib.Tactic.Linter.DocPrime +import Mathlib.Tactic.Lemma + +set_option linter.docPrime true + +-- no warning on a primed-declaration with a doc-string containing `'` +/-- X' has a doc-string -/ +def X' := 0 + +-- no warning on a declaration whose name contains a `'` *and does not end with it* +def X'X := 0 + +-- A list of universe names in the declaration is handled correctly, i.e. warns. +/-- +warning: `Y'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +def Y'.{u} := ULift.{u} Nat + +namespace X +/-- +warning: `ABC.thm_no_doc1'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem _root_.ABC.thm_no_doc1' : True := .intro + +/-- +warning: `X.thm_no_doc2'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem thm_no_doc2' : True := .intro + +end X + +/-- +warning: `thm_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +theorem thm_no_doc' : True := .intro + +/-- +warning: `thm_with_attr_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +@[simp] +theorem thm_with_attr_no_doc' : True := .intro + +/-- +warning: `inst_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +instance inst_no_doc' : True := .intro + +/-- +warning: `abbrev_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +abbrev abbrev_no_doc' : True := .intro + +/-- +warning: `def_no_doc'` is missing a doc-string, please add one. +Declarations whose name ends with a `'` are expected to contain an explanation for the presence of a `'` in their doc-string. This may consist of discussion of the difference relative to the unprimed version, or an explanation as to why no better naming scheme is possible. +note: this linter can be disabled with `set_option linter.docPrime false` +-/ +#guard_msgs in +def def_no_doc' : True := .intro diff --git a/test/Lint.lean b/test/Lint.lean index c4f49cc99687e..25bf9c9147d13 100644 --- a/test/Lint.lean +++ b/test/Lint.lean @@ -294,70 +294,3 @@ note: this linter can be disabled with `set_option linter.style.longLine false` #guard_msgs in set_option linter.style.longLine true in #check " \" " - -/- -# Testing the `longFile` linter - -Things to note: -* `set_option linter.style.longFile 0` disables the linter, allowing us to set a value smaller than - `1500` without triggering the warning for setting a small value for the option; -* `guard_msgs ... in #exit` and `set_option ... in #exit` allow processing of the file *beyond* - `#exit`, since they wrap `#exit` inside an anonymous section, - making Lean active again *after* that anonymous section. - --/ - -section longFile - -/-- -warning: The default value of the `longFile` linter is 1500. -The current value of 1500 does not exceed the allowed bound. -Please, remove the `set_option linter.style.longFile 1500`. --/ -#guard_msgs in --- Do not allow setting a "small" `longFile` linter option -set_option linter.style.longFile 1500 - -/-- -warning: using 'exit' to interrupt Lean ---- -warning: The default value of the `longFile` linter is 1500. -This file is 331 lines long which does not exceed the allowed bound. -Please, remove the `set_option linter.style.longFile 1600`. --/ -#guard_msgs in --- Do not allow unnecessarily increasing the `longFile` linter option -set_option linter.style.longFile 1600 in -#exit - -/-- -warning: using 'exit' to interrupt Lean ---- -warning: This file is 346 lines long, but the limit is 10. - -You can extend the allowed length of the file using `set_option linter.style.longFile 1500`. -You can completely disable this linter by setting the length limit to `0`. --/ -#guard_msgs in --- First, we silence the linter, so that we can set a default value smaller than 1500. -set_option linter.style.longFile 0 in --- Next, we test that the `longFile` linter warns when a file exceeds the allowed value. -set_option linter.style.longFile 10 in -#exit - -/-- -warning: using 'exit' to interrupt Lean ---- -warning: The default value of the `longFile` linter is 1500. -This file is 361 lines long which does not exceed the allowed bound. -Please, remove the `set_option linter.style.longFile 1700`. --/ -#guard_msgs in --- First, we silence the linter, so that we can set a default value smaller than 1500. -set_option linter.style.longFile 0 in --- If we set the allowed bound for the `longFile` linter that is too large, --- the linter tells us to use a smaller bound. -set_option linter.style.longFile 1700 in -#exit - -end longFile diff --git a/test/LongFile.lean b/test/LongFile.lean new file mode 100644 index 0000000000000..faec16c404806 --- /dev/null +++ b/test/LongFile.lean @@ -0,0 +1,68 @@ +import Mathlib.Tactic.Linter.Lint + +/- +# Testing the `longFile` linter + +Things to note: +* `set_option linter.style.longFile 0` disables the linter, allowing us to set a value smaller than + `1500` without triggering the warning for setting a small value for the option; +* `guard_msgs ... in #exit` and `set_option ... in #exit` allow processing of the file *beyond* + `#exit`, since they wrap `#exit` inside an anonymous section, + making Lean active again *after* that anonymous section. + +-/ + +section longFile + +/-- +warning: The default value of the `longFile` linter is 1500. +The current value of 1500 does not exceed the allowed bound. +Please, remove the `set_option linter.style.longFile 1500`. +-/ +#guard_msgs in +-- Do not allow setting a "small" `longFile` linter option +set_option linter.style.longFile 1500 + +/-- +warning: using 'exit' to interrupt Lean +--- +warning: The default value of the `longFile` linter is 1500. +This file is 36 lines long which does not exceed the allowed bound. +Please, remove the `set_option linter.style.longFile 1600`. +-/ +#guard_msgs in +-- Do not allow unnecessarily increasing the `longFile` linter option +set_option linter.style.longFile 1600 in +#exit + +/-- +warning: using 'exit' to interrupt Lean +--- +warning: This file is 51 lines long, but the limit is 10. + +You can extend the allowed length of the file using `set_option linter.style.longFile 1500`. +You can completely disable this linter by setting the length limit to `0`. +-/ +#guard_msgs in +-- First, we silence the linter, so that we can set a default value smaller than 1500. +set_option linter.style.longFile 0 in +-- Next, we test that the `longFile` linter warns when a file exceeds the allowed value. +set_option linter.style.longFile 10 in +#exit + +/-- +warning: using 'exit' to interrupt Lean +--- +warning: The default value of the `longFile` linter is 1500. +This file is 66 lines long which does not exceed the allowed bound. +Please, remove the `set_option linter.style.longFile 1700`. +-/ +#guard_msgs in +-- First, we silence the linter, so that we can set a default value smaller than 1500. +set_option linter.style.longFile 0 in +-- If we set the allowed bound for the `longFile` linter that is too large, +-- the linter tells us to use a smaller bound. +set_option linter.style.longFile 1700 in +#exit + +end longFile diff --git a/test/MfldSetTac.lean b/test/MfldSetTac.lean index fd50fd05c2ca3..ad921934de097 100644 --- a/test/MfldSetTac.lean +++ b/test/MfldSetTac.lean @@ -47,7 +47,7 @@ test_sorry (e.toPartialEquiv.symm : β → α) = (e.symm : β → α) := test_sorry -structure ModelWithCorners (𝕜 E H : Type u) extends PartialEquiv H E := +structure ModelWithCorners (𝕜 E H : Type u) extends PartialEquiv H E where (source_eq : source = Set.univ) attribute [mfld_simps] ModelWithCorners.source_eq diff --git a/test/NthRewrite.lean b/test/NthRewrite.lean index 608d18fdb6bf8..287039007dce6 100644 --- a/test/NthRewrite.lean +++ b/test/NthRewrite.lean @@ -14,7 +14,7 @@ example [AddZeroClass G] {a : G} (h : a = a): a = (a + 0) := by example [AddZeroClass G] {a : G} : a + a = a + (a + 0) := by nth_rw 2 [← add_zero a] -structure F := +structure F where (a : ℕ) (v : Vector ℕ a) (p : v.val = []) @@ -22,7 +22,7 @@ structure F := example (f : F) : f.v.val = [] := by nth_rw 1 [f.p] -structure Cat := +structure Cat where (O : Type) (H : O → O → Type) (i : (o : O) → H o o) diff --git a/test/PPRoundtrip.lean b/test/PPRoundtrip.lean new file mode 100644 index 0000000000000..752a26277923b --- /dev/null +++ b/test/PPRoundtrip.lean @@ -0,0 +1,66 @@ +import Mathlib.Tactic.Linter.PPRoundtrip + +/-- +info: "a a" +--- +warning: source context +'al " a ' +'al " a a\n' +pretty-printed context +note: this linter can be disabled with `set_option linter.ppRoundtrip false` +-/ +#guard_msgs in +set_option linter.ppRoundtrip true in +#eval " a a\n " |>.trim + +/-- +warning: source context +'rd ¬ fa' +'rd ¬false' +pretty-printed context +note: this linter can be disabled with `set_option linter.ppRoundtrip false` +-/ +#guard_msgs in +set_option linter.ppRoundtrip true in +#guard ¬ false + +/-- +warning: source context +'le {a: Nat' +'le {a : Na' +pretty-printed context +note: this linter can be disabled with `set_option linter.ppRoundtrip false` +-/ +#guard_msgs in +set_option linter.ppRoundtrip true in +variable {a: Nat} + +/-- +warning: source context +' {a :Nat}' +' {a : Nat}' +pretty-printed context +note: this linter can be disabled with `set_option linter.ppRoundtrip false` +-/ +#guard_msgs in +set_option linter.ppRoundtrip true in +variable {a :Nat} + +/-- +info: (fun x1 x2 => x1 + x2) 0 1 : Nat +--- +warning: source context +'k (·+·) ' +'k (· + ·' +pretty-printed context +note: this linter can be disabled with `set_option linter.ppRoundtrip false` +-/ +#guard_msgs in +set_option linter.ppRoundtrip true in +#check (·+·) 0 1 + +#guard_msgs in +set_option linter.ppRoundtrip true in +-- check that trailing comments do not trigger the linter +example : 0 = 0 := by + rw [] -- this goal is closed by the `rfl` implied by `rw` diff --git a/test/Simps.lean b/test/Simps.lean index 4fb569642e899..cb6c499476837 100644 --- a/test/Simps.lean +++ b/test/Simps.lean @@ -91,7 +91,7 @@ initialize_simps_projections Something universe v u w -structure Equiv' (α : Sort _) (β : Sort _) := +structure Equiv' (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) (left_inv : invFun.LeftInverse toFun) @@ -101,7 +101,7 @@ infix:25 (priority := default+1) " ≃ " => Equiv' /- Since `prod` and `PProd` are a special case for `@[simps]`, we define a new structure to test the basic functionality.-/ -structure MyProd (α β : Type _) := (fst : α) (snd : β) +structure MyProd (α β : Type _) where (fst : α) (snd : β) def MyProd.map {α α' β β'} (f : α → α') (g : β → β') (x : MyProd α β) : MyProd α' β' := ⟨f x.1, g x.2⟩ @@ -262,7 +262,7 @@ run_cmd liftTermElabM <| do guard <| env.find? `rflWithData'_toEquiv_toFun |>.isNone guard <| env.find? `test_sneaky_extra |>.isNone -structure PartiallyAppliedStr := +structure PartiallyAppliedStr where (data : ℕ → MyProd ℕ ℕ) /- if we have a partially applied constructor, we treat it as if it were eta-expanded -/ @@ -279,7 +279,7 @@ run_cmd liftTermElabM <| do guard <| simpsAttr.getParam? env `partially_applied_term == #[`partially_applied_term_data_fst, `partially_applied_term_data_snd] -structure VeryPartiallyAppliedStr := +structure VeryPartiallyAppliedStr where (data : ∀β, ℕ → β → MyProd ℕ β) /- if we have a partially applied constructor, we treat it as if it were eta-expanded. @@ -424,12 +424,12 @@ run_cmd liftTermElabM <| do guard <| env.find? `pprodEquivProd22_invFun_snd |>.isSome /- Tests with universe levels -/ -class has_hom (obj : Type u) : Type (max u (v+1)) := +class has_hom (obj : Type u) : Type (max u (v+1)) where (hom : obj → obj → Type v) infixr:10 " ⟶ " => has_hom.hom -- type as \h -class CategoryStruct (obj : Type u) extends has_hom.{v} obj : Type (max u (v+1)) := +class CategoryStruct (obj : Type u) extends has_hom.{v} obj : Type (max u (v+1)) where (id : ∀ X : obj, hom X X) (comp : ∀ {X Y Z : obj}, (X ⟶ Y) → (Y ⟶ Z) → (X ⟶ Z)) @@ -450,7 +450,7 @@ example (X Y Z : Type u) (f : X ⟶ Y) (g : Y ⟶ Z) {k : X → Z} (h : ∀ x, g namespace coercing -structure FooStr := +structure FooStr where (c : Type) (x : c) @@ -462,7 +462,7 @@ instance : CoeSort FooStr Type := ⟨FooStr.c⟩ example {x : Type} (h : ℕ = x) : foo = x := by simp only [foo_c]; rw [h] example {x : ℕ} (h : (3 : ℕ) = x) : foo.x = x := by simp only [foo_x]; rw [h] -structure VooStr (n : ℕ) := +structure VooStr (n : ℕ) where (c : Type) (x : c) @@ -474,7 +474,7 @@ instance (n : ℕ) : CoeSort (VooStr n) Type := ⟨VooStr.c⟩ example {x : Type} (h : ℕ = x) : voo = x := by simp only [voo_c]; rw [h] example {x : ℕ} (h : (3 : ℕ) = x) : voo.x = x := by simp only [voo_x]; rw [h] -structure Equiv2 (α : Sort _) (β : Sort _) := +structure Equiv2 (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) (left_inv : invFun.LeftInverse toFun) @@ -515,7 +515,7 @@ class Semigroup (G : Type u) extends Mul G where example {α β} [Semigroup α] [Semigroup β] (x y : α × β) : x * y = (x.1 * y.1, x.2 * y.2) := by simp example {α β} [Semigroup α] [Semigroup β] (x y : α × β) : (x * y).1 = x.1 * y.1 := by simp -structure BSemigroup := +structure BSemigroup where (G : Type _) (op : G → G → G) -- (infix:60 " * " => op) -- this seems to be removed @@ -535,8 +535,8 @@ protected def prod (G H : BSemigroup) : BSemigroup := end BSemigroup -class ExtendingStuff (G : Type u) extends Mul G, Zero G, Neg G, HasSubset G := - (new_axiom : ∀ x : G, x * - 0 ⊆ - x) +class ExtendingStuff (G : Type u) extends Mul G, Zero G, Neg G, HasSubset G where + new_axiom : ∀ x : G, x * - 0 ⊆ - x @[simps] def bar : ExtendingStuff ℕ := { mul := (·*·) @@ -550,8 +550,8 @@ attribute [local instance] bar example (x : ℕ) : x * - 0 ⊆ - x := by simp end -class new_ExtendingStuff (G : Type u) extends Mul G, Zero G, Neg G, HasSubset G := - (new_axiom : ∀ x : G, x * - 0 ⊆ - x) +class new_ExtendingStuff (G : Type u) extends Mul G, Zero G, Neg G, HasSubset G where + new_axiom : ∀ x : G, x * - 0 ⊆ - x @[simps] def new_bar : new_ExtendingStuff ℕ := { mul := (·*·) @@ -570,7 +570,7 @@ end coercing namespace ManualCoercion -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -598,7 +598,7 @@ end ManualCoercion namespace FaultyManualCoercion -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -622,7 +622,7 @@ namespace ManualInitialize /- defining a manual coercion. -/ variable {α β γ : Sort _} -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -654,7 +654,7 @@ namespace FaultyUniverses variable {α β γ : Sort _} -structure Equiv (α : Sort u) (β : Sort v) := +structure Equiv (α : Sort u) (β : Sort v) where (toFun : α → β) (invFun : β → α) @@ -683,7 +683,7 @@ namespace ManualUniverses variable {α β γ : Sort _} -structure Equiv (α : Sort u) (β : Sort v) := +structure Equiv (α : Sort u) (β : Sort v) where (toFun : α → β) (invFun : β → α) @@ -704,7 +704,7 @@ end ManualUniverses namespace ManualProjectionNames -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -744,7 +744,7 @@ end ManualProjectionNames namespace PrefixProjectionNames -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -791,7 +791,7 @@ end PrefixProjectionNames -- test transparency setting -structure SetPlus (α : Type) := +structure SetPlus (α : Type) where (s : Set α) (x : α) (h : x ∈ s) @@ -818,7 +818,7 @@ example {x : Set ℕ} (h : Set.univ = x) : Nat.SetPlus3.s = x := by namespace NestedNonFullyApplied -structure Equiv (α : Sort _) (β : Sort _) := +structure Equiv (α : Sort _) (β : Sort _) where (toFun : α → β) (invFun : β → α) @@ -854,19 +854,19 @@ example (e : α ≃ β) {x : β → α} (h : e.invFun = x) : (Equiv.symm2.invFun end NestedNonFullyApplied -- test that type classes which are props work -class PropClass (n : ℕ) : Prop := - (has_true : True) +class PropClass (n : ℕ) : Prop where + has_true : True instance has_PropClass (n : ℕ) : PropClass n := ⟨trivial⟩ -structure NeedsPropClass (n : ℕ) [PropClass n] := +structure NeedsPropClass (n : ℕ) [PropClass n] where (t : True) @[simps] def test_PropClass : NeedsPropClass 1 := { t := trivial } /- check that when the coercion is given in eta-expanded form, we can also find the coercion. -/ -structure AlgHom (R A B : Type _) := +structure AlgHom (R A B : Type _) where (toFun : A → B) instance (R A B : Type _) : CoeFun (AlgHom R A B) (fun _ ↦ A → B) := ⟨fun f ↦ f.toFun⟩ @@ -931,7 +931,7 @@ section attribute [local simp] Nat.add -structure MyType := +structure MyType where (A : Type) @[simps (config := {simpRhs := true})] def myTypeDef : MyType := @@ -972,7 +972,7 @@ instance {α β} : CoeFun (α ≃ β) (fun _ ↦ α → β) := ⟨Equiv'.toFun @[simps] protected def Equiv'.symm {α β} (f : α ≃ β) : β ≃ α := ⟨f.invFun, f, f.right_inv, f.left_inv⟩ -structure DecoratedEquiv (α : Sort _) (β : Sort _) extends Equiv' α β := +structure DecoratedEquiv (α : Sort _) (β : Sort _) extends Equiv' α β where (P_toFun : Function.Injective toFun ) (P_invFun : Function.Injective invFun) @@ -1022,7 +1022,7 @@ example {α : Type} (x z : α) (h : x = z) : foo2 α x = z := by guard_target = x = z rw [h] -structure FurtherDecoratedEquiv (α : Sort _) (β : Sort _) extends DecoratedEquiv α β := +structure FurtherDecoratedEquiv (α : Sort _) (β : Sort _) extends DecoratedEquiv α β where (Q_toFun : Function.Surjective toFun ) (Q_invFun : Function.Surjective invFun ) @@ -1097,11 +1097,11 @@ def fffoo2 (α : Type) : OneMore α α := fffoo α /- test the case where a projection takes additional arguments. -/ variable {ι : Type _} [DecidableEq ι] (A : ι → Type _) -structure ZeroHom (M N : Type _) [Zero M] [Zero N] := +structure ZeroHom (M N : Type _) [Zero M] [Zero N] where (toFun : M → N) (map_zero' : toFun 0 = 0) -structure AddHom (M N : Type _) [Add M] [Add N] := +structure AddHom (M N : Type _) [Add M] [Add N] where (toFun : M → N) (map_add' : ∀ x y, toFun (x + y) = toFun x + toFun y) @@ -1112,7 +1112,7 @@ infixr:25 " →+ " => AddMonoidHom instance (M N : Type _) [AddMonoid M] [AddMonoid N] : CoeFun (M →+ N) (fun _ ↦ M → N) := ⟨(·.toFun)⟩ -class AddHomPlus [Add ι] [∀ i, AddCommMonoid (A i)] := +class AddHomPlus [Add ι] [∀ i, AddCommMonoid (A i)] where (myMul {i} : A i →+ A i) def AddHomPlus.Simps.apply [Add ι] [∀ i, AddCommMonoid (A i)] [AddHomPlus A] {i : ι} (x : A i) : @@ -1121,7 +1121,7 @@ def AddHomPlus.Simps.apply [Add ι] [∀ i, AddCommMonoid (A i)] [AddHomPlus A] initialize_simps_projections AddHomPlus (myMul_toFun → apply, -myMul) -class AddHomPlus2 [Add ι] := +class AddHomPlus2 [Add ι] where (myMul {i j} : A i ≃ (A j ≃ A (i + j))) def AddHomPlus2.Simps.mul [Add ι] [AddHomPlus2 A] {i j : ι} (x : A i) (y : A j) : A (i + j) := @@ -1153,7 +1153,7 @@ end comp_projs section /-! Check that the tactic also works if the elaborated type of `type` reduces to `Sort _`, but is not `Sort _` itself. -/ -structure MyFunctor (C D : Type _) := +structure MyFunctor (C D : Type _) where (obj : C → D) local infixr:26 " ⥤ " => MyFunctor diff --git a/test/Traversable.lean b/test/Traversable.lean index 136433f0ae4ea..ae7c2e2279e61 100644 --- a/test/Traversable.lean +++ b/test/Traversable.lean @@ -34,7 +34,7 @@ inductive RecData (α : Type u) : Type u #guard_msgs (drop info) in #synth LawfulTraversable RecData -unsafe structure MetaStruct (α : Type u) : Type u := +unsafe structure MetaStruct (α : Type u) : Type u where x : α y : ℤ z : List α diff --git a/test/ValuedCSP.lean b/test/ValuedCSP.lean index f60e3aed3e421..48b89612eacdc 100644 --- a/test/ValuedCSP.lean +++ b/test/ValuedCSP.lean @@ -40,6 +40,8 @@ private def exampleFiniteValuedInstance : exampleFiniteValuedCSP.Instance (Fin 2 example : exampleFiniteValuedInstance.IsOptimumSolution ![(0 : ℚ), (0 : ℚ)] := by intro s convert_to 0 ≤ exampleFiniteValuedInstance.evalSolution s + · simp [exampleFiniteValuedInstance, ValuedCSP.Instance.evalSolution] + exact Rat.zero_add 0 rw [ValuedCSP.Instance.evalSolution, exampleFiniteValuedInstance] convert_to 0 ≤ |s 0| + |s 1| · simp [ValuedCSP.unaryTerm, ValuedCSP.Term.evalSolution, Function.OfArity.uncurry] diff --git a/test/aesop_cat.lean b/test/aesop_cat.lean index 7790b9c1b983c..549cd69b92adb 100644 --- a/test/aesop_cat.lean +++ b/test/aesop_cat.lean @@ -10,6 +10,8 @@ example : Foo where x := sorry /-- +error: could not synthesize default value for field 'w' of 'Foo' using tactics +--- error: tactic 'aesop' failed, failed to prove the goal after exhaustive search. Initial goal: ⊢ 35 = 37 diff --git a/test/algebraize.lean b/test/algebraize.lean new file mode 100644 index 0000000000000..7cebc3123da0a --- /dev/null +++ b/test/algebraize.lean @@ -0,0 +1,96 @@ +import Mathlib.Tactic.Algebraize + +section example_definitions + +/-- Test property for when `RingHom` and `Algebra` properties are definitionally the same, +see e.g. `RingHom.FiniteType` for a concrete example of this. -/ +class Algebra.testProperty1 (A B : Type*) [CommRing A] [CommRing B] [Algebra A B] : Prop where + out : ∀ x : A, algebraMap A B x = 0 + +/-- Test property for when `RingHom` and `Algebra` properties are definitionally the same, +see e.g. `RingHom.FiniteType` for a concrete example of this. -/ +@[algebraize] +def RingHom.testProperty1 {A B : Type*} [CommRing A] [CommRing B] (f : A →+* B) : Prop := + @Algebra.testProperty1 A B _ _ f.toAlgebra + +/-- Test property for when the `RingHom` porperty corresponds to a `Module` property (that is +definitionally the same). See e.g. `Module.Finite` for a concrete example of this. -/ +class Module.testProperty2 (A M : Type*) [Semiring A] [AddCommMonoid M] [Module A M] : Prop where + out : ∀ x : A, ∀ M : M, x • M = 0 + +/-- Test property for when the `RingHom` porperty corresponds to a `Module` property (that is +definitionally the same). See e.g. `Module.Finite` for a concrete example of this. -/ +@[algebraize Module.testProperty2] +def RingHom.testProperty2 {A B : Type*} [CommRing A] [CommRing B] (f : A →+* B) : Prop := + letI : Algebra A B := f.toAlgebra + Module.testProperty2 A B + +/-- Test property for when the `RingHom` porperty corresponds to a `Algebra` property that is not +definitionally the same, and needs to be created through a lemma. See e.g. `Algebra.IsIntegral` for +an example. -/ +class Algebra.testProperty3 (A B : Type*) [CommRing A] [CommRing B] [Algebra A B] : Prop where + out : Algebra.testProperty1 A B + +/- Test property for when the `RingHom` porperty corresponds to a `Algebra` property that is not +definitionally the same, and needs to be created through a lemma. See e.g. `Algebra.IsIntegral` for +an example. -/ +@[algebraize Algebra.testProperty3.mk] +def RingHom.testProperty3 {A B : Type*} [CommRing A] [CommRing B] (f : A →+* B) : Prop := + f.testProperty1 + +end example_definitions + +set_option tactic.hygienic false + +/-- Synthesize algebra instance from ring hom. -/ +example (A B : Type*) [CommRing A] [CommRing B] (f : A →+* B) : True := by + fail_if_success -- Check that this instance is not available by default + have h : Algebra A B := inferInstance + algebraize [f] + guard_hyp algInst := f.toAlgebra + trivial + +/-- Synthesize algebra instance from a composition -/ +example (A B C : Type*) [CommRing A] [CommRing B] [CommRing C] (f : A →+* B) (g : B →+* C) : + True := by + fail_if_success -- Check that this instance is not available by default + have h : Algebra A C := inferInstance + algebraize [g.comp f] + guard_hyp algInst := (g.comp f).toAlgebra + trivial + +/-- Synthesize algebra instance and scalar tower instance from a composition -/ +example (A B C : Type*) [CommRing A] [CommRing B] [CommRing C] (f : A →+* B) (g : B →+* C) : + True := by + fail_if_success -- Check that this instance is not available by default + have h : IsScalarTower A B C := inferInstance + algebraize [f, g, g.comp f] + guard_hyp scalarTowerInst := IsScalarTower.of_algebraMap_eq' rfl + trivial + +example (A B : Type*) [CommRing A] [CommRing B] (f : A →+* B) (hf : f.testProperty1) : True := by + algebraize [f] + guard_hyp algebraizeInst : Algebra.testProperty1 A B := hf + trivial + +example (A B : Type*) [CommRing A] [CommRing B] (f : A →+* B) (hf : f.testProperty2) : True := by + algebraize [f] + guard_hyp algebraizeInst : Module.testProperty2 A B := hf + trivial + +example (A B : Type*) [CommRing A] [CommRing B] (f : A →+* B) (hf : f.testProperty3) : True := by + algebraize [f] + guard_hyp algebraizeInst : Algebra.testProperty3 A B := ⟨hf⟩ + trivial + +/-- Synthesize from morphism property of a composition (and check that tower is also synthesized). -/ +example (A B C : Type*) [CommRing A] [CommRing B] [CommRing C] (f : A →+* B) (g : B →+* C) + (hfg : (g.comp f).testProperty1) : True := by + fail_if_success -- Check that this instance is not available by default + have h : Algebra.Flat A C := inferInstance + fail_if_success + have h : IsScalarTower A B C := inferInstance + algebraize [f, g, g.comp f] + guard_hyp algebraizeInst : Algebra.testProperty1 A C := hfg + guard_hyp scalarTowerInst := IsScalarTower.of_algebraMap_eq' rfl + trivial diff --git a/test/eval_elab.lean b/test/eval_elab.lean index 7e929bdda3698..da0e2ae6197d7 100644 --- a/test/eval_elab.lean +++ b/test/eval_elab.lean @@ -4,7 +4,7 @@ import Mathlib.Data.Finset.Sort #guard_expr eval% 2^10 =ₛ 1024 -#guard_expr (eval% 2^10 : Int) =ₛ .ofNat 1024 +#guard_expr (eval% 2^10 : Int) =ₛ (1024 : Int) -- https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/How.20to.20simplify.20this.20proof.20without.20using.20a.20have.20statement.3F/near/422294189 section from_zulip diff --git a/test/fun_prop_dev.lean b/test/fun_prop_dev.lean index f3f139b1913a3..f78abae43617a 100644 --- a/test/fun_prop_dev.lean +++ b/test/fun_prop_dev.lean @@ -107,10 +107,10 @@ structure LinHom (α β) where infixr:25 " -o " => LinHom instance : CoeFun (α ->> β) (fun _ => α → β) where - coe := fun f => f.toFun + coe f := f.toFun instance : FunLike (α -o β) α β where - coe := fun f => f.toFun + coe f := f.toFun coe_injective' := silentSorry #eval Lean.Elab.Command.liftTermElabM do diff --git a/test/interactiveUnfold.lean b/test/interactiveUnfold.lean index 7972cf5866271..b17d3daa3cae8 100644 --- a/test/interactiveUnfold.lean +++ b/test/interactiveUnfold.lean @@ -57,7 +57,8 @@ info: Unfolds for 5 / 3: info: Unfolds for 1 + 1: · Ordinal.type (Sum.Lex EmptyRelation EmptyRelation) · ⟦{ α := PUnit.{u_1 + 1} ⊕ PUnit.{u_1 + 1}, r := Sum.Lex EmptyRelation EmptyRelation, wo := ⋯ }⟧ -· Quot.mk Setoid.r { α := PUnit.{u_1 + 1} ⊕ PUnit.{u_1 + 1}, r := Sum.Lex EmptyRelation EmptyRelation, wo := ⋯ } +· Quot.mk ⇑Ordinal.isEquivalent + { α := PUnit.{u_1 + 1} ⊕ PUnit.{u_1 + 1}, r := Sum.Lex EmptyRelation EmptyRelation, wo := ⋯ } -/ #guard_msgs in #unfold? (1 : Ordinal) + 1 diff --git a/test/linear_combination.lean b/test/linear_combination.lean index ac2eaed2036b2..9f652a8186a63 100644 --- a/test/linear_combination.lean +++ b/test/linear_combination.lean @@ -229,6 +229,15 @@ example (x y : ℤ) (h1 : x * y + 2 * x = 1) (h2 : x = y) : x * y = -2 * y + 1 : /-! ### Cases that should fail -/ +/-- +error: ring failed, ring expressions not equal +a : ℤ +ha : a = 1 +⊢ -1 = 0 +-/ +#guard_msgs in +example (a : ℤ) (ha : a = 1) : a = 2 := by linear_combination ha + /-- error: ring failed, ring expressions not equal a : ℚ diff --git a/test/matrix.lean b/test/matrix.lean index 962e193b1ef97..522acbe923c7d 100644 --- a/test/matrix.lean +++ b/test/matrix.lean @@ -154,7 +154,7 @@ example {α : Type _} [CommRing α] {a b c d : α} : 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, + Finset.univ_unique, Fin.val_succ, Fin.val_eq_zero, zero_add, pow_one, cons_val_succ, neg_mul, Fin.succ_succAbove_zero, Finset.sum_const, Finset.card_singleton, smul_neg, one_smul] ring @@ -167,7 +167,7 @@ example {α : Type _} [CommRing α] {a b c d e f g h i : α} : 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, + Fin.zero_succAbove, Finset.univ_unique, Fin.val_succ, Fin.val_eq_zero, 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_two, Even.neg_pow, one_pow, Finset.sum_const, Finset.card_singleton, one_smul] diff --git a/test/measurability.lean b/test/measurability.lean index 2ebf1a799ee68..d373a1d2d8576 100644 --- a/test/measurability.lean +++ b/test/measurability.lean @@ -82,7 +82,7 @@ example [Div β] [MeasurableDiv₂ β] (hf : Measurable f) (hg : Measurable g) example [AddCommMonoid β] [MeasurableAdd₂ β] {s : Finset ℕ} {F : ℕ → α → β} (hF : ∀ i, Measurable (F i)) : Measurable (∑ i ∈ s, (fun x => F (i+1) x + F i x)) := by - measurability + fun_prop example [AddCommMonoid β] [MeasurableAdd₂ β] {s : Finset ℕ} {F : ℕ → α → β} (hF : ∀ i, AEMeasurable (F i) μ) : AEMeasurable (∑ i ∈ s, (fun x => F (i+1) x + F i x)) μ := by diff --git a/test/module.lean b/test/module.lean new file mode 100644 index 0000000000000..ee59dd02d0d9f --- /dev/null +++ b/test/module.lean @@ -0,0 +1,308 @@ +/- +Copyright (c) 2024 Heather Macbeth. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Heather Macbeth +-/ +import Mathlib.Tactic.FieldSimp +import Mathlib.Tactic.LinearCombination +import Mathlib.Tactic.Module +import Mathlib.Tactic.NoncommRing +import Mathlib.Tactic.Positivity + +/-! # Tests for the module-normalization tactic -/ + +open Mathlib.Tactic.LinearCombination + +variable {V : Type*} {K : Type*} {t u v w x y z : V} {a b c d e f μ ν ρ : K} + +/-! ### `ℕ` (most tests copied from the `abel` tactic) -/ + +section Nat +variable [AddCommMonoid V] + +example : x + (y + x) = x + x + y := by module +example : (3 : ℕ) • x = x + (2 : ℕ) • x := by module +example : 0 + x = x := by module +example (n : ℕ) : n • x = n • x := by module +example (n : ℕ) : 0 + n • x = n • x := by module +example : x + (y + (x + (z + (x + (u + (x + v)))))) = v + u + z + y + 4 • x := by module +example : x + y = y + x := by module +example : x + 2 • x = 2 • x + x := by module + +example : x + (y + x) = x + x + y ∨ False := by + left + module + +/-- +error: unsolved goals +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 1 + +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 2 * 1 +-/ +#guard_msgs in +example : x + y = x + 2 • y := by match_scalars + +/-- +error: ring failed, ring expressions not equal +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommMonoid V +⊢ 1 = 2 +-/ +#guard_msgs in +example : x + y = x + 2 • y := by module + +/-- error: goal x ≠ y is not an equality -/ +#guard_msgs in +example : x ≠ y := by module + +end Nat + +/-! ### `ℤ` (most tests copied from the `abel` tactic) -/ + +variable [AddCommGroup V] + +example : (x + y) - ((y + x) + x) = -x := by module +example : x - 0 = x := by module +example : (3 : ℤ) • x = x + (2 : ℤ) • x := by module +example : x - 2 • y = x - 2 • y := by module +example : (x + y) - ((y + x) + x) = -x := by module +example : x + y + (z + w - x) = y + z + w := by module +example : x + y + z + (z - x - x) = (-1) • x + y + 2 • z := by module +example : -x + x = 0 := by module +example : x - (0 - 0) = x := by module +example : x + (y - x) = y := by module +example : -y + (z - x) = z - y - x := by module + +example : x + y = y + x ∧ (↑((1:ℕ) + 1) : ℚ) = 2 := by + constructor + module -- do not focus this tactic: the double goal is the point of the test + guard_target =ₐ (↑((1:ℕ) + 1) : ℚ) = 2 + norm_cast + +-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Interaction.20of.20abel.20with.20casting/near/319895001 +example : True := by + have : ∀ (p q r s : V), s + p - q = s - r - (q - r - p) := by + intro p q r s + module + trivial + +example : True := by + have : ∀ (p q r s : V), s + p - q = s - r - (q - r - p) := by + intro p q r s + match_scalars + · decide + · decide + · decide + · decide + trivial + +-- https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Interaction.20of.20abel.20with.20casting/near/319897374 +example : y = x + z - (x - y + z) := by + have : True := trivial + module + +example : y = x + z - (x - y + z) := by + have : True := trivial + match_scalars <;> decide + +/-- +error: unsolved goals +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝ : AddCommGroup V +⊢ -1 + 1 = 0 +-/ +#guard_msgs in +example : -x + x = 0 := by + match_scalars + +/-! ### Commutative ring -/ + +section CommRing +variable [CommRing K] [Module K V] + +example : a • x + b • x = (a + b) • x := by module +example : a • x - b • x = (a - b) • x := by module +example : a • x - b • y = a • x + (-b) • y := by module +example : 2 • a • x = a • 2 • x := by module +example : a • x - b • y = a • x + (-b) • y := by module +example : (μ - ν) • a • x = (a • μ • x + b • ν • y) - ν • (a • x + b • y) := by module +example : (μ - ν) • b • y = μ • (a • x + b • y) - (a • μ • x + b • ν • y) := by module + +-- from https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/smul.20diamond/near/457163013 +example : (4 : ℤ) • v = (4 : K) • v := by module +example : (4 : ℕ) • v = (4 : K) • v := by module + +-- from https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/linear_combination.20for.20groups/near/437042918 +example : (1 + a ^ 2) • (v + w) - a • (a • v - w) = v + (1 + a + a ^ 2) • w := by module + +example (h : a = b) : a • x = b • x := by + match_scalars + linear_combination h + +/- `linear_combination` does not currently handle `•`. The following mimics what should eventually +be performed by a `linear_combination` call, with exact syntax TBD -- maybe +`linear_combination (norm := module) h • x` or `module_combination h • x`. -/ +example (h : a = b) : a • x = b • x := by + apply eq_of_add (congr($h • x):) + module + +example (h : a ^ 2 + b ^ 2 = 1) : a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + match_scalars + · linear_combination h + · ring + +example (h : a ^ 2 + b ^ 2 = 1) : a • (a • x - b • y) + (b • a • y + b • b • x) = x := by + -- `linear_combination (norm := module) h • x` + apply eq_of_add (congr($h • x):) + module + +example (h1 : a • x + b • y = 0) (h2 : a • μ • x + b • ν • y = 0) : + (μ - ν) • a • x = 0 ∧ (μ - ν) • b • y = 0 := by + constructor + · -- `linear_combination (norm := module) h2 - ν • h1` + apply eq_of_add (congr($h2 - ν • $h1):) + module + · -- `linear_combination (norm := module) μ • h1 + h2` + apply eq_of_add (congr(μ • $h1 - $h2):) + module + +example (h1 : 0 • z + a • x + b • y = 0) (h2 : 0 • ρ • z + a • μ • x + b • ν • y = 0) : + (μ - ν) • a • x = 0 := by + -- `linear_combination (norm := module) h2 - ν • h1` + apply eq_of_add (congr($h2 - ν • $h1):) + module + +example + (h1 : a • x + b • y + c • z = 0) + (h2 : a • μ • x + b • ν • y + c • ρ • z = 0) + (h3 : a • μ • μ • x + b • ν • ν • y + c • ρ • ρ • z = 0) : + (μ - ν) • (μ - ρ) • a • x = 0 ∧ (μ - ν) • (ν - ρ) • b • y = 0 + ∧ (μ - ρ) • (ν - ρ) • c • z = 0 := by + refine ⟨?_, ?_, ?_⟩ + · -- `linear_combination (norm := module) h3 - (ν + ρ) • h2 + ν • ρ • h1` + apply eq_of_add (congr($h3 - (ν + ρ) • $h2 + ν • ρ • $h1):) + module + · -- `linear_combination (norm := module) - h3 + (μ + ρ) • h2 - μ • ρ • h1` + apply eq_of_add (congr(- $h3 + (μ + ρ) • $h2 - μ • ρ • $h1):) + module + · -- `linear_combination (norm := module) h3 - (μ + ν) • h2 + μ • ν • h1` + apply eq_of_add (congr($h3 - (μ + ν) • $h2 + μ • ν • $h1):) + module + +/-- +error: ring failed, ring expressions not equal +V : Type u_1 +K : Type u_2 +t u v w x y z : V +a b c d e f μ ν ρ : K +inst✝² : AddCommGroup V +inst✝¹ : CommRing K +inst✝ : Module K V +⊢ a * 2 = 2 +-/ +#guard_msgs in +example : 2 • a • x = 2 • x := by module + +end CommRing + +/-! ### (Noncommutative) ring -/ + +section Ring +variable [Ring K] [Module K V] + +example : a • x + b • x = (b + a) • x := by + match_scalars + noncomm_ring + +example : 2 • a • x = a • (2:ℤ) • x := by + match_scalars + noncomm_ring + +example (h : a = b) : a • x = b • x := by + match_scalars + simp [h] + +example : (a - b) • a • x + b • b • x = a • a • x + b • (-a + b) • x := by + match_scalars + noncomm_ring + +end Ring + +/-! ### Characteristic-zero field -/ + +section CharZeroField +variable [Field K] [CharZero K] [Module K V] + +example : (2:K)⁻¹ • x + (3:K)⁻¹ • x + (6:K)⁻¹ • x = x := by module + +example (h₁ : t - u = -(v - w)) (h₂ : t + u = v + w) : t = w := by + -- `linear_combination (norm := module) 2⁻¹ • h₁ + 2⁻¹ • h₂` + apply eq_of_add (congr((2:K)⁻¹ • $h₁ + (2:K)⁻¹ • $h₂):) + module + +end CharZeroField + +/-! ### Linearly ordered field -/ + +section LinearOrderedField +variable [LinearOrderedField K] [Module K V] + +example (ha : 0 ≤ a) (hb : 0 < b) : + x = (a / (a + b)) • y + (b / (a + b)) • (x + (a / b) • (x - y)) := by + match_scalars + · field_simp + ring + · field_simp + ring + +-- From Analysis.Convex.StoneSeparation +example (hab : 0 < a * b + c * d) : + (a * b / (a * b + c * d) * e) • u + (c * d / (a * b + c * d) * f) • v + + ((a * b / (a * b + c * d)) • d • x + (c * d / (a * b + c * d)) • b • y) = + (a * b + c * d)⁻¹ • ((a * b * e) • u + ((c * d * f) • v + + ((a * b) • d • x + (c * d) • b • y))) := by + match_scalars + · field_simp + · field_simp + · field_simp + · field_simp + +example (h₁ : 1 = a ^ 2 + b ^ 2) (h₂ : 1 - a ≠ 0) : + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • (4:K) • ((2 / (1 - a)) • y) + + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • ((2 / (1 - a)) ^ 2 * b ^ 2 - 4) • x + = a • x + y := by + -- `linear_combination (norm := skip) (h₁ * (b ^ 2 + (1 - a) ^ 2)⁻¹) • (y + (a - 1) • x)` + apply eq_of_add (congr(($h₁ * (b ^ 2 + (1 - a) ^ 2)⁻¹) • (y + (a - 1) • x)):) + match_scalars + · field_simp + ring + · field_simp + ring + +example (h₁ : 1 = a ^ 2 + b ^ 2) (h₂ : 1 - a ≠ 0) : + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • (4:K) • ((2 / (1 - a)) • y) + + ((2 / (1 - a)) ^ 2 * b ^ 2 + 4)⁻¹ • ((2 / (1 - a)) ^ 2 * b ^ 2 - 4) • x + = a • x + y := by + match_scalars + · field_simp + linear_combination 4 * (1 - a) * h₁ + · field_simp + linear_combination 4 * (a - 1) ^ 3 * h₁ + +end LinearOrderedField diff --git a/test/positivity.lean b/test/positivity.lean index d75fda862bd69..fc773c8abd962 100644 --- a/test/positivity.lean +++ b/test/positivity.lean @@ -23,6 +23,9 @@ example : 0 ≤ 3 := by positivity example : 0 < 3 := by positivity +example : (0 : ℝ≥0∞) < 1 := by positivity +example : (0 : ℝ≥0∞) < 2 := by positivity + /- ## Goals working directly from a hypothesis -/ -- set_option trace.Meta.debug true -- sudo set_option trace.Tactic.positivity true diff --git a/test/ring_compare.lean b/test/ring_compare.lean new file mode 100644 index 0000000000000..3e282d9fbfe30 --- /dev/null +++ b/test/ring_compare.lean @@ -0,0 +1,114 @@ +import Mathlib.Tactic.NormNum.OfScientific +import Mathlib.Tactic.Ring.Compare +import Mathlib.Tactic.Ring.RingNF + +open Lean Elab Tactic + +elab "ring_le" : tactic => liftMetaFinishingTactic Mathlib.Tactic.Ring.proveLE +elab "ring_lt" : tactic => liftMetaFinishingTactic Mathlib.Tactic.Ring.proveLT + +section Nat +variable {x y : ℕ} + +example : 3 ≤ (3:ℕ) := by ring_le +example : 1 ≤ (3:ℕ) := by ring_le +example : 0 ≤ (3:ℕ) + 1 := by ring_le +example : x ≤ x + 3 := by ring_le +example : x ≤ 1 + x := by ring_le +example : x + y + 1 ≤ y + x + 3 := by ring_le +example : x + y ≤ y + x + 3 := by ring_le +example : x + y + 1 ≤ y + 4 + x := by ring_le + +example : 1 < (3:ℕ) := by ring_lt +example : 0 < (3:ℕ) + 1 := by ring_lt +example : x < x + 3 := by ring_lt +example : x < 1 + x := by ring_lt +example : x + y + 1 < y + x + 3 := by ring_lt +example : x + y < y + x + 3 := by ring_lt +example : x + y + 1 < y + 4 + x := by ring_lt + +end Nat + +section LinearOrderedField +variable {K : Type*} [LinearOrderedField K] {x y : K} + +example : (0:K) ≤ 0 := by ring_le +example : 3 ≤ (3:K) := by ring_le +example : 1 ≤ (3:K) := by ring_le +example : -1 ≤ (3:K) := by ring_le +example : 1.5 ≤ (3:K) := by ring_le +example : 0 ≤ x + 3 - x := by ring_le +example : -1 ≤ x - x := by ring_le +example : x + y + 1 ≤ y + x + 3 := by ring_le +example : x + y + 1 ≤ y + x + 1 := by ring_le +example : x + y ≤ y + x + 3 := by ring_le +example : x + y - 3 ≤ y + x := by ring_le +example : x + y - x + 1 ≤ y + (4:K) := by ring_le + +example : 1 < (3:K) := by ring_lt +example : -1 < (3:K) := by ring_lt +example : 1.5 < (3:K) := by ring_lt +example : 0 < x + 3 - x := by ring_lt +example : -1 < x - x := by ring_lt +example : x + y + 1 < y + x + 3 := by ring_lt +example : x + y < y + x + 3 := by ring_lt +example : x + y - 3 < y + x := by ring_lt +example : x + y - x + 1 < y + (4:K) := by ring_lt + +/- The speed of `Mathlib.Tactic.Ring.proveLE` is very sensitive to how much typeclass inference is +demanded by the lemmas it orchestrates. This example took 1112 heartbeats (and 40 ms on a good +laptop) on an implementation with "minimal" typeclasses everywhere, e.g. lots of +`CovariantClass`/`ContravariantClass`, and takes 662 heartbeats (28 ms on a good laptop) on the +implementation at the time of joining Mathlib (October 2024). -/ +set_option maxHeartbeats 750 in +example : x + y - x + 1 ≤ y + (4:K) := by ring_le + +/- The speed of `Mathlib.Tactic.Ring.proveLT` is very sensitive to how much typeclass inference is +demanded by the lemmas it orchestrates. This example took 1410 heartbeats (and 48 ms on a good +laptop) on an implementation with "minimal" typeclasses everywhere, e.g. lots of +`CovariantClass`/`ContravariantClass`, and takes 676 heartbeats (28 ms on a good laptop) on the +implementation at the time of joining Mathlib (October 2024). -/ +set_option maxHeartbeats 750 in +example : x + y - x + 1 < y + (4:K) := by ring_lt + +/-- +error: ring failed, ring expressions not equal up to an additive constant +K : Type u_1 +inst✝ : LinearOrderedField K +x y : K +⊢ 1 + x + y ≤ 3 + y +-/ +#guard_msgs in +example : x + y + 1 ≤ y + 3 := by ring_le + +/-- +error: comparison failed, LHS is larger +K : Type u_1 +inst✝ : LinearOrderedField K +x y : K +⊢ 4 + x + y ≤ 3 + x + y +-/ +#guard_msgs in +example : x + y + 4 ≤ y + x + 3 := by ring_le + +/-- +error: ring failed, ring expressions not equal up to an additive constant +K : Type u_1 +inst✝ : LinearOrderedField K +x y : K +⊢ 1 + x + y < 3 + y +-/ +#guard_msgs in +example : x + y + 1 < y + 3 := by ring_lt + +/-- +error: comparison failed, LHS is at least as large +K : Type u_1 +inst✝ : LinearOrderedField K +x y : K +⊢ 4 + x + y < 4 + x + y +-/ +#guard_msgs in +example : x + y + 4 < y + x + 4 := by ring_lt + +end LinearOrderedField diff --git a/test/says.lean b/test/says.lean index e2f9a3f834662..4315e51cb870d 100644 --- a/test/says.lean +++ b/test/says.lean @@ -101,7 +101,8 @@ def very_long_lemma_name_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa : Q → P := fun _ @[simp] def very_long_lemma_name_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb : Q := trivial /-- -info: Try this: aesop? says simp_all only [very_long_lemma_name_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, +info: Try this: aesop? says + simp_all only [very_long_lemma_name_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, very_long_lemma_name_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] -/ #guard_msgs in diff --git a/test/set_like.lean b/test/set_like.lean index a322a2c96e894..2847a594eb156 100644 --- a/test/set_like.lean +++ b/test/set_like.lean @@ -8,10 +8,10 @@ set_option autoImplicit true section Delab variable {M : Type u} [Monoid M] (S S' : Submonoid M) -/-- info: { x // x ∈ S } → { x // x ∈ S' } : Type u -/ +/-- info: ↥S → ↥S' : Type u -/ #guard_msgs in #check S → S' -/-- info: { x // x ∈ S } : Type u -/ +/-- info: ↥S : Type u -/ #guard_msgs in #check {x // x ∈ S} /-- info: { x // 1 * x ∈ S } : Type u -/ diff --git a/test/slow_simp.lean b/test/slow_simp.lean index fa6de3b23f5b9..651d0e10e6014 100644 --- a/test/slow_simp.lean +++ b/test/slow_simp.lean @@ -61,7 +61,7 @@ def PointedSpaceEquiv_inverse : Under (TopCat.of Unit) ⥤ PointedSpace where base := by have := f.w replace this := DFunLike.congr_fun this () - simp [- Under.w] at this + simp [-Under.w] at this simp exact this.symm } map_comp := by intros; simp_all; rfl -- This is the slow step. diff --git a/test/tactic_timeout.lean b/test/tactic_timeout.lean new file mode 100644 index 0000000000000..455b2ff5e2399 --- /dev/null +++ b/test/tactic_timeout.lean @@ -0,0 +1,98 @@ +import Mathlib.Tactic.Linarith + +/-! +# Test that tactics respond to a cancellation request +-/ + + +variable {α} + +open Lean Elab Tactic + +/-! versions of try/catch that catch `interrupted` too -/ +section catch_interrupted +attribute [-instance] + Lean.instMonadExceptOfExceptionCoreM Lean.Elab.Tactic.instMonadExceptExceptionTacticM + +def Meta.tryCatchAll (m : MetaM α) (h : Exception → MetaM α) : MetaM α := tryCatch m h +def Term.tryCatchAll (m : TermElabM α) (h : Exception → TermElabM α) : TermElabM α := tryCatch m h +def Tactic.tryCatchAll (x : TacticM α) (h : Exception → TacticM α) : TacticM α := do + let b ← saveState + try x catch ex => b.restore; h ex + +end catch_interrupted + +section test_infra + +def Tactic.withTimeout (ms : UInt32) (t : TacticM α) : TacticM (α ⊕ Nat) := do + let tk ← IO.CancelToken.new + withTheReader Core.Context (fun s => { s with cancelTk? := some tk }) do + let t0 ← IO.monoMsNow + let watchdog ← IO.asTask do + IO.sleep ms + tk.set + let r ← Tactic.tryCatchAll (.inl <$> t) + (fun e => do + IO.cancel watchdog + if !e.isInterrupt || !(← tk.isSet) then + throw e + else + let duration := (← IO.monoMsNow) - t0 + return .inr duration) + IO.cancel watchdog + return r + +/-- `with_timeout 100 => tac` allows `tac` only 100ms to run. -/ +elab "with_timeout " ms:num "=>" tac:tacticSeq : tactic => do + let ms := ms.getNat.toUInt32 + if let .inr _duration ← Tactic.withTimeout ms (evalTactic tac) then + throwError f!"Tactic took more than {ms}ms" + +set_option linter.unusedTactic false + +/-- error: Tactic took more than 500ms -/ +#guard_msgs in +example : True := by + with_timeout 500 => + sleep 1000 + trivial + +example: True := by + with_timeout 500 => + sleep 100 + trivial + +end test_infra + +/-- `check_timeouts 100 => tac` checks that `tac` never goes longer than `100ms` without checking +for cancellation. -/ +elab "check_timeouts " tol_ms:num "=>" tac:tacticSeq : tactic => do + let mut t := 0 + let tol_ms := tol_ms.getNat + repeat do + if let .inr duration ← Tactic.withTimeout t.toUInt32 (evalTactic tac) then + if duration > t + tol_ms then + logError f!"Tactic took much more than {t}ms ({duration}ms)" + trace[debug] "Tactic overran from {t}ms to {duration}ms" + else + break + t := t + tol_ms + +set_option maxHeartbeats 0 +set_option linter.unusedTactic false +set_option linter.unusedVariables false + +theorem linear_combination_with_10_terms + (a b c d e f g h i j : Int) + (h0 : -e + g + -h + i = 0) + (h1 : b + -d + -e + f + g + i = 0) + (h2 : -b + j = 0) + (h3 : c + d + -f + -i = 0) + (h4 : b + c + e + -g + -h + i + j = 0) + (h5 : -a + b + d + f + -h + -i = 0) + (h6 : a + d + e + -g + -h = 0) + (h7 : -a + d + -f + -h + j = 0) + (h8 : a + -d + e + f + g + h + -i + j = 0) + (h9 : -a + b + c + -e + -f + h + j = 0) : + -2*a + b + 2*c + d + -3*f + -g + 3*h + -3*i = 0 := by + check_timeouts 250 => nlinarith diff --git a/test/toAdditive.lean b/test/toAdditive.lean index cb1938438e035..bd2ad86c8e087 100644 --- a/test/toAdditive.lean +++ b/test/toAdditive.lean @@ -19,12 +19,12 @@ def foo0 {α} [Mul α] [One α] (x y : α) : α := x * y * 1 theorem bar0_works : bar0 3 4 = 7 := by decide -class my_has_pow (α : Type u) (β : Type v) := +class my_has_pow (α : Type u) (β : Type v) where (pow : α → β → α) instance : my_has_pow Nat Nat := ⟨fun a b => a ^ b⟩ -class my_has_scalar (M : Type u) (α : Type v) := +class my_has_scalar (M : Type u) (α : Type v) where (smul : M → α → α) instance : my_has_scalar Nat Nat := ⟨fun a b => a * b⟩